% Copyright (C) 2002-2004 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 rollback} \begin{code} module Rollback ( rollback ) where import SignalHandler ( withSignalsBlocked ) import DarcsCommands ( DarcsCommand(..), nodefaults ) import DarcsArguments ( DarcsFlag, verbose, working_repo_dir, nocompress, match_one_nontag, umask_option, ) import Repository ( amInRepository, withRepoLock, read_pending, with_new_pending, applyToPristine, writePatch, updateInventory, ) import Patch ( join_patches, invert, patch2patchinfo, null_patch, ) import Depends ( is_tag ) import PatchInfo ( is_inverted ) import SelectChanges ( with_selected_patch_from_repo ) #include "impossible.h" \end{code} \begin{code} rollback_description :: String rollback_description = "Record an inverse patch without changing the working directory." \end{code} \options{rollback} \haskell{rollback_help} If you decide you didn't want to roll back a patch after all, you probably should use unrecord to undo the rollback, since like rollback, unrecord doesn't affect the working directory. \begin{code} rollback_help :: String rollback_help = "Rollback is used to undo the effects of a single patch without actually\n"++ "deleting that patch. Instead, it applies the inverse patch as a new patch.\n"++ "Unlike unpull and unrecord (which accomplish a similar goal) rollback is\n"++ "perfectly safe, since it leaves in the repository a record of the patch it\n"++ "is removing.\n" \end{code} \begin{code} rollback :: DarcsCommand rollback = DarcsCommand {command_name = "rollback", command_help = rollback_help, command_description = rollback_description, command_extra_args = 0, command_extra_arg_help = [], command_command = rollback_cmd, command_prereq = amInRepository, command_get_arg_possibilities = return [], command_argdefaults = nodefaults, command_darcsoptions = [match_one_nontag, nocompress,verbose, working_repo_dir, umask_option]} \end{code} \begin{code} rollback_cmd :: [DarcsFlag] -> [String] -> IO () rollback_cmd opts _ = withRepoLock opts $ \repository -> do mpend <- read_pending repository let pend = case mpend of Nothing -> null_patch Just p -> p with_selected_patch_from_repo "rollback" opts True $ \ (p, _) -> case patch2patchinfo (invert p) of Nothing -> impossible Just pinfo | is_tag pinfo -> fail "cannot roll back a 'tag' patch." Just pinfo | not (is_inverted pinfo) -> fail "cannot roll back a 'rollback' patch." Just pinfo -> do (_, t) <- writePatch repository opts $ invert p let newpend = join_patches [p, pend] withSignalsBlocked $ with_new_pending repository newpend $ do applyToPristine repository (invert p) `catch` \e -> fail ("Unable to apply inverse patch!\n" ++ show e) updateInventory repository [(pinfo, t)] putStrLn "Finished rolling back." \end{code}