module Darcs.UI.Commands.Rebase ( rebase ) where
import Prelude ()
import Darcs.Prelude
import Darcs.UI.Commands
( DarcsCommand(..), withStdOpts
, normalCommand, hiddenCommand
, commandAlias
, defaultRepo, nodefaults
, putInfo, putVerbose
, setEnvDarcsPatches
, printDryRunMessageAndExit
, amInHashedRepository
)
import Darcs.UI.Commands.Apply ( applyCmd )
import Darcs.UI.Commands.Log ( changelog, getLogInfo )
import Darcs.UI.Commands.Pull ( pullCmd, revertable )
import Darcs.UI.Commands.Unrecord ( getLastPatches, matchingHead )
import Darcs.UI.CommandsAux ( checkPaths )
import Darcs.UI.Flags
( DarcsFlag
( AllowConflicts
, NoAllowConflicts
, MarkConflicts
, SkipConflicts
, SetScriptsExecutable)
, externalMerge, allowConflicts
, compression, diffingOpts
, dryRun, reorder, verbosity
, useCache, wantGuiPause
, umask, toMatchFlags, doReverse
, DarcsFlag(XMLOutput)
, showChangesOnlyToFiles
, diffAlgorithm, maxCount, hasSummary, isInteractive
, selectDeps, hasXmlOutput
)
import Darcs.UI.Options
( DarcsOption, (^), oid, odesc, ocheck, onormalise
, defaultFlags, parseFlags
)
import qualified Darcs.UI.Options.All as O
import Darcs.UI.PatchHeader ( HijackT, HijackOptions(..), runHijackT
, getAuthor
, updatePatchHeader, AskAboutDeps(..) )
import Darcs.Repository
( Repository, RepoJob(..), withRepoLock, withRepository
, RebaseJobFlags(..)
, tentativelyAddPatch, finalizeRepositoryChanges
, invalidateIndex
, tentativelyRemovePatches, readRepo
, tentativelyAddToPending, unrecordedChanges, applyToWorking
, revertRepositoryChanges
, setScriptsExecutablePatches
, listFiles
)
import Darcs.Repository.Flags ( UpdateWorking(..), ExternalMerge(..) )
import Darcs.Repository.Internal ( announceMergeConflicts )
import Darcs.Repository.Merge ( tentativelyMergePatches )
import Darcs.Repository.Prefs ( getPreflist )
import Darcs.Repository.Resolution ( standardResolution )
import Darcs.Patch ( invert, effect, commute, RepoPatch, description )
import Darcs.Patch.Apply ( ApplyState )
import Darcs.Patch.Commute ( selfCommuter )
import Darcs.Patch.CommuteFn ( commuterIdFL )
import Darcs.Patch.Info ( showPatchInfo )
import Darcs.Patch.Match ( firstMatch, secondMatch, splitSecondFL )
import Darcs.Patch.Named ( Named, fmapFL_Named, patchcontents, patch2patchinfo )
import Darcs.Patch.Named.Wrapped ( mkRebase, toRebasing, fromRebasing )
import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, info, n2pia, hopefully )
import Darcs.Patch.Prim ( PrimOf, canonizeFL, fromPrim )
import Darcs.Patch.Rebase ( takeHeadRebase, takeHeadRebaseFL )
import Darcs.Patch.Rebase.Container ( Suspended(..) )
import Darcs.Patch.Rebase.Fixup ( RebaseFixup(..), flToNamesPrims )
import Darcs.Patch.Rebase.Item ( RebaseItem(..), simplifyPush, simplifyPushes )
import Darcs.Patch.Rebase.Name ( RebaseName(..), commuteNameNamed )
import Darcs.Patch.Rebase.Viewing
( RebaseSelect(RSFwd), rsToPia
, toRebaseSelect, fromRebaseSelect, extractRebaseSelect, reifyRebaseSelect
, partitionUnconflicted
, WithDroppedDeps(..), WDDNamed, commuterIdWDD
, toRebaseChanges
)
import Darcs.Patch.Permutations ( partitionConflictingFL )
import Darcs.Patch.Progress ( progressFL )
import Darcs.Patch.RepoType ( RepoType(..), RebaseType(..) )
import Darcs.Patch.Set ( PatchSet(..), appendPSFL )
import Darcs.Patch.Show ( showNicely )
import Darcs.Patch.Split ( primSplitter )
import Darcs.UI.ApplyPatches ( PatchApplier(..), PatchProxy(..) )
import Darcs.UI.SelectChanges
( runSelection
, selectionContext, selectionContextGeneric, selectionContextPrim
, WhichChanges(First, Last, LastReversed)
, viewChanges
)
import qualified Darcs.UI.SelectChanges as S ( PatchSelectionOptions (..) )
import Darcs.Patch.Witnesses.Eq ( EqCheck(..) )
import Darcs.Patch.Witnesses.Ordered
( FL(..), (+>+), mapFL_FL
, concatFL, mapFL, nullFL, lengthFL
, (:>)(..)
, RL(..), reverseRL
)
import Darcs.Patch.Witnesses.Sealed
( Sealed(..), seal, unseal
, FlippedSeal(..)
, Sealed2(..)
)
import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )
import Darcs.Util.English ( englishNum, Noun(Noun) )
import Darcs.Util.Printer
( vcat, text, ($$)
, putDocLnWith, simplePrinters
, renderString, RenderMode(..)
)
import Darcs.Util.Printer.Color ( fancyPrinters )
import Darcs.Util.Progress ( debugMessage )
import Darcs.Util.Path ( AbsolutePath )
import Darcs.Util.Tree ( Tree )
import Control.Exception ( catch, IOException )
import Control.Monad ( when )
import Control.Monad.Trans ( liftIO )
import System.Exit ( exitSuccess )
#include "impossible.h"
rebaseDescription :: String
rebaseDescription = "Edit several patches at once."
rebaseHelp :: String
rebaseHelp =
"The `darcs rebase' command is used to edit a collection of darcs patches.\n"
rebase :: DarcsCommand [DarcsFlag]
rebase = SuperCommand
{ commandProgramName = "darcs"
, commandName = "rebase"
, commandHelp = rebaseHelp
, commandDescription = rebaseDescription
, commandPrereq = amInHashedRepository
, commandSubCommands =
[ normalCommand pull
, normalCommand apply
, normalCommand suspend
, normalCommand unsuspend
, hiddenCommand reify
, hiddenCommand inject
, normalCommand obliterate
, normalCommand log
, hiddenCommand changes
]
}
suspendBasicOpts :: DarcsOption a
([O.MatchFlag]
-> O.SelectDeps
-> Maybe Bool
-> Maybe O.Summary
-> O.DiffAlgorithm
-> a)
suspendBasicOpts
= O.matchSeveralOrLast
^ O.selectDeps
^ O.interactive
^ O.summary
^ O.diffAlgorithm
suspendAdvancedOpts :: DarcsOption a (Bool -> O.UseIndex -> a)
suspendAdvancedOpts
= O.changesReverse
^ O.useIndex
suspendOpts :: DarcsOption a
([O.MatchFlag]
-> O.SelectDeps
-> Maybe Bool
-> Maybe O.Summary
-> O.DiffAlgorithm
-> Maybe O.StdCmdAction
-> Bool
-> Bool
-> O.Verbosity
-> Bool
-> Bool
-> O.UseIndex
-> O.UseCache
-> Maybe String
-> Bool
-> Maybe String
-> Bool
-> a)
suspendOpts = suspendBasicOpts `withStdOpts` suspendAdvancedOpts
suspend :: DarcsCommand [DarcsFlag]
suspend = DarcsCommand
{ commandProgramName = "darcs"
, commandName = "suspend"
, commandHelp = "Select patches to move into a suspended state at the end of the repo.\n"
, commandDescription = "Select patches to move into a suspended state at the end of the repo."
, commandPrereq = amInHashedRepository
, commandExtraArgs = 0
, commandExtraArgHelp = []
, commandCommand = suspendCmd
, commandGetArgPossibilities = return []
, commandArgdefaults = nodefaults
, commandAdvancedOptions = odesc suspendAdvancedOpts
, commandBasicOptions = odesc suspendBasicOpts
, commandDefaults = defaultFlags suspendOpts
, commandCheckOptions = ocheck suspendOpts
, commandParseOptions = onormalise suspendOpts
}
suspendCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()
suspendCmd _ opts _args =
withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $
StartRebaseJob (RebaseJobFlags (compression opts) (verbosity opts) YesUpdateWorking) $
\repository -> do
allpatches <- readRepo repository
(rOld, suspended, allpatches_tail) <- return $ takeHeadRebase allpatches
(_ :> patches) <-
return $ if firstMatch (parseFlags O.matchSeveralOrLast opts)
then getLastPatches (parseFlags O.matchSeveralOrLast opts) allpatches_tail
else matchingHead (parseFlags O.matchSeveralOrLast opts) allpatches_tail
let direction = if doReverse opts then Last else LastReversed
patches_context = selectionContext direction "suspend" (patchSelOpts True opts) Nothing Nothing
(_ :> psToSuspend) <-
runSelection
patches
patches_context
when (nullFL psToSuspend) $ do
putStrLn "No patches selected!"
exitSuccess
runHijackT RequestHijackPermission
$ mapM_ (getAuthor "suspend" False Nothing)
$ mapFL info psToSuspend
repository' <- doSuspend opts repository suspended rOld psToSuspend
finalizeRepositoryChanges repository' YesUpdateWorking (compression opts)
return ()
doSuspend
:: forall p wR wU wT wX
. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)
=> [DarcsFlag]
-> Repository ('RepoType 'IsRebase) p wR wU wT
-> Suspended p wT wT
-> PatchInfoAnd ('RepoType 'IsRebase) p wT wT
-> FL (PatchInfoAnd ('RepoType 'IsRebase) p) wX wT
-> IO (Repository ('RepoType 'IsRebase) p wR wU wX)
doSuspend opts repository (Items qs) rOld psToSuspend = do
pend <- unrecordedChanges (diffingOpts opts) repository Nothing
FlippedSeal psAfterPending <-
let effectPsToSuspend = effect psToSuspend in
case commute (effectPsToSuspend :> pend) of
Just (_ :> res) -> return (FlippedSeal res)
Nothing -> do
putVerbose opts $
let invPsEffect = invert effectPsToSuspend
doPartition = partitionConflictingFL (commuterIdFL selfCommuter)
in
case (doPartition invPsEffect pend, doPartition pend invPsEffect) of
(_ :> invSuspendedConflicts, _ :> pendConflicts) ->
let suspendedConflicts = invert invSuspendedConflicts in
text "these changes in the suspended patches:" $$
showNicely suspendedConflicts $$
text "conflict with these local changes:" $$
showNicely pendConflicts
fail $ "Can't suspend selected patches without reverting some unrecorded change. Use --verbose to see the details."
rNew <- mkRebase (Items (mapFL_FL (ToEdit . fromRebasing . hopefully) psToSuspend +>+ qs))
invalidateIndex repository
repository' <- tentativelyRemovePatches repository (compression opts) YesUpdateWorking (psToSuspend +>+ (rOld :>: NilFL))
tentativelyAddToPending repository' YesUpdateWorking $ invert $ effect psToSuspend
repository'' <- tentativelyAddPatch repository' (compression opts) (verbosity opts) YesUpdateWorking (n2pia rNew)
_ <- applyToWorking repository'' (verbosity opts) (invert psAfterPending)
`catch` \(e :: IOException) -> fail ("Couldn't undo patch in working dir.\n" ++ show e)
return repository''
unsuspendBasicOpts :: DarcsOption a
(Maybe O.AllowConflicts
-> [O.MatchFlag]
-> Maybe Bool
-> Maybe O.Summary
-> ExternalMerge
-> Bool
-> Maybe String
-> O.DiffAlgorithm
-> a)
unsuspendBasicOpts
= O.conflicts O.YesAllowConflictsAndMark
^ O.matchSeveralOrFirst
^ O.interactive
^ O.summary
^ O.useExternalMerge
^ O.keepDate
^ O.author
^ O.diffAlgorithm
unsuspendAdvancedOpts :: DarcsOption a (O.UseIndex -> a)
unsuspendAdvancedOpts = O.useIndex
unsuspendOpts :: DarcsOption a
(Maybe O.AllowConflicts
-> [O.MatchFlag]
-> Maybe Bool
-> Maybe O.Summary
-> ExternalMerge
-> Bool
-> Maybe String
-> O.DiffAlgorithm
-> Maybe O.StdCmdAction
-> Bool
-> Bool
-> O.Verbosity
-> Bool
-> O.UseIndex
-> O.UseCache
-> Maybe String
-> Bool
-> Maybe String
-> Bool
-> a)
unsuspendOpts = unsuspendBasicOpts `withStdOpts` unsuspendAdvancedOpts
unsuspend :: DarcsCommand [DarcsFlag]
unsuspend = DarcsCommand
{ commandProgramName = "darcs"
, commandName = "unsuspend"
, commandHelp = "Selected patches to restore from a suspended state to the end of the repo.\n"
, commandDescription = "Select suspended patches to restore to the end of the repo."
, commandPrereq = amInHashedRepository
, commandExtraArgs = 0
, commandExtraArgHelp = []
, commandCommand = unsuspendCmd False
, commandGetArgPossibilities = return []
, commandArgdefaults = nodefaults
, commandAdvancedOptions = odesc unsuspendAdvancedOpts
, commandBasicOptions = odesc unsuspendBasicOpts
, commandDefaults = defaultFlags unsuspendOpts
, commandCheckOptions = ocheck unsuspendOpts
, commandParseOptions = onormalise unsuspendOpts
}
reifyBasicOpts :: DarcsOption a
([O.MatchFlag] -> Maybe Bool -> Bool -> Maybe String -> O.DiffAlgorithm -> a)
reifyBasicOpts
= O.matchSeveralOrFirst
^ O.interactive
^ O.keepDate
^ O.author
^ O.diffAlgorithm
reifyOpts :: DarcsOption a
([O.MatchFlag]
-> Maybe Bool
-> Bool
-> Maybe String
-> O.DiffAlgorithm
-> Maybe O.StdCmdAction
-> Bool
-> Bool
-> O.Verbosity
-> Bool
-> O.UseCache
-> Maybe String
-> Bool
-> Maybe String
-> Bool
-> a)
reifyOpts = reifyBasicOpts `withStdOpts` oid
reify :: DarcsCommand [DarcsFlag]
reify = DarcsCommand
{ commandProgramName = "darcs"
, commandName = "reify"
, commandHelp = "Select suspended patches to restore to the end of the repo, reifying any fixup patches.\n"
, commandDescription = "Select suspended patches to restore to the end of the repo, reifying any fixup patches."
, commandPrereq = amInHashedRepository
, commandExtraArgs = 0
, commandExtraArgHelp = []
, commandCommand = unsuspendCmd True
, commandGetArgPossibilities = return []
, commandArgdefaults = nodefaults
, commandAdvancedOptions = []
, commandBasicOptions = odesc reifyBasicOpts
, commandDefaults = defaultFlags reifyOpts
, commandCheckOptions = ocheck reifyOpts
, commandParseOptions = onormalise reifyOpts
}
unsuspendCmd :: Bool -> (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()
unsuspendCmd reifyFixups _ opts _args =
withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $
RebaseJob (RebaseJobFlags (compression opts) (verbosity opts) YesUpdateWorking) $
\(repository :: Repository ('RepoType 'IsRebase) p wR wU wR) -> (do
patches <- readRepo repository
pend <- unrecordedChanges (diffingOpts opts) repository Nothing
let checkChanges :: FL (PrimOf p) wA wB -> IO (EqCheck wA wB)
checkChanges NilFL = return IsEq
checkChanges _ = error "can't unsuspend when there are unrecorded changes"
IsEq <- checkChanges pend :: IO (EqCheck wR wU)
(rOld, Items ps, _) <- return $ takeHeadRebase patches
let selects = toRebaseSelect ps
let matchFlags = toMatchFlags opts
inRange :> outOfRange <-
return $
if secondMatch matchFlags then
splitSecondFL rsToPia matchFlags selects
else selects :> NilFL
offer :> dontoffer <-
return $
if SkipConflicts `elem` opts
then partitionUnconflicted inRange
else inRange :> NilRL
let warnSkip :: RL q wX wY -> IO ()
warnSkip NilRL = return ()
warnSkip _ = putStrLn "Skipping some patches which would cause conflicts."
warnSkip dontoffer
let patches_context = selectionContextGeneric rsToPia First "unsuspend" (patchSelOpts True opts) Nothing
(chosen :> keep) <- runSelection offer patches_context
when (nullFL chosen) $ do putStrLn "No patches selected!"
exitSuccess
(ps_to_unsuspend :: FL (WDDNamed p) wR wZ) :> chosen_fixups
<- (if reifyFixups then reifyRebaseSelect else return . extractRebaseSelect) chosen
let da = diffAlgorithm opts
ps_to_keep = simplifyPushes da chosen_fixups .
fromRebaseSelect $
keep +>+ reverseRL dontoffer +>+ outOfRange
Sealed standard_resolved_p <- return $ standardResolution $ concatFL
$ progressFL "Examining patches for conflicts"
$ mapFL_FL (patchcontents . wddPatch) ps_to_unsuspend
:: IO (Sealed (FL (PrimOf p) wZ))
let merge_opts | NoAllowConflicts `elem` opts = opts
| AllowConflicts `elem` opts = opts
| otherwise = MarkConflicts : opts
have_conflicts <- announceMergeConflicts "unsuspend" (allowConflicts merge_opts) (externalMerge merge_opts) standard_resolved_p
Sealed (resolved_p :: FL (PrimOf p) wA wB) <-
case (externalMerge opts, have_conflicts) of
(NoExternalMerge,_) -> return $ if AllowConflicts `elem` opts
then seal NilFL
else seal standard_resolved_p
(_,False) -> return $ seal standard_resolved_p
(YesExternalMerge _, True) -> error "external resolution for unsuspend not implemented yet"
let effect_to_apply = concatFL (mapFL_FL effect ps_to_unsuspend) +>+ resolved_p
invalidateIndex repository
repository' <- tentativelyRemovePatches repository (compression opts) YesUpdateWorking (rOld :>: NilFL)
tentativelyAddToPending repository' YesUpdateWorking effect_to_apply
(repository'', renames) <- runHijackT IgnoreHijack $ doAdd repository' ps_to_unsuspend
rNew <- unseal (mkRebase . Items) . unseal (simplifyPushes da (mapFL_FL NameFixup renames)) $ ps_to_keep
repository''' <- tentativelyAddPatch repository'' (compression opts) (verbosity opts) YesUpdateWorking (n2pia rNew)
finalizeRepositoryChanges repository''' YesUpdateWorking (compression opts)
_ <- applyToWorking repository''' (verbosity opts) effect_to_apply `catch` \(e :: IOException) ->
fail ("couldn't apply patch in working dir.\n" ++ show e)
return ()
) :: IO ()
where doAdd :: (RepoPatch p, ApplyState p ~ Tree)
=> Repository ('RepoType 'IsRebase) p wR wU wT
-> FL (WDDNamed p) wT wT2
-> HijackT IO (Repository ('RepoType 'IsRebase) p wR wU wT2, FL (RebaseName p) wT2 wT2)
doAdd repo NilFL = return (repo, NilFL)
doAdd repo ((p :: WDDNamed p wT wU) :>:ps) = do
case wddDependedOn p of
[] -> return ()
deps -> liftIO $ do
putStr $ "Warning: dropping the following explicit "
++ englishNum (length deps) (Noun "dependency") ":\n\n"
let printIndented n =
mapM_ (putStrLn . (replicate n ' '++)) . lines .
renderString Encode . showPatchInfo
putStrLn . renderString Encode . showPatchInfo .
patch2patchinfo $ wddPatch p
putStr " depended on:\n"
mapM_ (printIndented 2) deps
putStr "\n"
p' <- snd <$> updatePatchHeader "unsuspend"
NoAskAboutDeps
(patchSelOpts True opts)
(diffAlgorithm opts)
(parseFlags O.keepDate opts)
(parseFlags O.selectAuthor opts)
(parseFlags O.author opts)
(parseFlags O.patchname opts)
(parseFlags O.askLongComment opts)
(n2pia (toRebasing (wddPatch p))) NilFL
repo' <- liftIO $ tentativelyAddPatch repo (compression opts) (verbosity opts) YesUpdateWorking p'
let rename :: RebaseName p wU wU
rename = Rename (info p') (patch2patchinfo (wddPatch p))
Just (ps2 :> (rename2 :: RebaseName p wV wT2)) <- return (commuterIdFL (commuterIdWDD commuteNameNamed) (rename :> ps))
IsEq <- return (unsafeCoerceP IsEq :: EqCheck wV wT2)
(repo'', renames) <- doAdd repo' ps2
return (repo'', rename2 :>: renames)
injectBasicOpts :: DarcsOption a (Bool -> Maybe String -> O.DiffAlgorithm -> a)
injectBasicOpts = O.keepDate ^ O.author ^ O.diffAlgorithm
injectOpts :: DarcsOption a
(Bool
-> Maybe String
-> O.DiffAlgorithm
-> Maybe O.StdCmdAction
-> Bool
-> Bool
-> O.Verbosity
-> Bool
-> O.UseCache
-> Maybe String
-> Bool
-> Maybe String
-> Bool
-> a)
injectOpts = injectBasicOpts `withStdOpts` oid
inject :: DarcsCommand [DarcsFlag]
inject = DarcsCommand
{ commandProgramName = "darcs"
, commandName = "inject"
, commandHelp = "Merge a change from the fixups of a patch into the patch itself.\n"
, commandDescription = "Merge a change from the fixups of a patch into the patch itself."
, commandPrereq = amInHashedRepository
, commandExtraArgs = 0
, commandExtraArgHelp = []
, commandCommand = injectCmd
, commandGetArgPossibilities = return []
, commandArgdefaults = nodefaults
, commandAdvancedOptions = []
, commandBasicOptions = odesc injectBasicOpts
, commandDefaults = defaultFlags injectOpts
, commandCheckOptions = ocheck injectOpts
, commandParseOptions = onormalise injectOpts
}
injectCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()
injectCmd _ opts _args =
withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $
RebaseJob (RebaseJobFlags (compression opts) (verbosity opts) YesUpdateWorking) $
\(repository :: Repository ('RepoType 'IsRebase) p wR wU wR) -> do
patches <- readRepo repository
(rOld, Items ps, _) <- return $ takeHeadRebase patches
let selects = toRebaseSelect ps
let patches_context = selectionContextGeneric rsToPia First "inject into" (patchSelOpts True opts) Nothing
(chosens :> rest_selects) <- runSelection selects patches_context
let extractSingle :: FL (RebaseSelect p) wX wY -> (FL (RebaseFixup p) :> Named p) wX wY
extractSingle (RSFwd fixups toedit :>: NilFL) = fixups :> toedit
extractSingle (_ :>: NilFL) = impossible
extractSingle _ = error "You must select precisely one patch!"
fixups :> toedit <- return $ extractSingle chosens
name_fixups :> prim_fixups <- return $ flToNamesPrims fixups
let changes_context = selectionContextPrim Last "inject" (patchSelOpts True opts) (Just (primSplitter (diffAlgorithm opts))) Nothing Nothing
(rest_fixups :> injects) <- runSelection prim_fixups changes_context
when (nullFL injects) $ do
putStrLn "No changes selected!"
exitSuccess
let da = diffAlgorithm opts
toeditNew = fmapFL_Named (mapFL_FL fromPrim . canonizeFL da . (injects +>+) . effect) toedit
rNew <- unseal (mkRebase . Items)
$ unseal (simplifyPushes da (mapFL_FL NameFixup name_fixups))
$ simplifyPushes da (mapFL_FL PrimFixup rest_fixups)
$ ToEdit toeditNew :>: fromRebaseSelect rest_selects
repository' <- tentativelyRemovePatches repository (compression opts) YesUpdateWorking (rOld :>: NilFL)
repository'' <- tentativelyAddPatch repository' (compression opts) (verbosity opts) YesUpdateWorking (n2pia rNew)
finalizeRepositoryChanges repository'' YesUpdateWorking (compression opts)
return ()
obliterateBasicOpts :: DarcsOption a (O.DiffAlgorithm -> a)
obliterateBasicOpts = O.diffAlgorithm
obliterateOpts :: DarcsOption a
(O.DiffAlgorithm
-> Maybe O.StdCmdAction
-> Bool
-> Bool
-> O.Verbosity
-> Bool
-> O.UseCache
-> Maybe String
-> Bool
-> Maybe String
-> Bool
-> a)
obliterateOpts = obliterateBasicOpts `withStdOpts` oid
obliterate :: DarcsCommand [DarcsFlag]
obliterate = DarcsCommand
{ commandProgramName = "darcs"
, commandName = "obliterate"
, commandHelp = "Obliterate a patch that is currently suspended.\n"
, commandDescription = "Obliterate a patch that is currently suspended.\n"
, commandPrereq = amInHashedRepository
, commandExtraArgs = 0
, commandExtraArgHelp = []
, commandCommand = obliterateCmd
, commandGetArgPossibilities = return []
, commandArgdefaults = nodefaults
, commandAdvancedOptions = []
, commandBasicOptions = odesc obliterateBasicOpts
, commandDefaults = defaultFlags obliterateOpts
, commandCheckOptions = ocheck obliterateOpts
, commandParseOptions = onormalise obliterateOpts
}
obliterateCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()
obliterateCmd _ opts _args =
withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $
RebaseJob (RebaseJobFlags (compression opts) (verbosity opts) YesUpdateWorking) $
\(repository :: Repository ('RepoType 'IsRebase) p wR wU wR) -> (do
patches <- readRepo repository
(rOld, Items ps, _) <- return $ takeHeadRebase patches
let selects = toRebaseSelect ps
let patches_context = selectionContextGeneric rsToPia First "obliterate" (obliteratePatchSelOpts opts) Nothing
(chosen :> keep) <- runSelection selects patches_context
when (nullFL chosen) $ do putStrLn "No patches selected!"
exitSuccess
let da = diffAlgorithm opts
do_obliterate :: FL (RebaseItem p) wX wY -> FL (RebaseItem p) wY wZ -> Sealed (FL (RebaseItem p) wX)
do_obliterate NilFL = Sealed
do_obliterate (Fixup f :>: qs) = unseal (simplifyPush da f) . do_obliterate qs
do_obliterate (ToEdit e :>: qs) =
unseal (simplifyPush da (NameFixup (AddName (patch2patchinfo e)))) .
unseal (simplifyPushes da (mapFL_FL PrimFixup (effect (patchcontents e)))) .
do_obliterate qs
let ps_to_keep = do_obliterate (fromRebaseSelect chosen) (fromRebaseSelect keep)
rNew <- unseal (mkRebase . Items) ps_to_keep
repository' <- tentativelyRemovePatches repository (compression opts) YesUpdateWorking (rOld :>: NilFL)
repository'' <- tentativelyAddPatch repository' (compression opts) (verbosity opts) YesUpdateWorking (n2pia rNew)
finalizeRepositoryChanges repository'' YesUpdateWorking (compression opts)
return ()
) :: IO ()
pullDescription :: String
pullDescription =
"Copy and apply patches from another repository, suspending any local patches that conflict."
pullHelp :: String
pullHelp =
"Copy and apply patches from another repository, suspending any local patches that conflict."
pullBasicOpts :: DarcsOption a
([O.MatchFlag]
-> O.Reorder
-> Maybe Bool
-> Maybe O.AllowConflicts
-> ExternalMerge
-> O.RunTest
-> O.DryRun
-> O.XmlOutput
-> Maybe O.Summary
-> O.SelectDeps
-> Maybe Bool
-> Maybe String
-> Bool
-> O.DiffAlgorithm
-> a)
pullBasicOpts
= O.matchSeveral
^ O.reorder
^ O.interactive
^ O.conflicts O.YesAllowConflictsAndMark
^ O.useExternalMerge
^ O.test
^ O.dryRunXml
^ O.summary
^ O.selectDeps
^ O.setDefault
^ O.workingRepoDir
^ O.allowUnrelatedRepos
^ O.diffAlgorithm
pullAdvancedOpts :: DarcsOption a
(O.RepoCombinator
-> O.Compression
-> O.UseIndex
-> O.RemoteRepos
-> O.SetScriptsExecutable
-> O.UMask
-> Bool
-> Bool
-> O.NetworkOptions
-> a)
pullAdvancedOpts
= O.repoCombinator
^ O.compress
^ O.useIndex
^ O.remoteRepos
^ O.setScriptsExecutable
^ O.umask
^ O.restrictPaths
^ O.changesReverse
^ O.network
pullOpts :: DarcsOption a
([O.MatchFlag]
-> O.Reorder
-> Maybe Bool
-> Maybe O.AllowConflicts
-> ExternalMerge
-> O.RunTest
-> O.DryRun
-> O.XmlOutput
-> Maybe O.Summary
-> O.SelectDeps
-> Maybe Bool
-> Maybe String
-> Bool
-> O.DiffAlgorithm
-> Maybe O.StdCmdAction
-> Bool
-> Bool
-> O.Verbosity
-> Bool
-> O.RepoCombinator
-> O.Compression
-> O.UseIndex
-> O.RemoteRepos
-> O.SetScriptsExecutable
-> O.UMask
-> Bool
-> Bool
-> O.NetworkOptions
-> O.UseCache
-> Maybe String
-> Bool
-> Maybe String
-> Bool
-> a)
pullOpts = pullBasicOpts `withStdOpts` pullAdvancedOpts
pull :: DarcsCommand [DarcsFlag]
pull = DarcsCommand
{ commandProgramName = "darcs"
, commandName = "pull"
, commandHelp = pullHelp
, commandDescription = pullDescription
, commandExtraArgs = 1
, commandExtraArgHelp = ["[REPOSITORY]..."]
, commandCommand = pullCmd RebasePatchApplier
, commandPrereq = amInHashedRepository
, commandGetArgPossibilities = getPreflist "repos"
, commandArgdefaults = defaultRepo
, commandAdvancedOptions = odesc pullAdvancedOpts
, commandBasicOptions = odesc pullBasicOpts
, commandDefaults = defaultFlags pullOpts
, commandCheckOptions = ocheck pullOpts
, commandParseOptions = onormalise pullOpts
}
applyDescription :: String
applyDescription = "Apply a patch bundle, suspending any local patches that conflict."
applyHelp :: String
applyHelp = "Apply a patch bundle, suspending any local patches that conflict."
stdindefault :: a -> [String] -> IO [String]
stdindefault _ [] = return ["-"]
stdindefault _ x = return x
apply :: DarcsCommand [DarcsFlag]
apply = DarcsCommand
{ commandProgramName = "darcs"
, commandName = "apply"
, commandHelp = applyHelp
, commandDescription = applyDescription
, commandExtraArgs = 1
, commandExtraArgHelp = ["<PATCHFILE>"]
, commandCommand = applyCmd RebasePatchApplier
, commandPrereq = amInHashedRepository
, commandGetArgPossibilities = listFiles False
, commandArgdefaults = const stdindefault
, commandAdvancedOptions = odesc applyAdvancedOpts
, commandBasicOptions = odesc applyBasicOpts
, commandDefaults = defaultFlags applyOpts
, commandCheckOptions = ocheck applyOpts
, commandParseOptions = onormalise applyOpts
}
applyBasicOpts :: DarcsOption a
(O.Verify
-> O.Reorder
-> Maybe Bool
-> O.DryRun
-> O.XmlOutput
-> [O.MatchFlag]
-> Maybe String
-> O.DiffAlgorithm
-> a)
applyBasicOpts
= O.verify
^ O.reorder
^ O.interactive
^ O.dryRunXml
^ O.matchSeveral
^ O.workingRepoDir
^ O.diffAlgorithm
applyAdvancedOpts :: DarcsOption a
(Maybe String
-> Maybe String
-> Bool
-> (Bool, Maybe String)
-> O.UseIndex
-> O.Compression
-> O.SetScriptsExecutable
-> O.UMask
-> Bool
-> Bool
-> O.WantGuiPause
-> a)
applyAdvancedOpts
= O.reply
^ O.ccApply
^ O.happyForwarding
^ O.sendmail
^ O.useIndex
^ O.compress
^ O.setScriptsExecutable
^ O.umask
^ O.restrictPaths
^ O.changesReverse
^ O.pauseForGui
applyOpts :: DarcsOption a
(O.Verify
-> O.Reorder
-> Maybe Bool
-> O.DryRun
-> O.XmlOutput
-> [O.MatchFlag]
-> Maybe String
-> O.DiffAlgorithm
-> Maybe O.StdCmdAction
-> Bool
-> Bool
-> O.Verbosity
-> Bool
-> Maybe String
-> Maybe String
-> Bool
-> (Bool, Maybe String)
-> O.UseIndex
-> O.Compression
-> O.SetScriptsExecutable
-> O.UMask
-> Bool
-> Bool
-> O.WantGuiPause
-> O.UseCache
-> Maybe String
-> Bool
-> Maybe String
-> Bool
-> a)
applyOpts = applyBasicOpts `withStdOpts` applyAdvancedOpts
data RebasePatchApplier = RebasePatchApplier
instance PatchApplier RebasePatchApplier where
type ApplierRepoTypeConstraint RebasePatchApplier rt = rt ~ 'RepoType 'IsRebase
repoJob RebasePatchApplier opts f =
StartRebaseJob
(RebaseJobFlags (compression opts) (verbosity opts) YesUpdateWorking)
(f PatchProxy)
applyPatches RebasePatchApplier PatchProxy = applyPatchesForRebaseCmd
applyPatchesForRebaseCmd
:: forall p wR wU wX wT wZ
. ( RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree
)
=> String
-> [DarcsFlag]
-> String
-> Repository ('RepoType 'IsRebase) p wR wU wT
-> FL (PatchInfoAnd ('RepoType 'IsRebase) p) wX wT
-> FL (PatchInfoAnd ('RepoType 'IsRebase) p) wX wZ
-> IO ()
applyPatchesForRebaseCmd cmdName opts _from_whom repository us' to_be_applied = do
printDryRunMessageAndExit cmdName
(verbosity opts)
(hasSummary O.NoSummary opts)
(dryRun opts)
(hasXmlOutput opts)
(isInteractive True opts)
to_be_applied
setEnvDarcsPatches to_be_applied
when (nullFL to_be_applied) $ do
putStrLn $ "You don't want to " ++ cmdName ++ " any patches, and that's fine with me!"
exitSuccess
checkPaths opts to_be_applied
putVerbose opts $ text $ "Will " ++ cmdName ++ " the following patches:"
putVerbose opts $ vcat $ mapFL description to_be_applied
usOk :> usConflicted <- return $ partitionConflictingFL (commuterIdFL selfCommuter) us' to_be_applied
when (lengthFL usConflicted > 0) $
putInfo opts $ text "The following local patches are in conflict:"
let patches_context = selectionContext LastReversed "suspend" applyPatchSelOpts Nothing Nothing
(usKeep :> usToSuspend) <- runSelection usConflicted patches_context
runHijackT RequestHijackPermission
$ mapM_ (getAuthor "suspend" False Nothing)
$ mapFL info usToSuspend
(rOld, suspended, _) <- return $ takeHeadRebaseFL us'
repository' <- doSuspend opts repository suspended rOld usToSuspend
finalizeRepositoryChanges repository' YesUpdateWorking (compression opts)
>> revertRepositoryChanges repository' YesUpdateWorking
Sealed pw <-
tentativelyMergePatches
repository' cmdName
(allowConflicts opts) YesUpdateWorking
(externalMerge opts)
(wantGuiPause opts) (compression opts) (verbosity opts)
(reorder opts) (diffingOpts opts)
(usOk +>+ usKeep) to_be_applied
invalidateIndex repository
finalizeRepositoryChanges repository' YesUpdateWorking (compression opts)
_ <- revertable $ applyToWorking repository' (verbosity opts) pw
when (SetScriptsExecutable `elem` opts) $ setScriptsExecutablePatches pw
putInfo opts $ text $ "Finished " ++ cmdName ++ "ing."
applyPatchSelOpts :: S.PatchSelectionOptions
applyPatchSelOpts = S.PatchSelectionOptions
{ S.verbosity = O.NormalVerbosity
, S.matchFlags = []
, S.interactive = True
, S.selectDeps = O.PromptDeps
, S.summary = O.NoSummary
, S.withContext = O.NoContext
}
obliteratePatchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions
obliteratePatchSelOpts opts = (patchSelOpts True opts)
{ S.selectDeps = O.NoDeps
}
patchSelOpts :: Bool -> [DarcsFlag] -> S.PatchSelectionOptions
patchSelOpts defInteractive flags = S.PatchSelectionOptions
{ S.verbosity = verbosity flags
, S.matchFlags = parseFlags O.matchSeveralOrLast flags
, S.interactive = isInteractive defInteractive flags
, S.selectDeps = selectDeps flags
, S.summary = hasSummary O.NoSummary flags
, S.withContext = O.NoContext
}
log :: DarcsCommand [DarcsFlag]
log = DarcsCommand
{ commandProgramName = "darcs"
, commandName = "log"
, commandHelp = "List the currently suspended changes.\n"
, commandDescription = "List the currently suspended changes"
, commandPrereq = amInHashedRepository
, commandExtraArgs = 0
, commandExtraArgHelp = []
, commandCommand = logCmd
, commandGetArgPossibilities = return []
, commandArgdefaults = nodefaults
, commandAdvancedOptions = odesc logAdvancedOpts
, commandBasicOptions = odesc logBasicOpts
, commandDefaults = defaultFlags logOpts
, commandCheckOptions = ocheck logOpts
, commandParseOptions = onormalise logOpts
}
logBasicOpts :: DarcsOption a
(Maybe O.Summary
-> Maybe Bool
-> a)
logBasicOpts
= O.summary
^ O.interactive
logAdvancedOpts :: DarcsOption a a
logAdvancedOpts = oid
logOpts :: DarcsOption a
(Maybe O.Summary
-> Maybe Bool
-> Maybe O.StdCmdAction
-> Bool
-> Bool
-> O.Verbosity
-> Bool
-> O.UseCache
-> Maybe String
-> Bool
-> Maybe String
-> Bool
-> a)
logOpts = logBasicOpts `withStdOpts` logAdvancedOpts
logCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()
logCmd _ opts _files =
withRepository (useCache opts) $
RebaseJob (RebaseJobFlags (compression opts) (verbosity opts) YesUpdateWorking) $ \repository -> do
patches <- readRepo repository
(_, Items ps, _) <- return $ takeHeadRebase patches
let psToShow = toRebaseChanges ps
if isInteractive False opts
then viewChanges (patchSelOpts False opts) (mapFL Sealed2 psToShow)
else do
debugMessage "About to print the changes..."
let printers = if XMLOutput `elem` opts then simplePrinters else fancyPrinters
emptyPatchSet = PatchSet NilRL NilRL
patchSet = appendPSFL emptyPatchSet psToShow
logInfo <-
getLogInfo
(maxCount opts)
(toMatchFlags opts)
(showChangesOnlyToFiles opts)
Nothing
(\_ qs -> return qs)
patchSet
let logDoc = changelog opts patchSet logInfo
putDocLnWith printers logDoc
changes :: DarcsCommand [DarcsFlag]
changes = commandAlias "changes" Nothing log