\subsection{darcs put} \begin{code} module Put ( put ) where import System ( ExitCode( ExitSuccess ), exitWith ) import Monad ( when ) import Directory ( createDirectory ) import IO ( isAlreadyExistsError ) import DarcsCommands ( DarcsCommand(..), nodefaults ) import DarcsArguments ( DarcsFlag( Quiet, Verbose ), applyas, match_one_context, fix_filepath, any_verbosity, pristine_tree, working_repo_dir, ssh_cm, ) import Repository ( patchSetToPatches ) import DarcsRepo ( read_repo, am_in_repo, absolute_dir, write_inventory ) import PatchBundle ( make_bundle ) import Match ( have_patchset_match, get_one_patchset ) import RepoPrefs ( write_default_prefs, get_preflist, set_defaultrepo ) import DarcsURL ( is_url, is_file, is_relative ) import DarcsUtils ( withCurrentDirectory, formatPath ) import Printer ( text, putDocLn, errorDoc ) import Pristine ( Pristine, createPristine, flagsToPristine, pristineToFlagString ) import SlurpDirectory ( empty_slurpy ) import External ( execSSH ) import RemoteApply ( remote_apply ) #include "impossible.h" \end{code} \begin{code} put_description :: String put_description = "Makes a copy of the repository" \end{code} \options{put} \haskell{put_help} \begin{code} put_help :: String put_help = "Put is the opposite of get. Put copies the content of the current \n" ++ "repository and puts it in a newly created repository.\n" \end{code} \begin{code} put ::DarcsCommand put = DarcsCommand {command_name = "put", command_help = put_help, command_description = put_description, command_extra_args = 1, command_extra_arg_help = [""], command_command = put_cmd, command_prereq = am_in_repo, command_get_arg_possibilities = get_preflist "repos", command_argdefaults = nodefaults, command_darcsoptions = [any_verbosity,working_repo_dir, match_one_context, applyas,pristine_tree, ssh_cm]} \end{code} \begin{code} put_cmd :: [DarcsFlag] -> [String] -> IO () put_cmd opts [unfixedrepodir] = let am_verbose = Verbose `elem` opts am_quiet = Quiet `elem` opts putVerbose s = when am_verbose $ putDocLn s putInfo s = when (not am_quiet) $ putDocLn s homedir = "." repodir = if is_relative unfixedrepodir then fix_filepath "" opts unfixedrepodir else unfixedrepodir in do -- Test to make sure we aren't trying to push to the current repo cur_absolute_repo_dir <- absolute_dir homedir req_absolute_repo_dir <- absolute_dir repodir when (cur_absolute_repo_dir == req_absolute_repo_dir) $ fail "Can't put to current repository!" when (is_url req_absolute_repo_dir) $ errorDoc (text "Can't put to a URL!") putVerbose $ text "Creating repository" if is_file req_absolute_repo_dir then do createDirectory req_absolute_repo_dir withCurrentDirectory req_absolute_repo_dir $ do createDirectory "_darcs" `catch` (\e-> if isAlreadyExistsError e then fail "Target repository has already been initialized. Use 'push' instead." else fail $ "Error creating directory " ++ formatPath "_darcs" ++ ".") createPristine $ flagsToPristine opts createDirectory "_darcs/patches" createDirectory "_darcs/prefs" write_default_prefs write_inventory "." [[]] else do -- is_ssh req_absolute_repo_dir remoteInit req_absolute_repo_dir $ flagsToPristine opts withCurrentDirectory cur_absolute_repo_dir $ do set_defaultrepo req_absolute_repo_dir opts patchset <- if have_patchset_match opts then get_one_patchset opts else read_repo "." let patches = patchSetToPatches patchset when (null patches) $ do putInfo $ text "No patches were selected to put. Nothing to be done." exitWith ExitSuccess out <- remote_apply opts req_absolute_repo_dir (make_bundle opts empty_slurpy [] patches) putInfo out put_cmd _ _ = impossible remoteInit :: FilePath -> Pristine -> IO () remoteInit repo pristine = do let pristineArg = pristineToFlagString pristine command = "mkdir -p '"++path++ "' && cd '"++path++ "' && darcs init "++pristineArg exitCode <- execSSH addr command when (exitCode /= ExitSuccess) $ fail "Couldn't initialize remote repository." where (addr,':':path) = break (==':') repo \end{code} \emph{WARNING:} Put is far less optimized than get, especially for local repositories. We recommend avoiding use of put except for small repositories. Put is used when you already have a repository and want to make a copy of it. A typical use-case is when you want to branch your project. Put works by first initializing a repository. If the new repository is not on the local file system then darcs will login to the remote host and run \verb!darcs init! there. After the new repository is created all selected patches will be pushed just as with the command \verb!push!. \begin{options} --apply-as \end{options} If you give the \verb!--apply-as! flag, darcs will use sudo to apply the changes as a different user. This can be useful if you want to set up a system where several users can modify the same repository, but you don't want to allow them full write access. This isn't secure against skilled malicious attackers, but at least can protect your repository from clumsy, inept or lazy users. \begin{options} --context, --tag, --to-patch, --to-match \end{options} If you want to put a specific version of a repository, you have a few options. You can either use the \verb!--tag!, \verb!--to-patch! or \verb!--to-match! options, or you can use the \verb!--context=FILENAME! option, which specifies a file containing a context generated with \verb!darcs changes --context!. This allows you (for example) to include in your compiled program an option to output the precise version of the repository from which it was generated, and then perhaps ask users to include this information in bug reports. Note that when specifying \verb!--to-patch! or \verb!--to-match!, you may get a version of your code that has never before been seen, if the patches have gotten themselves reordered. If you ever want to be able to precisely reproduce a given version, you need either to tag it or create a context file.