darcs-2.18.1: src/Darcs/UI/ApplyPatches.hs
module Darcs.UI.ApplyPatches
( PatchApplier(..)
, PatchProxy(..)
, StandardPatchApplier(..)
, applyPatchesStart
, applyPatchesFinish
) where
import Darcs.Prelude
import Control.Monad ( when, void )
import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd )
import Darcs.Util.SignalHandler ( withSignalsBlocked )
import Darcs.UI.Commands
( putVerbose
, putFinished
, setEnvDarcsPatches
)
import Darcs.UI.Commands.Util ( printDryRunMessageAndExit )
import Darcs.UI.Flags
( DarcsFlag, verbosity, reorder, allowConflicts
, wantGuiPause, diffingOpts, setScriptsExecutable, isInteractive
, xmlOutput, dryRun
)
import qualified Darcs.UI.Options.All as O
import Darcs.UI.Options ( (?) )
import Darcs.UI.Commands.Util ( testTentativeAndMaybeExit )
import Darcs.Repository
( Repository
, AccessType(..)
, tentativelyMergePatches
, finalizeRepositoryChanges
, applyToWorking
, setScriptsExecutablePatches
)
import Darcs.Repository.Pristine ( readPristine )
import Darcs.Repository.Job ( RepoJob(RepoJob) )
import Darcs.Patch ( RepoPatch, description )
import Darcs.Patch.Apply( ApplyState )
import Darcs.Patch.FromPrim ( PrimOf )
import Darcs.Patch.Set ( PatchSet, Origin )
import Darcs.Patch.Witnesses.Ordered
( FL, Fork(..), mapFL, nullFL )
import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed) )
import Darcs.Util.English ( presentParticiple )
import Darcs.Util.Printer ( vcat, text )
import Darcs.Util.Tree( Tree )
data PatchProxy (p :: * -> * -> *) = PatchProxy
-- |This class is a hack to abstract over pull/apply and rebase pull/apply.
class PatchApplier pa where
repoJob
:: pa
-> (forall p wR wU
. (RepoPatch p, ApplyState p ~ Tree)
=> (PatchProxy p -> Repository 'RW p wU wR -> IO ()))
-> RepoJob 'RW ()
applyPatches
:: forall p wR wU wZ
. (RepoPatch p, ApplyState p ~ Tree)
=> pa
-> PatchProxy p
-> String
-> [DarcsFlag]
-> Repository 'RW p wU wR
-> Fork (PatchSet p)
(FL (PatchInfoAnd p))
(FL (PatchInfoAnd p)) Origin wR wZ
-> IO ()
data StandardPatchApplier = StandardPatchApplier
instance PatchApplier StandardPatchApplier where
repoJob StandardPatchApplier f = RepoJob (f PatchProxy)
applyPatches StandardPatchApplier PatchProxy = standardApplyPatches
standardApplyPatches :: (RepoPatch p, ApplyState p ~ Tree)
=> String
-> [DarcsFlag]
-> Repository 'RW p wU wR
-> Fork (PatchSet p)
(FL (PatchInfoAnd p))
(FL (PatchInfoAnd p)) Origin wR wZ
-> IO ()
standardApplyPatches cmdName opts repository patches@(Fork _ _ to_be_applied) = do
!no_patches <- return (nullFL to_be_applied)
applyPatchesStart cmdName opts to_be_applied
Sealed pw <- mergeAndTest cmdName opts repository patches
applyPatchesFinish cmdName opts repository pw (not no_patches)
mergeAndTest :: (RepoPatch p, ApplyState p ~ Tree)
=> String
-> [DarcsFlag]
-> Repository 'RW p wU wR
-> Fork (PatchSet p)
(FL (PatchInfoAnd p))
(FL (PatchInfoAnd p)) Origin wR wZ
-> IO (Sealed (FL (PrimOf p) wU))
mergeAndTest cmdName opts repository patches = do
pw <- tentativelyMergePatches repository cmdName
(allowConflicts opts)
(wantGuiPause opts)
(reorder ? opts) (diffingOpts opts)
patches
tree <- readPristine repository
testTentativeAndMaybeExit tree opts
"those patches do not pass the tests." (cmdName ++ " them") Nothing
return pw
applyPatchesStart :: (RepoPatch p, ApplyState p ~ Tree)
=> String -> [DarcsFlag] -> FL (PatchInfoAnd p) wX wY -> IO ()
applyPatchesStart cmdName opts to_be_applied = do
printDryRunMessageAndExit cmdName
(verbosity ? opts)
(O.withSummary ? opts)
(dryRun ? opts)
(xmlOutput ? opts)
(isInteractive True opts)
to_be_applied
if nullFL to_be_applied then
putStrLn $ "You don't want to " ++ cmdName ++ " any patches, and that's fine with me!"
else do
putVerbose opts $ text $ "Will " ++ cmdName ++ " the following patches:"
putVerbose opts . vcat $ mapFL description to_be_applied
setEnvDarcsPatches to_be_applied
applyPatchesFinish :: (RepoPatch p, ApplyState p ~ Tree)
=> String
-> [DarcsFlag]
-> Repository 'RW p wU wR
-> FL (PrimOf p) wU wY
-> Bool
-> IO ()
applyPatchesFinish cmdName opts _repository pw any_applied = do
withSignalsBlocked $ do
_repository <- finalizeRepositoryChanges _repository (O.dryRun ? opts)
void $ applyToWorking _repository (verbosity ? opts) pw
when (setScriptsExecutable ? opts == O.YesSetScriptsExecutable) $
setScriptsExecutablePatches pw
case (any_applied, reorder ? opts == O.Reorder) of
(True,True) -> putFinished opts $ "reordering"
(False,True) -> putFinished opts $ presentParticiple cmdName ++ " and reordering"
_ -> putFinished opts $ presentParticiple cmdName