% 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; if not, write to the Free Software Foundation, % Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \section{darcs rollback} \begin{code} module Rollback ( rollback ) where import Directory hiding ( getCurrentDirectory ) import Workaround ( getCurrentDirectory ) import Control.Exception ( block ) import DarcsCommands ( DarcsCommand(..), nodefaults ) import DarcsArguments ( DarcsFlag, verbose, working_repo_dir, nocompress, match_one_nontag, ) import Repository ( am_in_repo, slurp_recorded, read_pending, write_patch, write_pending, add_to_inventory, sift_for_pending, ) import Patch ( join_patches, apply_to_slurpy, invert, patch2patchinfo, ) import Depends ( is_tag ) import PatchInfo ( is_inverted ) import SlurpDirectory ( slurp_write_dirty ) import Lock ( withLock ) import SelectChanges ( with_selected_patch_from_repo ) #include "impossible.h" \end{code} \begin{code} rollback_description :: String rollback_description = "Roll back a named patch." \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 = am_in_repo, command_get_arg_possibilities = return [], command_argdefaults = nodefaults, command_darcsoptions = [match_one_nontag, nocompress,verbose, working_repo_dir]} \end{code} \begin{code} rollback_cmd :: [DarcsFlag] -> [String] -> IO () rollback_cmd opts _ = withLock "./_darcs/lock" $ do recorded <- slurp_recorded "." mpend <- read_pending let pend = case mpend of Nothing -> join_patches [] Just p -> p with_selected_patch_from_repo "rollback" opts False $ \ (p, _) -> case apply_to_slurpy (invert p) recorded of Nothing -> bug "Rollback: Unable to apply inverse patch!\n" Just rec' -> 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 write_patch opts $ invert p former_dir <- getCurrentDirectory setCurrentDirectory "_darcs/current" block $ do slurp_write_dirty rec' setCurrentDirectory former_dir write_pending $ sift_for_pending $ join_patches [p, pend] add_to_inventory "." pinfo putStr $ "Finished rolling back.\n" \end{code}