% Copyright (C) 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; if not, write to the Free Software Foundation, % Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. \section{darcs repair} \begin{code} module Repair ( repair ) where import Directory hiding ( getCurrentDirectory ) import Workaround ( getCurrentDirectory ) import IO import System ( exitWith, ExitCode(..) ) import Monad ( when, ) import DarcsCommands import DarcsArguments ( DarcsFlag( Verbose, Quiet ), any_verbosity, ) import Patch ( patch2patchinfo ) import Repository ( read_repo, am_in_repo, get_checkpoint, apply_patches ) import Diff ( cmp ) import Depends ( get_patches_beyond_tag ) import Lock( withTempDir, withLock, rm_recursive, ) import DarcsUtils ( catchall ) import Check ( check_uniqueness ) \end{code} \options{repair} \begin{code} repair_description :: String repair_description = "Repair a corrupted repository.\n" \end{code} \haskell{repair_help} \begin{code} repair_help :: String repair_help = "Repair attempts to fix corruption that may have entered your\n"++ "repository.\n" \end{code} \begin{code} repair :: DarcsCommand repair = DarcsCommand {command_name = "repair", command_help = repair_help, command_description = repair_description, command_extra_args = 0, command_extra_arg_help = [], command_command = repair_cmd, command_prereq = am_in_repo, command_get_arg_possibilities = return [], command_argdefaults = nodefaults, command_darcsoptions = [any_verbosity]} \end{code} Repair currently will only repair damage to the \verb!_darcs/current! directory. Fortunately this is just the sort of corruption that is most likely to happen. \begin{code} repair_cmd :: [DarcsFlag] -> [String] -> IO () repair_cmd opts _ = let putVerbose s = when (Verbose `elem` opts) $ putStr s putInfo s = when (not $ Quiet `elem` opts) $ putStr s in withLock "./_darcs/lock" $ do am_verbose <- return $ Verbose `elem` opts check_uniqueness putVerbose putInfo patches <- read_repo "." maybe_chk <- get_checkpoint opts "." formerdir <- getCurrentDirectory withTempDir (formerdir++"/_darcs/newcurrent") $ \newcur -> do when am_verbose $ putStr "Applying patches...\n" case maybe_chk of Just chk -> case patch2patchinfo chk of Just chtg -> do when (Verbose `elem` opts) $ putStr "I am repairing from a checkpoint.\n" apply_patches putVerbose putInfo $ (chtg, Just chk) : reverse (concat $ get_patches_beyond_tag chtg patches) Nothing -> fail "Bug in repair_cmd, please report." Nothing -> apply_patches putVerbose putInfo $ reverse $ concat patches is_same <- cmp (formerdir++"/_darcs/current") newcur if is_same then do putStr "The repo is already consistent, no changes made.\n" exitWith ExitSuccess else do putStr "Fixing current...\n" rm_recursive (formerdir++"/_darcs/current_old") `catchall` return () renameDirectory (formerdir++"/_darcs/current") (formerdir++"/_darcs/current_old") -- workaround for win32, working dir can't be renamed setCurrentDirectory formerdir renameDirectory newcur (formerdir++"/_darcs/current") exitWith ExitSuccess \end{code}