%  Copyright (C) 2002-2003 David Roundy
%
%  This program is free software; you can redistribute it and/or modify
%  it under the terms of the GNU General Public License as published by
%  the Free Software Foundation; either version 2, or (at your option)
%  any later version.
%
%  This program is distributed in the hope that it will be useful,
%  but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%  GNU General Public License for more details.
%
%  You should have received a copy of the GNU General Public License
%  along with this program; see the file COPYING.  If not, write to
%  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
%  Boston, MA 02110-1301, USA.

\subsection{darcs initialize}
\begin{code}
module Darcs.Commands.Init ( initialize, initialize_cmd ) where
import System.Directory ( createDirectory )
import System.IO.Error ( isAlreadyExistsError )

import Darcs.Commands ( DarcsCommand(..), nodefaults )
import Darcs.Arguments ( DarcsFlag, pristine_tree, working_repo_dir,
                        inventory_choices )

import Darcs.Patch.Set ( PatchSet )
import Darcs.Patch ( Patch )

import Darcs.Patch.Ordered ( RL(..) )
import Darcs.Repository.Prefs ( write_default_prefs )
import Darcs.Repository.Format ( create_repo_format, writeRepoFormat,
                                 RepoProperty ( HashedInventory ), format_has )
import Darcs.Repository.Pristine ( createPristine, flagsToPristine )
import Darcs.Lock ( writeBinFile )
import Darcs.Repository.DarcsRepo ( write_inventory )
import Darcs.Repository ( amNotInRepository )
\end{code}

\options{initialize}

\haskell{initialize_description}

\begin{code}
initialize_description :: String
initialize_description = "Initialize a new source tree as a darcs repository."
\end{code}
Call \verb|initialize| once for each project you work on. Run it from the top
level directory of the project, with the project files already there. 
\verb|initialize| will set up all the directories and files darcs needs in order to
start keeping track of revisions for your project.

\begin{code}
initialize_help :: String
initialize_help =
 "Call 'initialize' once for each project you work on. Run it from the top  \n"++
 "level directory of the project, with the project files already there.   \n"++
 "'initialize' will set up all the directories and files darcs needs in order to \n"++
 " start keeping track of revisions for your project.  \n"
\end{code}

\begin{code}
initialize :: DarcsCommand
initialize = DarcsCommand {command_name = "initialize",
                         command_help = initialize_help,
                         command_description = initialize_description,
                         command_extra_args = 0,
                         command_extra_arg_help = [],
                         command_prereq = amNotInRepository,
                         command_command = initialize_cmd,
                         command_get_arg_possibilities = return [],
                         command_argdefaults = nodefaults,
                         command_advanced_options = [],
                         command_basic_options = [pristine_tree, inventory_choices,
                                                  working_repo_dir]}
\end{code}

\verb|initialize| creates a single directory named \verb|_darcs|, with contents
for internal use. The one subdictory of interest to users is
\verb'_darcs/prefs', which will include an empty file \verb'_darcs/prefs/motd'
(see Section~\ref{motd}), as well as files named \verb'boring' and
\verb'binaries', which contain useful defaults as described in Sections
\ref{boring} \emph{et seq.}

\begin{options}
--old-fashioned-inventory
--hashed
--darcs-2
\end{options}

These options describe possible repository formats to use. 

\verb'old-fashioned-inventory' is the default. While it has minimal features, it is the best tested and the limitations
it does have are well known.

\verb'hashed' Overs several features while still be compatible with old-fashioned repos. The specific features are:

\begin{itemize}  

\item The hashed format allows for greater atomicity of operations. This makes for greater safety and simultaneously greater efficiency. These benefits, however, have not been fully realized in this release. For instance, with a hashed repository, there is no need for darcs push to require a repository lock, so you could record patches while waiting for a push to finish (for instance, if it's waiting on the test suite).

\item The \verb!_darcs/pristine! directory no longer holds the pristine
cache. This disallows certain hackish short-cuts, but also dramatically
reduces the danger of third-party programs (e.g. DreamWeaver) recursing
into the pristine cache and corrupting darcs repositories.

\item Darcs get is now much faster, and always operates in a "lazy"
fashion, meaning that patches are downloaded only when they are
needed. This gives us much of the benefits of --partial repositories,
without most of their disadvantages. This approach, however, does have
several new dangers. First, some operations may unexpectedly require the
download of large numbers of patches, which could be slow (but you could
always interrupt with \verb!^C!). Secondly, if the source repository disappears,
or you lose network connectivity, some operations may fail.

\item Darcs now supports caching of patches and file contents to reduce bandwidth and save disk space. It greatly speeds up a number of operations, and is essentially transparent. The only reason we don't enable it by default is because it creates a large directory in ~/.darcs/cache without the user's explicit consent.

\end{itemize}

\verb'darcs-2' Enables all available features, at the expense of still being experimental, and requiring that all repos for a project use the same format. In addition to the features of the \verb'hashed' format described above, the \verb'darcs-2' format also enables the following:

\begin{itemize}

\item It should no longer be possible to confuse darcs or freeze it indefinitely by merging conflicting changes. 

\item Identical primitive changes no longer conflict. This is a long-requested feature, and has far-reaching implications. 

\end{itemize}

\begin{options}
--no-pristine-tree
\end{options}
In order to save disk space, you can use \verb|initialize| with the
\verb|--no-pristine-tree| flag to create a repository with no pristine
tree.  Please see Section~\ref{disk-usage} for more information.

\begin{code}
initialize_cmd :: [DarcsFlag] -> [String] -> IO ()
initialize_cmd opts _ = do
    createDirectory "_darcs" `catch`
        (\e-> if isAlreadyExistsError e
              then fail "Tree has already been initialized!"
              else fail "Error creating directory `_darcs'.")
    createPristine $ flagsToPristine opts
    createDirectory "_darcs/patches"
    createDirectory "_darcs/prefs"
    write_default_prefs
    let rf = create_repo_format opts
    writeRepoFormat rf "_darcs/format"
    if format_has HashedInventory rf
        then writeBinFile "_darcs/hashed_inventory" ""
        else write_inventory "." (NilRL:<:NilRL :: PatchSet Patch) -- YUCK!
\end{code}

