packages feed

darcs 2.12.5 → 2.14.0

raw patch · 343 files changed

+14797/−14939 lines, 343 filesdep +stmdep +temporarydep −transformers-compatdep ~FindBindep ~HTTPdep ~HUnitsetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies added: stm, temporary

Dependencies removed: transformers-compat

Dependency ranges changed: FindBin, HTTP, HUnit, QuickCheck, Win32, array, async, attoparsec, base, bytestring, cmdargs, containers, cryptohash, directory, fgl, filepath, graphviz, hashable, haskeline, mmap, mtl, network, old-time, parsec, process, random, shelly, tar, terminfo, test-framework, test-framework-hunit, test-framework-quickcheck2, time, transformers, unix, unix-compat, utf8-string, vector, zip-archive, zlib

API changes (from Hackage documentation)

- Bundled.Posix: data FileStatus
- Bundled.Posix: fileExists :: FileStatus -> Bool
- Bundled.Posix: fileSize :: FileStatus -> FileOffset
- Bundled.Posix: getFdStatus :: Fd -> IO FileStatus
- Bundled.Posix: getFileStatus :: FilePath -> IO FileStatus
- Bundled.Posix: getFileStatusBS :: ByteString -> IO FileStatus
- Bundled.Posix: getSymbolicLinkStatus :: FilePath -> IO FileStatus
- Bundled.Posix: isDirectory :: FileStatus -> Bool
- Bundled.Posix: isRegularFile :: FileStatus -> Bool
- Bundled.Posix: modificationTime :: FileStatus -> EpochTime
- Bundled.Posix: type EpochTime = CTime
- Darcs.Patch: class (Apply p, Commute p, Invert p) => Patchy p
- Darcs.Patch: class (Patchy p, Merge p, Effect p, IsHunk p, PatchInspect p, ReadPatch p, ShowPatch p, FromPrim p, Conflict p, CommuteNoConflicts p, Check p, RepairToFL p, PatchListFormat p, PrimPatchBase p, Patchy (PrimOf p), IsHunk (PrimOf p), Matchable p) => RepoPatch p
- Darcs.Patch: instance (Darcs.Patch.Patchy.Patchy p, Darcs.Patch.Apply.ApplyState p ~ Darcs.Util.Tree.Tree) => Darcs.Patch.Patchy.Patchy (Darcs.Patch.Named.Named p)
- Darcs.Patch: instance (Darcs.Patch.Patchy.Patchy p, Darcs.Patch.Apply.ApplyState p ~ Darcs.Util.Tree.Tree) => Darcs.Patch.Patchy.Patchy (Darcs.Patch.Named.Wrapped.WrappedNamed rt p)
- Darcs.Patch.Annotate: instance Darcs.Patch.ApplyMonad.ApplyMonad Darcs.Util.Tree.Tree Darcs.Patch.Annotate.AnnotatedM
- Darcs.Patch.Annotate: instance Darcs.Patch.ApplyMonad.ApplyMonadTree Darcs.Patch.Annotate.AnnotatedM
- Darcs.Patch.Apply: applyToFileMods :: (Apply p, ApplyState p ~ Tree) => p wX wY -> Set FileName -> (Set FileName, [PatchMod FileName])
- Darcs.Patch.ApplyMonad: mModifyFilePSs :: ApplyMonadTree m => FileName -> ([ByteString] -> m [ByteString]) -> m ()
- Darcs.Patch.ApplyMonad: mReadFilePSs :: ApplyMonadTree m => FileName -> m [ByteString]
- Darcs.Patch.Bundle: getContext :: ByteString -> ([PatchInfo], ByteString)
- Darcs.Patch.Bundle: hashBundle :: (PatchListFormat p, ShowPatchBasic p) => FL (WrappedNamed rt p) wX wY -> String
- Darcs.Patch.Bundle: makeBundle2 :: (ApplyState p ~ Tree, RepoPatch p) => Maybe (Tree IO) -> RL (PatchInfoAnd rt p) wStart wX -> FL (WrappedNamed rt p) wX wY -> FL (WrappedNamed rt p) wX wY -> IO Doc
- Darcs.Patch.Bundle: parseBundle :: forall rt p. RepoPatch p => ByteString -> Either String (Sealed ((PatchSet rt p :> FL (PatchInfoAnd rt p)) Origin))
- Darcs.Patch.Choices: instance Darcs.Patch.Witnesses.Eq.MyEq p => Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.Choices.LabelledPatch p)
- Darcs.Patch.Choices: instance Darcs.Patch.Witnesses.Eq.MyEq p => Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.Choices.PatchChoice p)
- Darcs.Patch.Choices: instance GHC.Classes.Ord Darcs.Patch.Choices.Label
- Darcs.Patch.Choices: lpPatch :: LabelledPatch p wX wY -> p wX wY
- Darcs.Patch.Choices: makeUncertain :: Patchy p => Label -> PatchChoices p wA wB -> PatchChoices p wA wB
- Darcs.Patch.Choices: patchChoicesLps :: Patchy p => FL p wX wY -> (PatchChoices p wX wY, FL (LabelledPatch p) wX wY)
- Darcs.Patch.Choices: patchChoicesLpsSub :: Patchy p => Maybe Label -> FL p wX wY -> (PatchChoices p wX wY, FL (LabelledPatch p) wX wY)
- Darcs.Patch.Choices: patchSlot' :: Patchy p => LabelledPatch p wA wB -> StateT (PatchChoices p wX wY) Identity Slot
- Darcs.Patch.Depends: newsetIntersection :: Patchy p => [SealedPatchSet rt p wStart] -> SealedPatchSet rt p wStart
- Darcs.Patch.Depends: newsetUnion :: (Patchy p, Merge p) => [SealedPatchSet rt p wStart] -> SealedPatchSet rt p wStart
- Darcs.Patch.Dummy: instance Darcs.Patch.Patchy.Patchy Darcs.Patch.Dummy.DummyPatch
- Darcs.Patch.Dummy: instance Darcs.Patch.Patchy.Patchy Darcs.Patch.Dummy.DummyPrim
- Darcs.Patch.Dummy: instance Darcs.Patch.Witnesses.Eq.MyEq Darcs.Patch.Dummy.DummyPatch
- Darcs.Patch.Dummy: instance Darcs.Patch.Witnesses.Eq.MyEq Darcs.Patch.Dummy.DummyPrim
- Darcs.Patch.Format: copyListFormat :: ListFormat p -> ListFormat q
- Darcs.Patch.Index.Monad: data FileModMonad a
- Darcs.Patch.Index.Monad: instance Control.Monad.State.Class.MonadState (Data.Set.Base.Set Darcs.Util.Path.FileName, [Darcs.Patch.Index.Types.PatchMod Darcs.Util.Path.FileName]) Darcs.Patch.Index.Monad.FileModMonad
- Darcs.Patch.Index.Types: DatedFilePath :: FilePath -> (Maybe PatchId) -> DatedFilePath
- Darcs.Patch.Index.Types: data DatedFilePath
- Darcs.Patch.Index.Types: makePatchID :: PatchInfo -> PatchId
- Darcs.Patch.Index.Types: parseFileId :: String -> FileId
- Darcs.Patch.Info: makeFilename :: PatchInfo -> String
- Darcs.Patch.Info: piDateBytestring :: PatchInfo -> ByteString
- Darcs.Patch.Info: readPatchInfos :: ByteString -> [PatchInfo]
- Darcs.Patch.Info: showPatchInfoUI :: PatchInfo -> Doc
- Darcs.Patch.Match: matchAPatchread :: (IsRepoType rt, Matchable p) => [MatchFlag] -> PatchInfoAnd rt p wX wY -> Bool
- Darcs.Patch.MonadProgress: instance (GHC.Base.Functor m, GHC.Base.Monad m) => Darcs.Patch.MonadProgress.MonadProgress (Darcs.Util.Tree.Monad.TreeMonad m)
- Darcs.Patch.Named: instance (Darcs.Patch.Apply.Apply p, Darcs.Patch.Conflict.CommuteNoConflicts p, Darcs.Patch.Conflict.Conflict p, Darcs.Patch.FileHunk.IsHunk p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Show.ShowPatch p) => Darcs.Patch.Show.ShowPatch (Darcs.Patch.Named.Named p)
- Darcs.Patch.Named: instance (Darcs.Patch.Commute.Commute p, Darcs.Patch.Witnesses.Eq.MyEq p) => Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.Named.Named p)
- Darcs.Patch.OldDate: readUTCDate :: String -> CalendarTime
- Darcs.Patch.OldDate: showIsoDateTime :: CalendarTime -> String
- Darcs.Patch.PatchInfoAnd: instance (Darcs.Patch.Patchy.Patchy p, Darcs.Patch.Apply.ApplyState p ~ Darcs.Util.Tree.Tree) => Darcs.Patch.Patchy.Patchy (Darcs.Patch.PatchInfoAnd.PatchInfoAnd rt p)
- Darcs.Patch.PatchInfoAnd: instance Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.PatchInfoAnd.PatchInfoAnd rt p)
- Darcs.Patch.PatchInfoAnd: instance Darcs.Patch.Witnesses.Eq.MyEq Darcs.Patch.PatchInfoAnd.WPatchInfo
- Darcs.Patch.Patchy: apply :: (Apply p, ApplyMonad (ApplyState p) m) => p wX wY -> m ()
- Darcs.Patch.Patchy: class Apply p where type ApplyState p :: (* -> *) -> * where {
- Darcs.Patch.Patchy: class Commute p
- Darcs.Patch.Patchy: class Invert p
- Darcs.Patch.Patchy: class PatchInspect p
- Darcs.Patch.Patchy: class (Apply p, Commute p, Invert p) => Patchy p
- Darcs.Patch.Patchy: class ReadPatch p
- Darcs.Patch.Patchy: class ShowPatchBasic p => ShowPatch p where showNicely = showPatch showContextPatch p = return $ showPatch p description = showPatch thing _ = "patch" things x = plural (Noun $ thing x) ""
- Darcs.Patch.Patchy: commute :: Commute p => (p :> p) wX wY -> Maybe ((p :> p) wX wY)
- Darcs.Patch.Patchy: description :: ShowPatch p => p wX wY -> Doc
- Darcs.Patch.Patchy: hunkMatches :: PatchInspect p => (ByteString -> Bool) -> p wX wY -> Bool
- Darcs.Patch.Patchy: invert :: Invert p => p wX wY -> p wY wX
- Darcs.Patch.Patchy: listTouchedFiles :: PatchInspect p => p wX wY -> [FilePath]
- Darcs.Patch.Patchy: readPatch' :: (ReadPatch p, ParserM m) => m (Sealed (p wX))
- Darcs.Patch.Patchy: showContextPatch :: (ShowPatch p, Monad m, ApplyMonad (ApplyState p) m) => p wX wY -> m Doc
- Darcs.Patch.Patchy: showNicely :: ShowPatch p => p wX wY -> Doc
- Darcs.Patch.Patchy: showPatch :: ShowPatchBasic p => p wX wY -> Doc
- Darcs.Patch.Patchy: summary :: ShowPatch p => p wX wY -> Doc
- Darcs.Patch.Patchy: summaryFL :: ShowPatch p => FL p wX wY -> Doc
- Darcs.Patch.Patchy: thing :: ShowPatch p => p wX wY -> String
- Darcs.Patch.Patchy: things :: ShowPatch p => p wX wY -> String
- Darcs.Patch.Patchy: type family ApplyState p :: (* -> *) -> *;
- Darcs.Patch.Patchy: }
- Darcs.Patch.Patchy.Instances: instance (Darcs.Patch.FileHunk.IsHunk p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Patchy.Patchy p) => Darcs.Patch.Patchy.Patchy (Darcs.Patch.Witnesses.Ordered.FL p)
- Darcs.Patch.Patchy.Instances: instance (Darcs.Patch.FileHunk.IsHunk p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Patchy.Patchy p) => Darcs.Patch.Patchy.Patchy (Darcs.Patch.Witnesses.Ordered.RL p)
- Darcs.Patch.Permutations: instance (Darcs.Patch.Witnesses.Eq.MyEq p, Darcs.Patch.Commute.Commute p) => Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.Witnesses.Ordered.FL p)
- Darcs.Patch.Permutations: instance (Darcs.Patch.Witnesses.Eq.MyEq p, Darcs.Patch.Commute.Commute p) => Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.Witnesses.Ordered.RL p)
- Darcs.Patch.Prim: showPrimFL :: PrimShow prim => FileNameFormat -> FL prim wA wB -> Doc
- Darcs.Patch.Prim.Class: showPrimFL :: PrimShow prim => FileNameFormat -> FL prim wA wB -> Doc
- Darcs.Patch.Prim.FileUUID: instance Darcs.Patch.Patchy.Patchy Darcs.Patch.Prim.FileUUID.Core.Prim
- Darcs.Patch.Prim.FileUUID.Apply: instance (GHC.Base.Functor m, GHC.Base.Monad m) => Darcs.Patch.ApplyMonad.ApplyMonad Darcs.Patch.Prim.FileUUID.ObjectMap.ObjectMap (Control.Monad.Trans.State.Lazy.StateT (Darcs.Patch.Prim.FileUUID.ObjectMap.ObjectMap m) m)
- Darcs.Patch.Prim.FileUUID.Apply: instance (GHC.Base.Functor m, GHC.Base.Monad m) => Darcs.Patch.ApplyMonad.ApplyMonadTrans Darcs.Patch.Prim.FileUUID.ObjectMap.ObjectMap m
- Darcs.Patch.Prim.FileUUID.Apply: instance (GHC.Base.Functor m, GHC.Base.Monad m) => Darcs.Patch.Prim.FileUUID.Apply.ApplyMonadObjectMap (Control.Monad.Trans.State.Lazy.StateT (Darcs.Patch.Prim.FileUUID.ObjectMap.ObjectMap m) m)
- Darcs.Patch.Prim.FileUUID.Commute: class Monad m => CommuteMonad m
- Darcs.Patch.Prim.FileUUID.Commute: commuteFail :: CommuteMonad m => m a
- Darcs.Patch.Prim.FileUUID.Commute: instance Darcs.Patch.Prim.FileUUID.Commute.Commute' Darcs.Patch.Prim.FileUUID.Core.Prim
- Darcs.Patch.Prim.FileUUID.Commute: instance Darcs.Patch.Prim.FileUUID.Commute.CommuteMonad GHC.Base.Maybe
- Darcs.Patch.Prim.FileUUID.Core: [BinaryHunk] :: !UUID -> Hunk wX wY -> Prim wX wY
- Darcs.Patch.Prim.FileUUID.Core: [Move] :: !UUID -> Location -> Location -> Prim wX wY
- Darcs.Patch.Prim.FileUUID.Core: [TextHunk] :: !UUID -> Hunk wX wY -> Prim wX wY
- Darcs.Patch.Prim.FileUUID.Core: hunkEdit :: Hunk wX wY -> ByteString -> ByteString
- Darcs.Patch.Prim.FileUUID.Core: instance Darcs.Patch.Witnesses.Eq.MyEq Darcs.Patch.Prim.FileUUID.Core.Hunk
- Darcs.Patch.Prim.FileUUID.Core: instance Darcs.Patch.Witnesses.Eq.MyEq Darcs.Patch.Prim.FileUUID.Core.Prim
- Darcs.Patch.Prim.FileUUID.Core: touches :: Prim wX wY -> [UUID]
- Darcs.Patch.Prim.FileUUID.Core: type Location = (UUID, ByteString)
- Darcs.Patch.Prim.FileUUID.ObjectMap: type Location = (UUID, ByteString)
- Darcs.Patch.Prim.FileUUID.Show: showHunk :: String -> UUID -> Hunk wX wY -> Doc
- Darcs.Patch.Prim.V1: instance Darcs.Patch.Patchy.Patchy Darcs.Patch.Prim.V1.Core.Prim
- Darcs.Patch.Prim.V1: instance Darcs.Patch.Prim.Class.FromPrim Darcs.Patch.Prim.V1.Core.Prim
- Darcs.Patch.Prim.V1: instance Darcs.Patch.Prim.Class.PrimPatch Darcs.Patch.Prim.V1.Core.Prim
- Darcs.Patch.Prim.V1: instance Darcs.Patch.Prim.Class.PrimPatchBase Darcs.Patch.Prim.V1.Core.Prim
- Darcs.Patch.Prim.V1.Commute: WrappedCommuteFunction :: CommuteFunction -> WrappedCommuteFunction
- Darcs.Patch.Prim.V1.Commute: [runWrappedCommuteFunction] :: WrappedCommuteFunction -> CommuteFunction
- Darcs.Patch.Prim.V1.Commute: newtype WrappedCommuteFunction
- Darcs.Patch.Prim.V1.Commute: subcommutes :: [(String, WrappedCommuteFunction)]
- Darcs.Patch.Prim.V1.Core: instance Darcs.Patch.Witnesses.Eq.MyEq Darcs.Patch.Prim.V1.Core.DirPatchType
- Darcs.Patch.Prim.V1.Core: instance Darcs.Patch.Witnesses.Eq.MyEq Darcs.Patch.Prim.V1.Core.FilePatchType
- Darcs.Patch.Prim.V1.Core: instance Darcs.Patch.Witnesses.Eq.MyEq Darcs.Patch.Prim.V1.Core.Prim
- Darcs.Patch.Prim.V1.Read: instance Darcs.Patch.Read.ReadPatch Darcs.Patch.Prim.V1.Core.Prim
- Darcs.Patch.Prim.V1.Show: instance Darcs.Patch.Apply.ApplyState Darcs.Patch.Prim.V1.Core.Prim ~ Darcs.Util.Tree.Tree => Darcs.Patch.Show.ShowPatch Darcs.Patch.Prim.V1.Core.Prim
- Darcs.Patch.Prim.V1.Show: instance Darcs.Patch.Format.PatchListFormat Darcs.Patch.Prim.V1.Core.Prim
- Darcs.Patch.Prim.V1.Show: instance Darcs.Patch.Prim.Class.PrimShow Darcs.Patch.Prim.V1.Core.Prim
- Darcs.Patch.Prim.V1.Show: instance Darcs.Patch.Show.ShowPatchBasic Darcs.Patch.Prim.V1.Core.Prim
- Darcs.Patch.Rebase.Container: instance Darcs.Patch.Apply.Apply p => Darcs.Patch.Apply.Apply (Darcs.Patch.Rebase.Container.Suspended p)
- Darcs.Patch.Rebase.Container: instance Darcs.Patch.Apply.Apply p => Darcs.Patch.Repair.Repair (Darcs.Patch.Rebase.Container.Suspended p)
- Darcs.Patch.Rebase.Container: instance Darcs.Patch.Apply.Apply p => Darcs.Patch.Repair.RepairToFL (Darcs.Patch.Rebase.Container.Suspended p)
- Darcs.Patch.Rebase.Fixup: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Apply.Apply p, Darcs.Patch.Apply.ApplyState p ~ Darcs.Patch.Apply.ApplyState (Darcs.Patch.Prim.Class.PrimOf p)) => Darcs.Patch.Apply.Apply (Darcs.Patch.Rebase.Fixup.RebaseFixup p)
- Darcs.Patch.Rebase.Fixup: instance Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.Prim.Class.PrimOf p) => Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.Rebase.Fixup.RebaseFixup p)
- Darcs.Patch.Rebase.Name: instance Darcs.Patch.Apply.Apply p => Darcs.Patch.Apply.Apply (Darcs.Patch.Rebase.Name.RebaseName p)
- Darcs.Patch.Rebase.Name: instance Darcs.Patch.Apply.Apply p => Darcs.Patch.Patchy.Patchy (Darcs.Patch.Rebase.Name.RebaseName p)
- Darcs.Patch.Rebase.Name: instance Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.Rebase.Name.RebaseName p)
- Darcs.Patch.Rebase.Viewing: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Apply.Apply p, Darcs.Patch.Apply.ApplyState p ~ Darcs.Patch.Apply.ApplyState (Darcs.Patch.Prim.Class.PrimOf p), Darcs.Patch.Invert.Invert p) => Darcs.Patch.Patchy.Patchy (Darcs.Patch.Rebase.Viewing.RebaseChange p)
- Darcs.Patch.Rebase.Viewing: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Commute.Commute p, Darcs.Patch.Witnesses.Eq.MyEq p) => Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.Rebase.Viewing.RebaseSelect p)
- Darcs.Patch.Rebase.Viewing: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Conflict.Conflict p, Darcs.Patch.Prim.Class.FromPrim p, Darcs.Patch.Effect.Effect p, Darcs.Patch.Conflict.CommuteNoConflicts p, Darcs.Patch.FileHunk.IsHunk p, Darcs.Patch.Patchy.Patchy p, Darcs.Patch.Apply.ApplyState p ~ Darcs.Patch.Apply.ApplyState (Darcs.Patch.Prim.Class.PrimOf p)) => Darcs.Patch.Patchy.Patchy (Darcs.Patch.Rebase.Viewing.RebaseSelect p)
- Darcs.Patch.Rebase.Viewing: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Show.ShowPatchBasic p) => Darcs.Patch.Show.ShowPatchBasic (Darcs.Patch.Rebase.Viewing.RebaseChange p)
- Darcs.Patch.Rebase.Viewing: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Prim.Class.FromPrim p, Darcs.Patch.Conflict.Conflict p, Darcs.Patch.Conflict.CommuteNoConflicts p, Darcs.Patch.Invert.Invert p) => Darcs.Patch.Conflict.Conflict (Darcs.Patch.Rebase.Viewing.RebaseSelect p)
- Darcs.Patch.Rebase.Viewing: instance Darcs.Patch.FileHunk.IsHunk p => Darcs.Patch.FileHunk.IsHunk (Darcs.Patch.Rebase.Viewing.RebaseChange p)
- Darcs.Patch.Rebase.Viewing: instance Darcs.Patch.Invert.Invert p => Darcs.Patch.Invert.Invert (Darcs.Patch.Rebase.Viewing.RebaseSelect p)
- Darcs.Patch.Rebase.Viewing: instance Darcs.Patch.Read.ReadPatch p => Darcs.Patch.Read.ReadPatch (Darcs.Patch.Rebase.Viewing.RebaseSelect p)
- Darcs.Patch.Set: newset2FL :: PatchSet rt p wStart wX -> FL (PatchInfoAnd rt p) wStart wX
- Darcs.Patch.Set: newset2RL :: PatchSet rt p wStart wX -> RL (PatchInfoAnd rt p) wStart wX
- Darcs.Patch.Show: showNamedPrefix :: PatchInfo -> [PatchInfo] -> Doc
- Darcs.Patch.TokenReplace: breakOutToken :: String -> ByteString -> (ByteString, ByteString, ByteString)
- Darcs.Patch.TokenReplace: tryTokInternal :: String -> ByteString -> ByteString -> ByteString -> Maybe [ByteString]
- Darcs.Patch.V1: instance Darcs.Patch.Prim.Class.PrimPatch prim => Darcs.Patch.Patchy.Patchy (Darcs.Patch.V1.Core.RepoPatchV1 prim)
- Darcs.Patch.V1: instance Darcs.Patch.Prim.Class.PrimPatch prim => Darcs.Patch.RepoPatch.RepoPatch (Darcs.Patch.V1.Core.RepoPatchV1 prim)
- Darcs.Patch.V1.Commute: instance Darcs.Patch.Witnesses.Eq.MyEq prim => Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.V1.Core.RepoPatchV1 prim)
- Darcs.Patch.V1.Commute: instance Darcs.Patch.Witnesses.Eq.MyEq prim => GHC.Classes.Eq (Darcs.Patch.V1.Core.RepoPatchV1 prim wX wY)
- Darcs.Patch.V1.Viewing: instance Darcs.Patch.Prim.Class.PrimPatch prim => Darcs.Patch.Show.ShowPatchBasic (Darcs.Patch.V1.Core.RepoPatchV1 prim)
- Darcs.Patch.V2: instance Darcs.Patch.Prim.Class.PrimPatch prim => Darcs.Patch.RepoPatch.RepoPatch (Darcs.Patch.V2.RepoPatch.RepoPatchV2 prim)
- Darcs.Patch.V2: prim2repopatchV2 :: prim wX wY -> RepoPatchV2 prim wX wY
- Darcs.Patch.V2.Non: instance (Darcs.Patch.Commute.Commute p, Darcs.Patch.Witnesses.Eq.MyEq p, Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.Prim.Class.PrimOf p)) => GHC.Classes.Eq (Darcs.Patch.V2.Non.Non p wX)
- Darcs.Patch.V2.RepoPatch: instance Darcs.Patch.Prim.Class.PrimPatch prim => Darcs.Patch.Patchy.Patchy (Darcs.Patch.V2.RepoPatch.RepoPatchV2 prim)
- Darcs.Patch.V2.RepoPatch: instance Darcs.Patch.Prim.Class.PrimPatch prim => Darcs.Patch.Witnesses.Eq.MyEq (Darcs.Patch.V2.RepoPatch.RepoPatchV2 prim)
- Darcs.Patch.V2.RepoPatch: prim2repopatchV2 :: prim wX wY -> RepoPatchV2 prim wX wY
- Darcs.Patch.Viewing: instance (Darcs.Patch.Apply.Apply p, Darcs.Patch.FileHunk.IsHunk p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Show.ShowPatch p) => Darcs.Patch.Show.ShowPatch (Darcs.Patch.Witnesses.Ordered.FL p)
- Darcs.Patch.Viewing: instance (Darcs.Patch.Apply.Apply p, Darcs.Patch.FileHunk.IsHunk p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Show.ShowPatch p) => Darcs.Patch.Show.ShowPatch (Darcs.Patch.Witnesses.Ordered.RL p)
- Darcs.Patch.Viewing: showContextSeries :: forall p m wX wY. (Apply p, ShowPatch p, IsHunk p, ApplyMonad (ApplyState p) m) => FL p wX wY -> m Doc
- Darcs.Patch.Witnesses.Eq: class MyEq p where unsafeCompare a b = IsEq == (a =/\= unsafeCoerceP b) a =\/= b | unsafeCompare a b = unsafeCoerceP IsEq | otherwise = NotEq a =/\= b | IsEq == (a =\/= unsafeCoerceP b) = unsafeCoerceP IsEq | otherwise = NotEq
- Darcs.Patch.Witnesses.Ordered: data (:||:) a1 a2 wX wY
- Darcs.Patch.Witnesses.Ordered: instance (Darcs.Patch.Witnesses.Eq.MyEq a, Darcs.Patch.Witnesses.Eq.MyEq b) => Darcs.Patch.Witnesses.Eq.MyEq (a Darcs.Patch.Witnesses.Ordered.:> b)
- Darcs.Patch.Witnesses.Ordered: instance (Darcs.Patch.Witnesses.Eq.MyEq a, Darcs.Patch.Witnesses.Eq.MyEq b) => GHC.Classes.Eq ((Darcs.Patch.Witnesses.Ordered.:>) a b wX wY)
- Darcs.Patch.Witnesses.Sealed: instance Darcs.Patch.Witnesses.Eq.MyEq a => GHC.Classes.Eq (Darcs.Patch.Witnesses.Sealed.Sealed (a wX))
- Darcs.Repository: checkUnrelatedRepos :: RepoPatch p => Bool -> PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> IO ()
- Darcs.Repository: listFiles :: Bool -> IO [String]
- Darcs.Repository: listRegisteredFiles :: IO [String]
- Darcs.Repository: listUnregisteredFiles :: Bool -> IO [String]
- Darcs.Repository: patchSetToRepository :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR1 wU1 wR1 -> PatchSet rt p Origin wX -> UseCache -> RemoteDarcs -> IO ()
- Darcs.Repository: readRepoUsingSpecificInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => String -> Repository rt p wR wU wT -> IO (PatchSet rt p Origin wT)
- Darcs.Repository: unrecordedChangesWithPatches :: forall rt p wR wU wT wX. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => FL (PrimOf p) wX wT -> FL (PrimOf p) wT wT -> (UseIndex, ScanKnown, DiffAlgorithm) -> Repository rt p wR wU wT -> Maybe [SubPath] -> IO (FL (PrimOf p) wT wU)
- Darcs.Repository: withRepositoryDirectory :: UseCache -> String -> RepoJob a -> IO a
- Darcs.Repository.Cache: takeHash :: ByteString -> Maybe (String, ByteString)
- Darcs.Repository.Clone: createRepository :: PatchFormat -> WithWorkingDir -> WithPatchIndex -> IO ()
- Darcs.Repository.Clone: patchSetToRepository :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR1 wU1 wR1 -> PatchSet rt p Origin wX -> UseCache -> RemoteDarcs -> IO ()
- Darcs.Repository.HashedIO: RW :: RW
- Darcs.Repository.HashedIO: data RW
- Darcs.Repository.HashedIO: instance Darcs.Patch.ApplyMonad.ApplyMonad Darcs.Util.Tree.Tree (Darcs.Repository.HashedIO.HashedIO p)
- Darcs.Repository.HashedIO: instance Darcs.Patch.ApplyMonad.ApplyMonadTree (Darcs.Repository.HashedIO.HashedIO p)
- Darcs.Repository.HashedIO: type HashedIO p = StateT (HashDir RW p) IO
- Darcs.Repository.HashedRepo: addToSpecificInventory :: RepoPatch p => String -> Cache -> Compression -> PatchInfoAnd rt p wX wY -> IO FilePath
- Darcs.Repository.HashedRepo: addToTentativeInventory :: RepoPatch p => Cache -> Compression -> PatchInfoAnd rt p wX wY -> IO FilePath
- Darcs.Repository.HashedRepo: applyToTentativePristine :: (ApplyState p ~ Tree, Patchy p) => p wX wY -> IO ()
- Darcs.Repository.HashedRepo: cleanInventories :: Repository rt p wR wU wT -> IO ()
- Darcs.Repository.HashedRepo: cleanPatches :: Repository rt p wR wU wT -> IO ()
- Darcs.Repository.HashedRepo: cleanPristine :: Repository rt p wR wU wT -> IO ()
- Darcs.Repository.HashedRepo: copyHashedInventory :: RepoPatch p => Repository rt p wR wU wT -> RemoteDarcs -> String -> IO ()
- Darcs.Repository.HashedRepo: copyPartialsPristine :: FilePathLike fp => Cache -> String -> String -> [fp] -> IO ()
- Darcs.Repository.HashedRepo: copyPristine :: Cache -> String -> String -> WithWorkingDir -> IO ()
- Darcs.Repository.HashedRepo: filterDirContents :: FilePath -> (FilePath -> Bool) -> IO [FilePath]
- Darcs.Repository.HashedRepo: finalizeTentativeChanges :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Compression -> IO ()
- Darcs.Repository.HashedRepo: hashedInventory :: String
- Darcs.Repository.HashedRepo: inv2pris :: ByteString -> String
- Darcs.Repository.HashedRepo: inventoriesDir :: String
- Darcs.Repository.HashedRepo: listInventories :: IO [String]
- Darcs.Repository.HashedRepo: listInventoriesLocal :: IO [String]
- Darcs.Repository.HashedRepo: listInventoriesRepoDir :: String -> IO [String]
- Darcs.Repository.HashedRepo: listPatchesLocalBucketed :: String -> String -> IO [String]
- Darcs.Repository.HashedRepo: patchesDir :: String
- Darcs.Repository.HashedRepo: pris2inv :: String -> ByteString -> Doc
- Darcs.Repository.HashedRepo: pristineDir :: String
- Darcs.Repository.HashedRepo: readHashedPristineRoot :: Repository rt p wR wU wT -> IO (Maybe String)
- Darcs.Repository.HashedRepo: readPatchIds :: ByteString -> [(PatchInfo, String)]
- Darcs.Repository.HashedRepo: readRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> String -> IO (PatchSet rt p Origin wR)
- Darcs.Repository.HashedRepo: readRepoFromInventoryList :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Cache -> (Maybe String, [(PatchInfo, String)]) -> IO (SealedPatchSet rt p Origin)
- Darcs.Repository.HashedRepo: readRepoUsingSpecificInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => String -> Repository rt p wR wU wT -> String -> IO (PatchSet rt p Origin wS)
- Darcs.Repository.HashedRepo: readTentativeRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> String -> IO (PatchSet rt p Origin wT)
- Darcs.Repository.HashedRepo: removeFromTentativeInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Compression -> FL (PatchInfoAnd rt p) wX wT -> IO ()
- Darcs.Repository.HashedRepo: revertTentativeChanges :: IO ()
- Darcs.Repository.HashedRepo: set :: [String] -> Set ByteString
- Darcs.Repository.HashedRepo: unset :: Set ByteString -> [String]
- Darcs.Repository.HashedRepo: writeAndReadPatch :: (IsRepoType rt, RepoPatch p) => Cache -> Compression -> PatchInfoAnd rt p wX wY -> IO (PatchInfoAnd rt p wX wY)
- Darcs.Repository.HashedRepo: writePatchIfNecessary :: RepoPatch p => Cache -> Compression -> PatchInfoAnd rt p wX wY -> IO (PatchInfo, String)
- Darcs.Repository.HashedRepo: writeTentativeInventory :: RepoPatch p => Cache -> Compression -> PatchSet rt p Origin wX -> IO ()
- Darcs.Repository.Internal: BadRepository :: String -> IdentifyRepo rt p wR wU wT
- Darcs.Repository.Internal: DontMakeChanges :: MakeChanges
- Darcs.Repository.Internal: DontUpdatePristine :: UpdatePristine
- Darcs.Repository.Internal: DontUpdatePristineNorRevert :: UpdatePristine
- Darcs.Repository.Internal: GoodRepository :: (Repository rt p wR wU wT) -> IdentifyRepo rt p wR wU wT
- Darcs.Repository.Internal: MakeChanges :: MakeChanges
- Darcs.Repository.Internal: NonRepository :: String -> IdentifyRepo rt p wR wU wT
- Darcs.Repository.Internal: Repo :: !String -> !RepoFormat -> !Pristine -> Cache -> Repository wRecordedstate wUnrecordedstate wTentativestate
- Darcs.Repository.Internal: UpdatePristine :: UpdatePristine
- Darcs.Repository.Internal: amInHashedRepository :: WorkRepo -> IO (Either String ())
- Darcs.Repository.Internal: amInRepository :: WorkRepo -> IO (Either String ())
- Darcs.Repository.Internal: amNotInRepository :: WorkRepo -> IO (Either String ())
- Darcs.Repository.Internal: announceMergeConflicts :: (PrimPatch p, PatchInspect p) => String -> AllowConflicts -> ExternalMerge -> FL p wX wY -> IO Bool
- Darcs.Repository.Internal: applyToTentativePristine :: (ApplyState q ~ Tree, Effect q, Patchy q, ShowPatch q, PrimPatchBase q) => Repository rt p wR wU wT -> Verbosity -> q wT wY -> IO ()
- Darcs.Repository.Internal: applyToWorking :: (ApplyState (PrimOf p) ~ Tree, RepoPatch p) => Repository rt p wR wU wT -> Verbosity -> FL (PrimOf p) wU wY -> IO (Repository rt p wR wY wT)
- Darcs.Repository.Internal: checkUnrecordedConflicts :: forall rt p wT wY. RepoPatch p => UpdateWorking -> FL (WrappedNamed rt p) wT wY -> IO Bool
- Darcs.Repository.Internal: cleanRepository :: RepoPatch p => Repository rt p wR wU wT -> IO ()
- Darcs.Repository.Internal: createPartialsPristineDirectoryTree :: (FilePathLike fp, RepoPatch p) => Repository rt p wR wU wT -> [fp] -> FilePath -> IO ()
- Darcs.Repository.Internal: createPristineDirectoryTree :: RepoPatch p => Repository rt p wR wU wT -> FilePath -> WithWorkingDir -> IO ()
- Darcs.Repository.Internal: data IdentifyRepo rt p wR wU wT
- Darcs.Repository.Internal: data MakeChanges
- Darcs.Repository.Internal: data Repository (rt :: RepoType) (p :: * -> * -> *) wRecordedstate wUnrecordedstate wTentativestate
- Darcs.Repository.Internal: data UpdatePristine
- Darcs.Repository.Internal: finalizeRepositoryChanges :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> Compression -> IO ()
- Darcs.Repository.Internal: findRepository :: WorkRepo -> IO (Either String ())
- Darcs.Repository.Internal: identifyRepository :: forall rt p wR wU wT. UseCache -> String -> IO (Repository rt p wR wU wT)
- Darcs.Repository.Internal: identifyRepositoryFor :: forall rt p wR wU wT vR vU vT. RepoPatch p => Repository rt p wR wU wT -> UseCache -> String -> IO (Repository rt p vR vU vT)
- Darcs.Repository.Internal: instance GHC.Classes.Eq Darcs.Repository.Internal.MakeChanges
- Darcs.Repository.Internal: instance GHC.Classes.Eq Darcs.Repository.Internal.UpdatePristine
- Darcs.Repository.Internal: makeNewPending :: forall rt p wR wU wT wY. (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wT wY -> IO ()
- Darcs.Repository.Internal: maybeIdentifyRepository :: UseCache -> String -> IO (IdentifyRepo rt p wR wU wT)
- Darcs.Repository.Internal: prefsUrl :: Repository rt p wR wU wT -> String
- Darcs.Repository.Internal: readRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (PatchSet rt p Origin wR)
- Darcs.Repository.Internal: readRepoUsingSpecificInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => String -> Repository rt p wR wU wT -> IO (PatchSet rt p Origin wT)
- Darcs.Repository.Internal: readTentativeRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (PatchSet rt p Origin wT)
- Darcs.Repository.Internal: reorderInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wR -> Compression -> UpdateWorking -> Verbosity -> IO ()
- Darcs.Repository.Internal: repoPatchType :: Repository rt p wR wU wT -> PatchType rt p
- Darcs.Repository.Internal: repoXor :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wR -> IO SHA1
- Darcs.Repository.Internal: revertRepositoryChanges :: RepoPatch p => Repository rt p wR wU wT -> UpdateWorking -> IO ()
- Darcs.Repository.Internal: seekRepo :: IO (Maybe (Either String ()))
- Darcs.Repository.Internal: setScriptsExecutable :: IO ()
- Darcs.Repository.Internal: setScriptsExecutablePatches :: PatchInspect p => p wX wY -> IO ()
- Darcs.Repository.Internal: setTentativePending :: forall rt p wR wU wT wX wY. RepoPatch p => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wX wY -> IO ()
- Darcs.Repository.Internal: tentativelyAddPatch :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Compression -> Verbosity -> UpdateWorking -> PatchInfoAnd rt p wT wY -> IO (Repository rt p wR wU wY)
- Darcs.Repository.Internal: tentativelyAddPatch_ :: forall rt p wR wU wT wY. (RepoPatch p, ApplyState p ~ Tree) => UpdatePristine -> Repository rt p wR wU wT -> Compression -> Verbosity -> UpdateWorking -> PatchInfoAnd rt p wT wY -> IO (Repository rt p wR wU wY)
- Darcs.Repository.Internal: tentativelyAddPatches_ :: forall rt p wR wU wT wY. (RepoPatch p, ApplyState p ~ Tree) => UpdatePristine -> Repository rt p wR wU wT -> Compression -> Verbosity -> UpdateWorking -> FL (PatchInfoAnd rt p) wT wY -> IO (Repository rt p wR wU wY)
- Darcs.Repository.Internal: tentativelyAddToPending :: forall rt p wR wU wT wX wY. RepoPatch p => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wX wY -> IO ()
- Darcs.Repository.Internal: tentativelyRemoveFromPending :: forall rt p wR wU wT wX wY. (RepoPatch p) => Repository rt p wR wU wT -> UpdateWorking -> PatchInfoAnd rt p wX wY -> IO ()
- Darcs.Repository.Internal: tentativelyRemovePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Compression -> UpdateWorking -> FL (PatchInfoAnd rt p) wX wT -> IO (Repository rt p wR wU wX)
- Darcs.Repository.Internal: tentativelyRemovePatches_ :: forall rt p wR wU wT wX. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => UpdatePristine -> Repository rt p wR wU wT -> Compression -> UpdateWorking -> FL (PatchInfoAnd rt p) wX wT -> IO (Repository rt p wR wU wX)
- Darcs.Repository.Internal: tentativelyReplacePatches :: forall rt p wR wU wT wX. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Compression -> UpdateWorking -> Verbosity -> FL (PatchInfoAnd rt p) wX wT -> IO ()
- Darcs.Repository.Internal: unrevertUrl :: Repository rt p wR wU wT -> String
- Darcs.Repository.Internal: withRecorded :: RepoPatch p => Repository rt p wR wU wT -> ((AbsolutePath -> IO a) -> IO a) -> (AbsolutePath -> IO a) -> IO a
- Darcs.Repository.Internal: withTentative :: forall rt p a wR wU wT. (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> ((AbsolutePath -> IO a) -> IO a) -> (AbsolutePath -> IO a) -> IO a
- Darcs.Repository.InternalTypes: Repo :: !String -> !RepoFormat -> !Pristine -> Cache -> Repository wRecordedstate wUnrecordedstate wTentativestate
- Darcs.Repository.InternalTypes: data Pristine
- Darcs.Repository.InternalTypes: extractCache :: Repository rt p wR wU wT -> Cache
- Darcs.Repository.InternalTypes: instance GHC.Classes.Eq Darcs.Repository.InternalTypes.Pristine
- Darcs.Repository.InternalTypes: instance GHC.Show.Show Darcs.Repository.InternalTypes.Pristine
- Darcs.Repository.Job: withRepositoryDirectory :: UseCache -> String -> RepoJob a -> IO a
- Darcs.Repository.Match: getFirstMatch :: (ApplyMonad (ApplyState p) DefaultIO, IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> [MatchFlag] -> IO ()
- Darcs.Repository.Motd: getMotd :: String -> IO ByteString
- Darcs.Repository.Motd: showMotd :: String -> IO ()
- Darcs.Repository.Old: revertTentativeChanges :: IO ()
- Darcs.Repository.PatchIndex: canCreatePI :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO Bool
- Darcs.Repository.PatchIndex: filterPatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, a ~ PatchInfoAnd rt p) => Repository rt p wR wU wT -> [FilePath] -> [Sealed2 a] -> IO [Sealed2 a]
- Darcs.Repository.Pending: readNewPending :: RepoPatch p => Repository rt p wR wU wT -> IO (Sealed (FL (PrimOf p) wT))
- Darcs.Repository.Pending: readTentativePending :: RepoPatch p => Repository rt p wR wU wT -> IO (Sealed (FL (PrimOf p) wT))
- Darcs.Repository.Pending: writeNewPending :: RepoPatch p => Repository rt p wR wU wT -> FL (PrimOf p) wT wY -> IO ()
- Darcs.Repository.Pending: writeTentativePending :: RepoPatch p => Repository rt p wR wU wT -> FL (PrimOf p) wT wY -> IO ()
- Darcs.Repository.Prefs: binariesFileHelp :: [String]
- Darcs.Repository.Prefs: boringFileHelp :: [String]
- Darcs.Repository.Prefs: oldGlobalCacheDir :: IO (Maybe FilePath)
- Darcs.Repository.State: getMovesPs :: forall rt p wR wU wB prim. (PrimConstruct prim, PrimCanonize prim, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wR -> Maybe [SubPath] -> IO (FL prim wB wB)
- Darcs.Repository.State: getReplaces :: forall rt p wR wU wT wX. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree, wX ~ wR) => (UseIndex, ScanKnown, DiffAlgorithm) -> Repository rt p wR wU wT -> Maybe [SubPath] -> IO (Sealed (FL (PrimOf p) wX))
- Darcs.Repository.State: unrecordedChangesWithPatches :: forall rt p wR wU wT wX. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => FL (PrimOf p) wX wT -> FL (PrimOf p) wT wT -> (UseIndex, ScanKnown, DiffAlgorithm) -> Repository rt p wR wU wT -> Maybe [SubPath] -> IO (FL (PrimOf p) wT wU)
- Darcs.UI.ApplyPatches: (rt :: RepoType) :: Constraint;
- Darcs.UI.Commands: [commandGetArgPossibilities] :: DarcsCommand parsedFlags -> IO [String]
- Darcs.UI.Commands: getCommandHelp :: Maybe (DarcsCommand pf1) -> DarcsCommand pf2 -> String
- Darcs.UI.Commands: getCommandMiniHelp :: Maybe (DarcsCommand pf1) -> DarcsCommand pf2 -> String
- Darcs.UI.Commands: printDryRunMessageAndExit :: (RepoPatch p, ApplyState p ~ Tree) => String -> Verbosity -> Summary -> DryRun -> XmlOutput -> Bool -> FL (PatchInfoAnd rt p) wX wY -> IO ()
- Darcs.UI.Commands: subusage :: DarcsCommand pf -> String
- Darcs.UI.Commands: usage :: [CommandControl] -> String
- Darcs.UI.Commands: usageHelper :: [CommandControl] -> String
- Darcs.UI.Commands.Add: expandDirs :: Bool -> [SubPath] -> IO [SubPath]
- Darcs.UI.Commands.Optimize: doOptimizeHTTP :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO ()
- Darcs.UI.Commands.ShowBug: showBug :: DarcsCommand [DarcsFlag]
- Darcs.UI.Commands.Tag: getTags :: PatchSet rt p wW wR -> IO [String]
- Darcs.UI.Flags: AfterHash :: String -> DarcsFlag
- Darcs.UI.Flags: AfterPatch :: String -> DarcsFlag
- Darcs.UI.Flags: AfterPattern :: String -> DarcsFlag
- Darcs.UI.Flags: AfterTag :: String -> DarcsFlag
- Darcs.UI.Flags: All :: DarcsFlag
- Darcs.UI.Flags: AllowCaseOnly :: DarcsFlag
- Darcs.UI.Flags: AllowConflicts :: DarcsFlag
- Darcs.UI.Flags: AllowUnrelatedRepos :: DarcsFlag
- Darcs.UI.Flags: AllowWindowsReserved :: DarcsFlag
- Darcs.UI.Flags: AmendUnrecord :: DarcsFlag
- Darcs.UI.Flags: ApplyAs :: String -> DarcsFlag
- Darcs.UI.Flags: ApplyOnDisk :: DarcsFlag
- Darcs.UI.Flags: AskDeps :: DarcsFlag
- Darcs.UI.Flags: AskPosthook :: DarcsFlag
- Darcs.UI.Flags: AskPrehook :: DarcsFlag
- Darcs.UI.Flags: Author :: String -> DarcsFlag
- Darcs.UI.Flags: Backoff :: DarcsFlag
- Darcs.UI.Flags: Bisect :: DarcsFlag
- Darcs.UI.Flags: Boring :: DarcsFlag
- Darcs.UI.Flags: Cc :: String -> DarcsFlag
- Darcs.UI.Flags: ChangesToAllFiles :: DarcsFlag
- Darcs.UI.Flags: Charset :: String -> DarcsFlag
- Darcs.UI.Flags: Check :: DarcsFlag
- Darcs.UI.Flags: Complement :: DarcsFlag
- Darcs.UI.Flags: Complete :: DarcsFlag
- Darcs.UI.Flags: Compress :: DarcsFlag
- Darcs.UI.Flags: Context :: AbsolutePath -> DarcsFlag
- Darcs.UI.Flags: Count :: DarcsFlag
- Darcs.UI.Flags: Debug :: DarcsFlag
- Darcs.UI.Flags: DebugHTTP :: DarcsFlag
- Darcs.UI.Flags: DiffCmd :: String -> DarcsFlag
- Darcs.UI.Flags: DiffFlags :: String -> DarcsFlag
- Darcs.UI.Flags: Directories :: DarcsFlag
- Darcs.UI.Flags: Disable :: DarcsFlag
- Darcs.UI.Flags: DistName :: String -> DarcsFlag
- Darcs.UI.Flags: DistZip :: DarcsFlag
- Darcs.UI.Flags: DontAllowCaseOnly :: DarcsFlag
- Darcs.UI.Flags: DontAllowWindowsReserved :: DarcsFlag
- Darcs.UI.Flags: DontGrabDeps :: DarcsFlag
- Darcs.UI.Flags: DontIgnoreTimes :: DarcsFlag
- Darcs.UI.Flags: DontPromptForDependencies :: DarcsFlag
- Darcs.UI.Flags: DontRestrictPaths :: DarcsFlag
- Darcs.UI.Flags: DontRmLogFile :: DarcsFlag
- Darcs.UI.Flags: DontSetScriptsExecutable :: DarcsFlag
- Darcs.UI.Flags: DryRun :: DarcsFlag
- Darcs.UI.Flags: EditDescription :: DarcsFlag
- Darcs.UI.Flags: EditLongComment :: DarcsFlag
- Darcs.UI.Flags: ExactVersion :: DarcsFlag
- Darcs.UI.Flags: ExternalMerge :: String -> DarcsFlag
- Darcs.UI.Flags: Files :: DarcsFlag
- Darcs.UI.Flags: ForceReplace :: DarcsFlag
- Darcs.UI.Flags: Forward :: DarcsFlag
- Darcs.UI.Flags: GenContext :: DarcsFlag
- Darcs.UI.Flags: HappyForwarding :: DarcsFlag
- Darcs.UI.Flags: Hashed :: DarcsFlag
- Darcs.UI.Flags: Help :: DarcsFlag
- Darcs.UI.Flags: HumanReadable :: DarcsFlag
- Darcs.UI.Flags: IgnoreTimes :: DarcsFlag
- Darcs.UI.Flags: InReplyTo :: String -> DarcsFlag
- Darcs.UI.Flags: Interactive :: DarcsFlag
- Darcs.UI.Flags: Intersection :: DarcsFlag
- Darcs.UI.Flags: JustThisRepo :: DarcsFlag
- Darcs.UI.Flags: KeepDate :: DarcsFlag
- Darcs.UI.Flags: LastN :: Int -> DarcsFlag
- Darcs.UI.Flags: Lazy :: DarcsFlag
- Darcs.UI.Flags: LeaveTestDir :: DarcsFlag
- Darcs.UI.Flags: Linear :: DarcsFlag
- Darcs.UI.Flags: ListCommands :: DarcsFlag
- Darcs.UI.Flags: ListOptions :: DarcsFlag
- Darcs.UI.Flags: LogFile :: AbsolutePath -> DarcsFlag
- Darcs.UI.Flags: LookForAdds :: DarcsFlag
- Darcs.UI.Flags: LookForMoves :: DarcsFlag
- Darcs.UI.Flags: LookForReplaces :: DarcsFlag
- Darcs.UI.Flags: MachineReadable :: DarcsFlag
- Darcs.UI.Flags: Mail :: DarcsFlag
- Darcs.UI.Flags: MarkConflicts :: DarcsFlag
- Darcs.UI.Flags: MaxCount :: Int -> DarcsFlag
- Darcs.UI.Flags: Minimize :: DarcsFlag
- Darcs.UI.Flags: NoAllowConflicts :: DarcsFlag
- Darcs.UI.Flags: NoAmendUnrecord :: DarcsFlag
- Darcs.UI.Flags: NoAskDeps :: DarcsFlag
- Darcs.UI.Flags: NoCache :: DarcsFlag
- Darcs.UI.Flags: NoCompress :: DarcsFlag
- Darcs.UI.Flags: NoDirectories :: DarcsFlag
- Darcs.UI.Flags: NoEditDescription :: DarcsFlag
- Darcs.UI.Flags: NoEditLongComment :: DarcsFlag
- Darcs.UI.Flags: NoFiles :: DarcsFlag
- Darcs.UI.Flags: NoHTTPPipelining :: DarcsFlag
- Darcs.UI.Flags: NoHappyForwarding :: DarcsFlag
- Darcs.UI.Flags: NoKeepDate :: DarcsFlag
- Darcs.UI.Flags: NoLeaveTestDir :: DarcsFlag
- Darcs.UI.Flags: NoLookForAdds :: DarcsFlag
- Darcs.UI.Flags: NoLookForMoves :: DarcsFlag
- Darcs.UI.Flags: NoLookForReplaces :: DarcsFlag
- Darcs.UI.Flags: NoMinimize :: DarcsFlag
- Darcs.UI.Flags: NoPacks :: DarcsFlag
- Darcs.UI.Flags: NoPatchIndexFlag :: DarcsFlag
- Darcs.UI.Flags: NoPauseForGui :: DarcsFlag
- Darcs.UI.Flags: NoPending :: DarcsFlag
- Darcs.UI.Flags: NoPosthook :: DarcsFlag
- Darcs.UI.Flags: NoPrehook :: DarcsFlag
- Darcs.UI.Flags: NoRecursive :: DarcsFlag
- Darcs.UI.Flags: NoReorder :: DarcsFlag
- Darcs.UI.Flags: NoSetDefault :: DarcsFlag
- Darcs.UI.Flags: NoSign :: DarcsFlag
- Darcs.UI.Flags: NoSummary :: DarcsFlag
- Darcs.UI.Flags: NoTest :: DarcsFlag
- Darcs.UI.Flags: NonApply :: DarcsFlag
- Darcs.UI.Flags: NonForce :: DarcsFlag
- Darcs.UI.Flags: NonUnified :: DarcsFlag
- Darcs.UI.Flags: NonVerify :: DarcsFlag
- Darcs.UI.Flags: NormalVerbosity :: DarcsFlag
- Darcs.UI.Flags: NotInRemote :: (Maybe String) -> DarcsFlag
- Darcs.UI.Flags: NullFlag :: DarcsFlag
- Darcs.UI.Flags: NumberPatches :: DarcsFlag
- Darcs.UI.Flags: Once :: DarcsFlag
- Darcs.UI.Flags: OneTag :: String -> DarcsFlag
- Darcs.UI.Flags: OnlyChangesToFiles :: DarcsFlag
- Darcs.UI.Flags: Output :: AbsolutePathOrStd -> DarcsFlag
- Darcs.UI.Flags: OutputAutoName :: AbsolutePath -> DarcsFlag
- Darcs.UI.Flags: Packs :: DarcsFlag
- Darcs.UI.Flags: PatchIndexFlag :: DarcsFlag
- Darcs.UI.Flags: PatchIndexRange :: Int -> Int -> DarcsFlag
- Darcs.UI.Flags: PatchName :: String -> DarcsFlag
- Darcs.UI.Flags: PauseForGui :: DarcsFlag
- Darcs.UI.Flags: Pending :: DarcsFlag
- Darcs.UI.Flags: Pipe :: DarcsFlag
- Darcs.UI.Flags: PosthookCmd :: String -> DarcsFlag
- Darcs.UI.Flags: PrehookCmd :: String -> DarcsFlag
- Darcs.UI.Flags: PromptForDependencies :: DarcsFlag
- Darcs.UI.Flags: PromptLongComment :: DarcsFlag
- Darcs.UI.Flags: Quiet :: DarcsFlag
- Darcs.UI.Flags: ReadMarks :: String -> DarcsFlag
- Darcs.UI.Flags: Recursive :: DarcsFlag
- Darcs.UI.Flags: RemoteDarcsOpt :: String -> DarcsFlag
- Darcs.UI.Flags: RemoteRepo :: String -> DarcsFlag
- Darcs.UI.Flags: Reorder :: DarcsFlag
- Darcs.UI.Flags: Repair :: DarcsFlag
- Darcs.UI.Flags: Reply :: String -> DarcsFlag
- Darcs.UI.Flags: RestrictPaths :: DarcsFlag
- Darcs.UI.Flags: Reverse :: DarcsFlag
- Darcs.UI.Flags: RmLogFile :: DarcsFlag
- Darcs.UI.Flags: RunPosthook :: DarcsFlag
- Darcs.UI.Flags: RunPrehook :: DarcsFlag
- Darcs.UI.Flags: SelectAuthor :: DarcsFlag
- Darcs.UI.Flags: SendmailCmd :: String -> DarcsFlag
- Darcs.UI.Flags: SetDefault :: DarcsFlag
- Darcs.UI.Flags: SetScriptsExecutable :: DarcsFlag
- Darcs.UI.Flags: SeveralPatch :: String -> DarcsFlag
- Darcs.UI.Flags: SeveralPattern :: String -> DarcsFlag
- Darcs.UI.Flags: Sibling :: AbsolutePath -> DarcsFlag
- Darcs.UI.Flags: Sign :: DarcsFlag
- Darcs.UI.Flags: SignAs :: String -> DarcsFlag
- Darcs.UI.Flags: SignSSL :: String -> DarcsFlag
- Darcs.UI.Flags: SkipBoring :: DarcsFlag
- Darcs.UI.Flags: SkipConflicts :: DarcsFlag
- Darcs.UI.Flags: StoreInMemory :: DarcsFlag
- Darcs.UI.Flags: Subject :: String -> DarcsFlag
- Darcs.UI.Flags: Summary :: DarcsFlag
- Darcs.UI.Flags: TagName :: String -> DarcsFlag
- Darcs.UI.Flags: Target :: String -> DarcsFlag
- Darcs.UI.Flags: Test :: DarcsFlag
- Darcs.UI.Flags: Timings :: DarcsFlag
- Darcs.UI.Flags: Toks :: String -> DarcsFlag
- Darcs.UI.Flags: UMask :: String -> DarcsFlag
- Darcs.UI.Flags: UnCompress :: DarcsFlag
- Darcs.UI.Flags: Unified :: DarcsFlag
- Darcs.UI.Flags: Union :: DarcsFlag
- Darcs.UI.Flags: UpToTag :: String -> DarcsFlag
- Darcs.UI.Flags: UseFormat1 :: DarcsFlag
- Darcs.UI.Flags: UseFormat2 :: DarcsFlag
- Darcs.UI.Flags: UseMyersDiff :: DarcsFlag
- Darcs.UI.Flags: UseNoWorkingDir :: DarcsFlag
- Darcs.UI.Flags: UsePatienceDiff :: DarcsFlag
- Darcs.UI.Flags: UseWorkingDir :: DarcsFlag
- Darcs.UI.Flags: Verbose :: DarcsFlag
- Darcs.UI.Flags: Verify :: AbsolutePath -> DarcsFlag
- Darcs.UI.Flags: VerifySSL :: AbsolutePath -> DarcsFlag
- Darcs.UI.Flags: Version :: DarcsFlag
- Darcs.UI.Flags: WorkRepoUrl :: String -> DarcsFlag
- Darcs.UI.Flags: WriteMarks :: String -> DarcsFlag
- Darcs.UI.Flags: XMLOutput :: DarcsFlag
- Darcs.UI.Flags: compression :: Config -> Compression
- Darcs.UI.Flags: doAllowCaseOnly :: Config -> Bool
- Darcs.UI.Flags: doAllowWindowsReserved :: Config -> Bool
- Darcs.UI.Flags: doHappyForwarding :: Config -> Bool
- Darcs.UI.Flags: doReverse :: Config -> Bool
- Darcs.UI.Flags: getCharset :: Config -> Maybe String
- Darcs.UI.Flags: getReply :: Config -> Maybe String
- Darcs.UI.Flags: hasAuthor :: Config -> Maybe String
- Darcs.UI.Flags: hasSummary :: Summary -> Config -> Summary
- Darcs.UI.Flags: isUnified :: Config -> WithContext
- Darcs.UI.Flags: removeFromAmended :: Config -> Bool
- Darcs.UI.Flags: runPatchIndex :: Config -> WithPatchIndex
- Darcs.UI.Flags: showChangesOnlyToFiles :: Config -> Bool
- Darcs.UI.Flags: toMatchFlags :: Config -> [MatchFlag]
- Darcs.UI.Message.Send: aborted :: Doc
- Darcs.UI.Message.Send: aboutToEdit :: FilePath -> String
- Darcs.UI.Message.Send: cannotSendToSelf :: String
- Darcs.UI.Message.Send: charsetAborted :: Doc
- Darcs.UI.Message.Send: charsetCouldNotGuess :: String
- Darcs.UI.Message.Send: charsetUtf8MailDiffLocale :: String
- Darcs.UI.Message.Send: cmdDescription :: String
- Darcs.UI.Message.Send: cmdHelp :: String
- Darcs.UI.Message.Send: creatingPatch :: String -> Doc
- Darcs.UI.Message.Send: currentEncodingIs :: String -> String
- Darcs.UI.Message.Send: emailBackedUp :: String -> Doc
- Darcs.UI.Message.Send: noWorkingSendmail :: Doc
- Darcs.UI.Message.Send: nothingSendable :: Doc
- Darcs.UI.Message.Send: postingPatch :: String -> Doc
- Darcs.UI.Message.Send: promptCharSetWarning :: String -> String
- Darcs.UI.Message.Send: promptNoDescriptionChange :: String
- Darcs.UI.Message.Send: promptTarget :: String
- Darcs.UI.Message.Send: savedButNotSent :: String -> Doc
- Darcs.UI.Message.Send: selectionIs :: [Doc] -> Doc
- Darcs.UI.Message.Send: selectionIsNull :: Doc
- Darcs.UI.Message.Send: success :: String -> String -> Doc
- Darcs.UI.Message.Send: willSendTo :: DryRun -> [String] -> Doc
- Darcs.UI.Message.Send: wroteBundle :: FilePathLike a => a -> Doc
- Darcs.UI.Options.All: [_diffCmd] :: ExternalDiff -> Maybe String
- Darcs.UI.Options.All: [_diffOpts] :: ExternalDiff -> [String]
- Darcs.UI.Options.All: askdeps :: PrimDarcsOption Bool
- Darcs.UI.Options.All: conflicts :: AllowConflicts -> PrimDarcsOption (Maybe AllowConflicts)
- Darcs.UI.Options.All: diffing :: PrimDarcsOption (UseIndex, ScanKnown, DiffAlgorithm)
- Darcs.UI.Options.All: humanReadable :: PrimDarcsOption Bool
- Darcs.UI.Options.All: matchMaxcount :: PrimDarcsOption (Maybe Int)
- Darcs.UI.Options.All: partial :: PrimDarcsOption CloneKind
- Darcs.UI.Options.All: patchIndex :: PrimDarcsOption WithPatchIndex
- Darcs.UI.Options.All: reorderPatches :: PrimDarcsOption Bool
- Darcs.UI.Options.All: test :: PrimDarcsOption RunTest
- Darcs.UI.Options.All: unidiff :: PrimDarcsOption Bool
- Darcs.UI.Options.All: useExternalMerge :: PrimDarcsOption ExternalMerge
- Darcs.UI.Options.All: useWorkingDir :: PrimDarcsOption WithWorkingDir
- Darcs.UI.Options.All: workingRepoDir :: PrimDarcsOption (Maybe String)
- Darcs.UI.Options.All: xmloutput :: PrimDarcsOption XmlOutput
- Darcs.UI.Options.Flags: Target :: String -> DarcsFlag
- Darcs.Util.Bug: _bug :: BugStuff -> String -> a
- Darcs.Util.Bug: _bugDoc :: BugStuff -> Doc -> a
- Darcs.Util.Bug: _fromJust :: BugStuff -> Maybe a -> a
- Darcs.Util.Bug: _impossible :: BugStuff -> a
- Darcs.Util.ByteString: breakAfterNthNewline :: Int -> ByteString -> Maybe (ByteString, ByteString)
- Darcs.Util.ByteString: breakBeforeNthNewline :: Int -> ByteString -> (ByteString, ByteString)
- Darcs.Util.ByteString: decodeString :: String -> IO String
- Darcs.Util.ByteString: unsafeWithInternals :: ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a
- Darcs.Util.Crypt.SHA1: SHA1 :: !Word32 -> !Word32 -> !Word32 -> !Word32 -> !Word32 -> SHA1
- Darcs.Util.Crypt.SHA1: data SHA1
- Darcs.Util.Crypt.SHA1: instance Data.Binary.Class.Binary Darcs.Util.Crypt.SHA1.SHA1
- Darcs.Util.Crypt.SHA1: instance GHC.Classes.Eq Darcs.Util.Crypt.SHA1.SHA1
- Darcs.Util.Crypt.SHA1: instance GHC.Classes.Ord Darcs.Util.Crypt.SHA1.SHA1
- Darcs.Util.Crypt.SHA1: instance GHC.Show.Show Darcs.Util.Crypt.SHA1.SHA1
- Darcs.Util.Crypt.SHA1: sha1PS :: ByteString -> SHA1
- Darcs.Util.Crypt.SHA1: sha1Xor :: SHA1 -> SHA1 -> SHA1
- Darcs.Util.Crypt.SHA1: showAsHex :: Word32 -> String
- Darcs.Util.Crypt.SHA1: zero :: SHA1
- Darcs.Util.Crypt.SHA256: sha256sum :: ByteString -> String
- Darcs.Util.Environment: maybeGetEnv :: String -> IO (Maybe String)
- Darcs.Util.Hash: SHA1 :: !ByteString -> Hash
- Darcs.Util.Lock: appendToFile :: FilePathLike p => p -> (Handle -> IO ()) -> IO ()
- Darcs.Util.Lock: readLocaleFile :: FilePathLike p => p -> IO String
- Darcs.Util.Lock: worldReadableTemp :: String -> IO String
- Darcs.Util.Lock: writeLocaleFile :: FilePathLike p => p -> String -> IO ()
- Darcs.Util.Lock: writeToFile :: FilePathLike p => p -> (Handle -> IO ()) -> IO ()
- Darcs.Util.Path: Name :: ByteString -> Name
- Darcs.Util.Path: floatBS :: ByteString -> AnchoredPath
- Darcs.Util.Path: fn2niceps :: FileName -> ByteString
- Darcs.Util.Path: newtype Name
- Darcs.Util.Path: niceps2fn :: ByteString -> FileName
- Darcs.Util.Printer: Encode :: RenderMode
- Darcs.Util.Printer: Standard :: RenderMode
- Darcs.Util.Printer: data RenderMode
- Darcs.Util.Tree: SHA1 :: !ByteString -> Hash
- Darcs.Util.Tree.Monad: instance (GHC.Base.Functor m, GHC.Base.Monad m) => Darcs.Util.Tree.Monad.TreeRO (Darcs.Util.Tree.Monad.TreeMonad m)
- Darcs.Util.Tree.Monad: instance (GHC.Base.Functor m, GHC.Base.Monad m) => Darcs.Util.Tree.Monad.TreeRW (Darcs.Util.Tree.Monad.TreeMonad m)
+ Darcs.Patch: ForDisplay :: ShowPatchFor
+ Darcs.Patch: ForStorage :: ShowPatchFor
+ Darcs.Patch: data ShowPatchFor
+ Darcs.Patch: displayPatch :: ShowPatchBasic p => p wX wY -> Doc
+ Darcs.Patch.Annotate: annotateFile :: Annotate p => FL (PatchInfoAnd rt p) wX wY -> FileName -> ByteString -> AnnotateResult
+ Darcs.Patch.Annotate: class Annotate p
+ Darcs.Patch.Annotate: instance Darcs.Patch.Annotate.Annotate Darcs.Patch.Prim.FileUUID.Core.Prim
+ Darcs.Patch.Annotate: instance Darcs.Patch.Annotate.Annotate Darcs.Patch.Prim.V1.Core.Prim
+ Darcs.Patch.Annotate: instance Darcs.Patch.Annotate.Annotate p => Darcs.Patch.Annotate.Annotate (Darcs.Patch.Named.Named p)
+ Darcs.Patch.Annotate: instance Darcs.Patch.Annotate.Annotate p => Darcs.Patch.Annotate.Annotate (Darcs.Patch.Named.Wrapped.WrappedNamed rt p)
+ Darcs.Patch.Annotate: instance Darcs.Patch.Annotate.Annotate p => Darcs.Patch.Annotate.Annotate (Darcs.Patch.PatchInfoAnd.PatchInfoAnd rt p)
+ Darcs.Patch.Annotate: instance Darcs.Patch.Annotate.Annotate p => Darcs.Patch.Annotate.Annotate (Darcs.Patch.Witnesses.Ordered.FL p)
+ Darcs.Patch.Choices: forceMiddle :: Commute p => Label -> PatchChoices p wA wB -> PatchChoices p wA wB
+ Darcs.Patch.Choices: instance Darcs.Patch.Witnesses.Eq.Eq2 p => Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.Choices.LabelledPatch p)
+ Darcs.Patch.Choices: instance Darcs.Patch.Witnesses.Eq.Eq2 p => Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.Choices.PatchChoice p)
+ Darcs.Patch.Choices: labelPatches :: Maybe Label -> FL p wX wY -> FL (LabelledPatch p) wX wY
+ Darcs.Patch.Choices: mkPatchChoices :: FL (LabelledPatch p) wX wY -> PatchChoices p wX wY
+ Darcs.Patch.Choices: unLabel :: LabelledPatch p wX wY -> p wX wY
+ Darcs.Patch.Depends: patchSetIntersection :: Commute p => [SealedPatchSet rt p wStart] -> SealedPatchSet rt p wStart
+ Darcs.Patch.Depends: patchSetUnion :: (Merge p) => [SealedPatchSet rt p wStart] -> SealedPatchSet rt p wStart
+ Darcs.Patch.Dummy: instance Darcs.Patch.Annotate.Annotate Darcs.Patch.Dummy.DummyPatch
+ Darcs.Patch.Dummy: instance Darcs.Patch.Prim.Class.PrimPatchCommon Darcs.Patch.Dummy.DummyPrim
+ Darcs.Patch.Dummy: instance Darcs.Patch.Show.ShowContextPatch Darcs.Patch.Dummy.DummyPatch
+ Darcs.Patch.Dummy: instance Darcs.Patch.Show.ShowContextPatch Darcs.Patch.Dummy.DummyPrim
+ Darcs.Patch.Dummy: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.Dummy.DummyPatch
+ Darcs.Patch.Dummy: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.Dummy.DummyPrim
+ Darcs.Patch.Format: UserFormat :: FileNameFormat
+ Darcs.Patch.Format: instance GHC.Classes.Eq Darcs.Patch.Format.FileNameFormat
+ Darcs.Patch.Format: instance GHC.Show.Show Darcs.Patch.Format.FileNameFormat
+ Darcs.Patch.Index.Monad: applyToFileMods :: (Apply p, ApplyState p ~ Tree) => p wX wY -> Set FileName -> (Set FileName, [PatchMod FileName])
+ Darcs.Patch.Index.Monad: instance Control.Monad.State.Class.MonadState (Data.Set.Internal.Set Darcs.Util.Path.FileName, [Darcs.Patch.Index.Types.PatchMod Darcs.Util.Path.FileName]) Darcs.Patch.Index.Monad.FileModMonad
+ Darcs.Patch.Index.Monad: makePatchID :: PatchInfo -> PatchId
+ Darcs.Patch.Index.Types: zero :: PatchId
+ Darcs.Patch.Info: displayPatchInfo :: PatchInfo -> Doc
+ Darcs.Patch.Info: toXmlShort :: PatchInfo -> Doc
+ Darcs.Patch.Info: validAuthor :: String -> Bool
+ Darcs.Patch.Info: validAuthorPS :: ByteString -> Bool
+ Darcs.Patch.Info: validDate :: String -> Bool
+ Darcs.Patch.Info: validDatePS :: ByteString -> Bool
+ Darcs.Patch.Info: validLog :: String -> Bool
+ Darcs.Patch.Info: validLogPS :: ByteString -> Bool
+ Darcs.Patch.Invert: instance Darcs.Patch.Invert.Invert p => Darcs.Patch.Invert.Invert (p Darcs.Patch.Witnesses.Ordered.:> p)
+ Darcs.Patch.Match: haveNonrangeExplicitMatch :: forall rt p. (IsRepoType rt, Matchable p) => PatchType rt p -> [MatchFlag] -> Bool
+ Darcs.Patch.Match: instance GHC.Classes.Eq Darcs.Patch.Match.IncludeInternalPatches
+ Darcs.Patch.Merge: naturalMerge :: (Invert p, Commute p) => (p :\/: p) wX wY -> Maybe ((p :/\: p) wX wY)
+ Darcs.Patch.Merge: prop_mergeCommute :: (Eq2 p, Merge p) => (p :\/: p) wX wY -> Bool
+ Darcs.Patch.Merge: prop_mergeSymmetric :: (Eq2 p, Merge p) => (p :\/: p) wX wY -> Bool
+ Darcs.Patch.MonadProgress: instance GHC.Base.Monad m => Darcs.Patch.MonadProgress.MonadProgress (Darcs.Util.Tree.Monad.TreeMonad m)
+ Darcs.Patch.Named: instance (Darcs.Patch.Apply.Apply p, Darcs.Patch.FileHunk.IsHunk p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Show.ShowContextPatch p) => Darcs.Patch.Show.ShowContextPatch (Darcs.Patch.Named.Named p)
+ Darcs.Patch.Named: instance (Darcs.Patch.Commute.Commute p, Darcs.Patch.Witnesses.Eq.Eq2 p) => Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.Named.Named p)
+ Darcs.Patch.Named: instance (Darcs.Patch.Conflict.CommuteNoConflicts p, Darcs.Patch.Conflict.Conflict p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Show.ShowPatch p) => Darcs.Patch.Show.ShowPatch (Darcs.Patch.Named.Named p)
+ Darcs.Patch.Named: instance GHC.Classes.Eq Darcs.Patch.Named.ShowDepsFormat
+ Darcs.Patch.Named.Wrapped: instance (Darcs.Patch.Show.ShowContextPatch p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Apply.Apply p, Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.FileHunk.IsHunk p) => Darcs.Patch.Show.ShowContextPatch (Darcs.Patch.Named.Wrapped.WrappedNamed rt p)
+ Darcs.Patch.PatchInfoAnd: instance (Darcs.Patch.Apply.Apply p, Darcs.Patch.FileHunk.IsHunk p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Show.ShowContextPatch p) => Darcs.Patch.Show.ShowContextPatch (Darcs.Patch.PatchInfoAnd.PatchInfoAnd rt p)
+ Darcs.Patch.PatchInfoAnd: instance Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.PatchInfoAnd.PatchInfoAnd rt p)
+ Darcs.Patch.PatchInfoAnd: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.PatchInfoAnd.WPatchInfo
+ Darcs.Patch.Permutations: instance (Darcs.Patch.Witnesses.Eq.Eq2 p, Darcs.Patch.Commute.Commute p) => Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.Witnesses.Ordered.FL p)
+ Darcs.Patch.Permutations: instance (Darcs.Patch.Witnesses.Eq.Eq2 p, Darcs.Patch.Commute.Commute p) => Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.Witnesses.Ordered.RL p)
+ Darcs.Patch.Prim: class PrimCanonize prim
+ Darcs.Patch.Prim: class (Apply prim, Commute prim, Invert prim, Eq2 prim, IsHunk prim, PatchInspect prim, RepairToFL prim, Show2 prim, PrimConstruct prim, PrimCanonize prim, PrimClassify prim, PrimDetails prim, PrimApply prim) => PrimPatchCommon prim
+ Darcs.Patch.Prim: class PrimRead prim
+ Darcs.Patch.Prim: class PrimShow prim
+ Darcs.Patch.Prim: showPrimCtx :: (PrimShow prim, ApplyMonad (ApplyState prim) m) => FileNameFormat -> prim wA wB -> m Doc
+ Darcs.Patch.Prim.Class: class (Apply prim, Commute prim, Invert prim, Eq2 prim, IsHunk prim, PatchInspect prim, RepairToFL prim, Show2 prim, PrimConstruct prim, PrimCanonize prim, PrimClassify prim, PrimDetails prim, PrimApply prim) => PrimPatchCommon prim
+ Darcs.Patch.Prim.Class: showPrimCtx :: (PrimShow prim, ApplyMonad (ApplyState prim) m) => FileNameFormat -> prim wA wB -> m Doc
+ Darcs.Patch.Prim.FileUUID: instance Darcs.Patch.Prim.Class.PrimPatchCommon Darcs.Patch.Prim.FileUUID.Core.Prim
+ Darcs.Patch.Prim.FileUUID.Apply: hunkEdit :: Hunk wX wY -> FileContent -> FileContent
+ Darcs.Patch.Prim.FileUUID.Apply: instance GHC.Base.Monad m => Darcs.Patch.ApplyMonad.ApplyMonad Darcs.Patch.Prim.FileUUID.ObjectMap.ObjectMap (Control.Monad.Trans.State.Lazy.StateT (Darcs.Patch.Prim.FileUUID.ObjectMap.ObjectMap m) m)
+ Darcs.Patch.Prim.FileUUID.Apply: instance GHC.Base.Monad m => Darcs.Patch.ApplyMonad.ApplyMonadTrans Darcs.Patch.Prim.FileUUID.ObjectMap.ObjectMap m
+ Darcs.Patch.Prim.FileUUID.Apply: instance GHC.Base.Monad m => Darcs.Patch.Prim.FileUUID.Apply.ApplyMonadObjectMap (Control.Monad.Trans.State.Lazy.StateT (Darcs.Patch.Prim.FileUUID.ObjectMap.ObjectMap m) m)
+ Darcs.Patch.Prim.FileUUID.Core: H :: !Int -> !FileContent -> !FileContent -> Hunk wX wY
+ Darcs.Patch.Prim.FileUUID.Core: HM :: !UUID -> !Int -> !UUID -> !Int -> !FileContent -> HunkMove wX wY
+ Darcs.Patch.Prim.FileUUID.Core: L :: !UUID -> !Name -> Location
+ Darcs.Patch.Prim.FileUUID.Core: [HunkMove] :: !(HunkMove wX wY) -> Prim wX wY
+ Darcs.Patch.Prim.FileUUID.Core: data HunkMove wX wY
+ Darcs.Patch.Prim.FileUUID.Core: data Location
+ Darcs.Patch.Prim.FileUUID.Core: data Name
+ Darcs.Patch.Prim.FileUUID.Core: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.Prim.FileUUID.Core.Hunk
+ Darcs.Patch.Prim.FileUUID.Core: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.Prim.FileUUID.Core.HunkMove
+ Darcs.Patch.Prim.FileUUID.Core: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.Prim.FileUUID.Core.Prim
+ Darcs.Patch.Prim.FileUUID.Core: instance GHC.Classes.Eq (Darcs.Patch.Prim.FileUUID.Core.Hunk wX wY)
+ Darcs.Patch.Prim.FileUUID.Core: instance GHC.Classes.Eq (Darcs.Patch.Prim.FileUUID.Core.HunkMove wX wY)
+ Darcs.Patch.Prim.FileUUID.Core: instance GHC.Show.Show (Darcs.Patch.Prim.FileUUID.Core.HunkMove wX wY)
+ Darcs.Patch.Prim.FileUUID.Core: type FileContent = ByteString
+ Darcs.Patch.Prim.FileUUID.ObjectMap: L :: !UUID -> !Name -> Location
+ Darcs.Patch.Prim.FileUUID.ObjectMap: data Location
+ Darcs.Patch.Prim.FileUUID.ObjectMap: data Name
+ Darcs.Patch.Prim.FileUUID.ObjectMap: instance GHC.Classes.Eq Darcs.Patch.Prim.FileUUID.ObjectMap.Location
+ Darcs.Patch.Prim.FileUUID.ObjectMap: instance GHC.Show.Show Darcs.Patch.Prim.FileUUID.ObjectMap.Location
+ Darcs.Patch.Prim.FileUUID.ObjectMap: isBlob :: Object m -> Bool
+ Darcs.Patch.Prim.FileUUID.ObjectMap: isDirectory :: Object m -> Bool
+ Darcs.Patch.Prim.FileUUID.ObjectMap: type FileContent = ByteString
+ Darcs.Patch.Prim.FileUUID.Show: displayHunk :: Maybe UUID -> Hunk wX wY -> Doc
+ Darcs.Patch.Prim.FileUUID.Show: instance Darcs.Patch.Show.ShowContextPatch Darcs.Patch.Prim.FileUUID.Core.Prim
+ Darcs.Patch.Prim.V1: instance Darcs.Patch.Prim.Class.PrimPatchCommon Darcs.Patch.Prim.V1.Core.Prim
+ Darcs.Patch.Prim.V1.Commute: cleverCommute :: CommuteFunction -> CommuteFunction
+ Darcs.Patch.Prim.V1.Commute: commuteFiledir :: CommuteFunction
+ Darcs.Patch.Prim.V1.Commute: commuteFilepatches :: CommuteFunction
+ Darcs.Patch.Prim.V1.Commute: speedyCommute :: CommuteFunction
+ Darcs.Patch.Prim.V1.Commute: toPerhaps :: Maybe a -> Perhaps a
+ Darcs.Patch.Prim.V1.Commute: type CommuteFunction = forall wX wY. (Prim :> Prim) wX wY -> Perhaps ((Prim :> Prim) wX wY)
+ Darcs.Patch.Prim.V1.Core: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.Prim.V1.Core.DirPatchType
+ Darcs.Patch.Prim.V1.Core: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.Prim.V1.Core.FilePatchType
+ Darcs.Patch.Prim.V1.Core: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.Prim.V1.Core.Prim
+ Darcs.Patch.Prim.V1.Show: instance Darcs.Patch.Apply.ApplyState Darcs.Patch.Prim.V1.Core.Prim ~ Darcs.Util.Tree.Tree => Darcs.Patch.Prim.Class.PrimShow Darcs.Patch.Prim.V1.Core.Prim
+ Darcs.Patch.Rebase: dropAnyRebase :: forall rt p wA wB. IsRepoType rt => PatchSet rt p wA wB -> PatchSet rt p wA wB
+ Darcs.Patch.Rebase.Container: instance Darcs.Patch.Apply.Apply (Darcs.Patch.Rebase.Container.Suspended p)
+ Darcs.Patch.Rebase.Container: instance Darcs.Patch.Repair.Repair (Darcs.Patch.Rebase.Container.Suspended p)
+ Darcs.Patch.Rebase.Container: instance Darcs.Patch.Repair.RepairToFL (Darcs.Patch.Rebase.Container.Suspended p)
+ Darcs.Patch.Rebase.Fixup: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Apply.ApplyState p ~ Darcs.Patch.Apply.ApplyState (Darcs.Patch.Prim.Class.PrimOf p)) => Darcs.Patch.Apply.Apply (Darcs.Patch.Rebase.Fixup.RebaseFixup p)
+ Darcs.Patch.Rebase.Fixup: instance Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.Prim.Class.PrimOf p) => Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.Rebase.Fixup.RebaseFixup p)
+ Darcs.Patch.Rebase.Name: instance Darcs.Patch.Apply.Apply (Darcs.Patch.Rebase.Name.RebaseName p)
+ Darcs.Patch.Rebase.Name: instance Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.Rebase.Name.RebaseName p)
+ Darcs.Patch.Rebase.Viewing: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Commute.Commute p, Darcs.Patch.Witnesses.Eq.Eq2 p) => Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.Rebase.Viewing.RebaseSelect p)
+ Darcs.Patch.Rebase.Viewing: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Conflict.Conflict p, Darcs.Patch.Conflict.CommuteNoConflicts p, Darcs.Patch.Invert.Invert p) => Darcs.Patch.Conflict.Conflict (Darcs.Patch.Rebase.Viewing.RebaseSelect p)
+ Darcs.Patch.Rebase.Viewing: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Show.ShowPatchBasic p) => Darcs.Patch.Show.ShowContextPatch (Darcs.Patch.Rebase.Viewing.RebaseSelect p)
+ Darcs.Patch.Rebase.Viewing: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Show.ShowPatchBasic p) => Darcs.Patch.Show.ShowContextPatch (Darcs.Patch.Rebase.Viewing.RebaseChange p)
+ Darcs.Patch.Rebase.Viewing: instance (Darcs.Patch.Prim.Class.PrimPatchBase p, Darcs.Patch.Show.ShowPatchBasic p) => Darcs.Patch.Show.ShowPatchBasic (Darcs.Patch.Rebase.Viewing.RebaseChange p)
+ Darcs.Patch.Rebase.Viewing: instance Darcs.Patch.FileHunk.IsHunk (Darcs.Patch.Rebase.Viewing.RebaseChange p)
+ Darcs.Patch.Rebase.Viewing: instance Darcs.Patch.Invert.Invert (Darcs.Patch.Rebase.Viewing.RebaseSelect p)
+ Darcs.Patch.Rebase.Viewing: instance Darcs.Patch.Read.ReadPatch (Darcs.Patch.Rebase.Viewing.RebaseSelect p)
+ Darcs.Patch.Set: patchSet2FL :: PatchSet rt p wStart wX -> FL (PatchInfoAnd rt p) wStart wX
+ Darcs.Patch.Set: patchSet2RL :: PatchSet rt p wStart wX -> RL (PatchInfoAnd rt p) wStart wX
+ Darcs.Patch.Show: ForDisplay :: ShowPatchFor
+ Darcs.Patch.Show: ForStorage :: ShowPatchFor
+ Darcs.Patch.Show: class ShowPatchBasic p => ShowContextPatch p
+ Darcs.Patch.Show: data ShowPatchFor
+ Darcs.Patch.Show: displayPatch :: ShowPatchBasic p => p wX wY -> Doc
+ Darcs.Patch.TokenReplace: annotateReplace :: String -> ByteString -> ByteString -> ByteString -> Bool
+ Darcs.Patch.TokenReplace: tryTokReplace :: String -> ByteString -> ByteString -> ByteString -> Maybe ByteString
+ Darcs.Patch.V1: instance (Darcs.Patch.Prim.Class.PrimPatch prim, Darcs.Patch.Annotate.Annotate prim) => Darcs.Patch.RepoPatch.RepoPatch (Darcs.Patch.V1.Core.RepoPatchV1 prim)
+ Darcs.Patch.V1.Apply: instance (Darcs.Patch.Prim.Class.PrimPatch prim, Darcs.Patch.Annotate.Annotate prim) => Darcs.Patch.Annotate.Annotate (Darcs.Patch.V1.Core.RepoPatchV1 prim)
+ Darcs.Patch.V1.Commute: instance Darcs.Patch.Witnesses.Eq.Eq2 prim => Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.V1.Core.RepoPatchV1 prim)
+ Darcs.Patch.V1.Commute: instance Darcs.Patch.Witnesses.Eq.Eq2 prim => GHC.Classes.Eq (Darcs.Patch.V1.Core.RepoPatchV1 prim wX wY)
+ Darcs.Patch.V1.Prim: Prim :: Prim x y -> Prim x y
+ Darcs.Patch.V1.Prim: [unPrim] :: Prim x y -> Prim x y
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Annotate.Annotate Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Apply.Apply Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Commute.Commute Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.FileHunk.IsHunk Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Format.PatchListFormat Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Inspect.PatchInspect Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Invert.Invert Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Prim.Class.FromPrim Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Prim.Class.PrimApply Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Prim.Class.PrimCanonize Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Prim.Class.PrimClassify Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Prim.Class.PrimConstruct Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Prim.Class.PrimDetails Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Prim.Class.PrimPatch Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Prim.Class.PrimPatchBase Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Prim.Class.PrimPatchCommon Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Prim.Class.ToFromPrim Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Read.ReadPatch Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Repair.RepairToFL Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Show.ShowContextPatch Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Show.ShowPatch Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Show.ShowPatchBasic Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Witnesses.Show.Show1 (Darcs.Patch.V1.Prim.Prim wX)
+ Darcs.Patch.V1.Prim: instance Darcs.Patch.Witnesses.Show.Show2 Darcs.Patch.V1.Prim.Prim
+ Darcs.Patch.V1.Prim: instance GHC.Show.Show (Darcs.Patch.V1.Prim.Prim wX wY)
+ Darcs.Patch.V1.Prim: newtype Prim x y
+ Darcs.Patch.V1.Show: instance Darcs.Patch.Show.ShowPatchBasic prim => Darcs.Patch.Show.ShowPatchBasic (Darcs.Patch.V1.Core.RepoPatchV1 prim)
+ Darcs.Patch.V1.Viewing: instance Darcs.Patch.Prim.Class.PrimPatch prim => Darcs.Patch.Show.ShowContextPatch (Darcs.Patch.V1.Core.RepoPatchV1 prim)
+ Darcs.Patch.V2: instance (Darcs.Patch.Prim.Class.PrimPatch prim, Darcs.Patch.Annotate.Annotate prim) => Darcs.Patch.RepoPatch.RepoPatch (Darcs.Patch.V2.RepoPatch.RepoPatchV2 prim)
+ Darcs.Patch.V2.Non: instance (Darcs.Patch.Commute.Commute p, Darcs.Patch.Witnesses.Eq.Eq2 p, Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.Prim.Class.PrimOf p)) => GHC.Classes.Eq (Darcs.Patch.V2.Non.Non p wX)
+ Darcs.Patch.V2.Prim: Prim :: Prim x y -> Prim x y
+ Darcs.Patch.V2.Prim: [unPrim] :: Prim x y -> Prim x y
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Annotate.Annotate Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Apply.Apply Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Commute.Commute Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.FileHunk.IsHunk Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Format.PatchListFormat Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Inspect.PatchInspect Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Invert.Invert Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Prim.Class.FromPrim Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Prim.Class.PrimApply Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Prim.Class.PrimCanonize Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Prim.Class.PrimClassify Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Prim.Class.PrimConstruct Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Prim.Class.PrimDetails Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Prim.Class.PrimPatch Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Prim.Class.PrimPatchBase Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Prim.Class.PrimPatchCommon Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Prim.Class.ToFromPrim Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Read.ReadPatch Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Repair.RepairToFL Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Show.ShowContextPatch Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Show.ShowPatch Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Show.ShowPatchBasic Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Witnesses.Eq.Eq2 Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Witnesses.Show.Show1 (Darcs.Patch.V2.Prim.Prim wX)
+ Darcs.Patch.V2.Prim: instance Darcs.Patch.Witnesses.Show.Show2 Darcs.Patch.V2.Prim.Prim
+ Darcs.Patch.V2.Prim: instance GHC.Show.Show (Darcs.Patch.V2.Prim.Prim wX wY)
+ Darcs.Patch.V2.Prim: newtype Prim x y
+ Darcs.Patch.V2.RepoPatch: instance (Darcs.Patch.Prim.Class.PrimPatch prim, Darcs.Patch.Annotate.Annotate prim) => Darcs.Patch.Annotate.Annotate (Darcs.Patch.V2.RepoPatch.RepoPatchV2 prim)
+ Darcs.Patch.V2.RepoPatch: instance Darcs.Patch.Prim.Class.PrimPatch prim => Darcs.Patch.Show.ShowContextPatch (Darcs.Patch.V2.RepoPatch.RepoPatchV2 prim)
+ Darcs.Patch.V2.RepoPatch: instance Darcs.Patch.Prim.Class.PrimPatch prim => Darcs.Patch.Witnesses.Eq.Eq2 (Darcs.Patch.V2.RepoPatch.RepoPatchV2 prim)
+ Darcs.Patch.Viewing: instance (Darcs.Patch.Apply.Apply p, Darcs.Patch.FileHunk.IsHunk p, Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Show.ShowContextPatch p) => Darcs.Patch.Show.ShowContextPatch (Darcs.Patch.Witnesses.Ordered.FL p)
+ Darcs.Patch.Viewing: instance (Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Show.ShowPatch p) => Darcs.Patch.Show.ShowPatch (Darcs.Patch.Witnesses.Ordered.FL p)
+ Darcs.Patch.Viewing: instance (Darcs.Patch.Format.PatchListFormat p, Darcs.Patch.Show.ShowPatch p) => Darcs.Patch.Show.ShowPatch (Darcs.Patch.Witnesses.Ordered.RL p)
+ Darcs.Patch.Viewing: instance (Darcs.Patch.Show.ShowContextPatch p, Darcs.Patch.Apply.Apply p, Darcs.Patch.FileHunk.IsHunk p, Darcs.Patch.Format.PatchListFormat p) => Darcs.Patch.Show.ShowContextPatch (Darcs.Patch.Witnesses.Ordered.RL p)
+ Darcs.Patch.Witnesses.Eq: class Eq2 p
+ Darcs.Patch.Witnesses.Ordered: (+<<+) :: RL p wX wY -> FL p wY wZ -> RL p wX wZ
+ Darcs.Patch.Witnesses.Ordered: (+>>+) :: RL p wX wY -> FL p wY wZ -> FL p wX wZ
+ Darcs.Patch.Witnesses.Ordered: allRL :: (forall wA wB. a wA wB -> Bool) -> RL a wX wY -> Bool
+ Darcs.Patch.Witnesses.Ordered: anyRL :: (forall wA wB. a wA wB -> Bool) -> RL a wX wY -> Bool
+ Darcs.Patch.Witnesses.Ordered: data a1 (:||:) a2 wX wY
+ Darcs.Patch.Witnesses.Ordered: data a3 (:/\:) a4 wX wY
+ Darcs.Patch.Witnesses.Ordered: foldFL_M :: Monad m => (forall wA wB. r wA -> p wA wB -> m (r wB)) -> r wX -> FL p wX wY -> m (r wY)
+ Darcs.Patch.Witnesses.Ordered: initsFL :: FL p wX wY -> [Sealed ((p :> FL p) wX)]
+ Darcs.Patch.Witnesses.Ordered: instance (Darcs.Patch.Witnesses.Eq.Eq2 a, Darcs.Patch.Witnesses.Eq.Eq2 b) => Darcs.Patch.Witnesses.Eq.Eq2 (a Darcs.Patch.Witnesses.Ordered.:> b)
+ Darcs.Patch.Witnesses.Ordered: instance (Darcs.Patch.Witnesses.Eq.Eq2 a, Darcs.Patch.Witnesses.Eq.Eq2 b) => GHC.Classes.Eq ((Darcs.Patch.Witnesses.Ordered.:>) a b wX wY)
+ Darcs.Patch.Witnesses.Ordered: sequenceFL_ :: Monad m => (forall wW wZ. a wW wZ -> m b) -> FL a wX wY -> m ()
+ Darcs.Patch.Witnesses.Sealed: instance Darcs.Patch.Witnesses.Eq.Eq2 a => GHC.Classes.Eq (Darcs.Patch.Witnesses.Sealed.Sealed (a wX))
+ Darcs.Prelude: bug :: String -> a
+ Darcs.Prelude: impossible :: a
+ Darcs.Repository: HashedPristine :: PristineType
+ Darcs.Repository: NoPristine :: PristineType
+ Darcs.Repository: PlainPristine :: PristineType
+ Darcs.Repository: [EmptyRepository] :: (RepoPatch p, ApplyState p ~ Tree) => Repository ( 'RepoType 'NoRebase) p Origin Origin Origin -> EmptyRepository
+ Darcs.Repository: createRepositoryV1 :: WithWorkingDir -> WithPatchIndex -> UseCache -> IO (Repository ( 'RepoType 'NoRebase) (RepoPatchV1 Prim) Origin Origin Origin)
+ Darcs.Repository: createRepositoryV2 :: WithWorkingDir -> WithPatchIndex -> UseCache -> IO (Repository ( 'RepoType 'NoRebase) (RepoPatchV2 Prim) Origin Origin Origin)
+ Darcs.Repository: data EmptyRepository
+ Darcs.Repository: data PristineType
+ Darcs.Repository: repoCache :: Repository rt p wR wU wT -> Cache
+ Darcs.Repository: repoFormat :: Repository rt p wR wU wT -> RepoFormat
+ Darcs.Repository: repoLocation :: Repository rt p wR wU wT -> String
+ Darcs.Repository: repoPristineType :: Repository rt p wR wU wT -> PristineType
+ Darcs.Repository: withRepositoryLocation :: UseCache -> String -> RepoJob a -> IO a
+ Darcs.Repository: withUMaskFlag :: UMask -> IO a -> IO a
+ Darcs.Repository.Create: [EmptyRepository] :: (RepoPatch p, ApplyState p ~ Tree) => Repository ( 'RepoType 'NoRebase) p Origin Origin Origin -> EmptyRepository
+ Darcs.Repository.Create: createRepository :: PatchFormat -> WithWorkingDir -> WithPatchIndex -> UseCache -> IO EmptyRepository
+ Darcs.Repository.Create: createRepositoryV1 :: WithWorkingDir -> WithPatchIndex -> UseCache -> IO (Repository ( 'RepoType 'NoRebase) (RepoPatchV1 Prim) Origin Origin Origin)
+ Darcs.Repository.Create: createRepositoryV2 :: WithWorkingDir -> WithPatchIndex -> UseCache -> IO (Repository ( 'RepoType 'NoRebase) (RepoPatchV2 Prim) Origin Origin Origin)
+ Darcs.Repository.Create: data EmptyRepository
+ Darcs.Repository.Create: writePristine :: FilePath -> Tree IO -> IO ()
+ Darcs.Repository.Flags: HookConfig :: Maybe String -> Bool -> HookConfig
+ Darcs.Repository.Flags: HooksConfig :: HookConfig -> HookConfig -> HooksConfig
+ Darcs.Repository.Flags: [cmd] :: HookConfig -> Maybe String
+ Darcs.Repository.Flags: [post] :: HooksConfig -> HookConfig
+ Darcs.Repository.Flags: [pre] :: HooksConfig -> HookConfig
+ Darcs.Repository.Flags: [prompt] :: HookConfig -> Bool
+ Darcs.Repository.Flags: data HookConfig
+ Darcs.Repository.Flags: data HooksConfig
+ Darcs.Repository.Hashed: DontUpdatePristine :: UpdatePristine
+ Darcs.Repository.Hashed: DontUpdatePristineNorRevert :: UpdatePristine
+ Darcs.Repository.Hashed: UpdatePristine :: UpdatePristine
+ Darcs.Repository.Hashed: addToTentativeInventory :: RepoPatch p => Cache -> Compression -> PatchInfoAnd rt p wX wY -> IO FilePath
+ Darcs.Repository.Hashed: applyToTentativePristine :: (ApplyState q ~ Tree, Apply q, ShowPatch q) => Repository rt p wR wU wT -> Verbosity -> q wT wY -> IO ()
+ Darcs.Repository.Hashed: applyToTentativePristineCwd :: (ApplyState p ~ Tree, Apply p) => p wX wY -> IO ()
+ Darcs.Repository.Hashed: cleanInventories :: Repository rt p wR wU wT -> IO ()
+ Darcs.Repository.Hashed: cleanPatches :: Repository rt p wR wU wT -> IO ()
+ Darcs.Repository.Hashed: cleanPristine :: Repository rt p wR wU wT -> IO ()
+ Darcs.Repository.Hashed: cleanRepository :: Repository rt p wR wU wT -> IO ()
+ Darcs.Repository.Hashed: copyHashedInventory :: Repository rt p wR wU wT -> RemoteDarcs -> String -> IO ()
+ Darcs.Repository.Hashed: copyPartialsPristine :: FilePathLike fp => Cache -> String -> String -> [fp] -> IO ()
+ Darcs.Repository.Hashed: copyPristine :: Cache -> String -> String -> WithWorkingDir -> IO ()
+ Darcs.Repository.Hashed: createPartialsPristineDirectoryTree :: (FilePathLike fp) => Repository rt p wR wU wT -> [fp] -> FilePath -> IO ()
+ Darcs.Repository.Hashed: createPristineDirectoryTree :: Repository rt p wR wU wT -> FilePath -> WithWorkingDir -> IO ()
+ Darcs.Repository.Hashed: data UpdatePristine
+ Darcs.Repository.Hashed: diffHashLists :: [String] -> [String] -> [String]
+ Darcs.Repository.Hashed: filterDirContents :: FilePath -> (FilePath -> Bool) -> IO [FilePath]
+ Darcs.Repository.Hashed: finalizeRepositoryChanges :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> Compression -> IO ()
+ Darcs.Repository.Hashed: finalizeTentativeChanges :: (IsRepoType rt, RepoPatch p) => Repository rt p wR wU wT -> Compression -> IO ()
+ Darcs.Repository.Hashed: hashedInventory :: String
+ Darcs.Repository.Hashed: hashedInventoryPath :: String
+ Darcs.Repository.Hashed: instance GHC.Classes.Eq Darcs.Repository.Hashed.UpdatePristine
+ Darcs.Repository.Hashed: inventoriesDir :: String
+ Darcs.Repository.Hashed: inventoriesDirPath :: String
+ Darcs.Repository.Hashed: listInventories :: IO [String]
+ Darcs.Repository.Hashed: listInventoriesLocal :: IO [String]
+ Darcs.Repository.Hashed: listInventoriesRepoDir :: String -> IO [String]
+ Darcs.Repository.Hashed: listPatchesLocalBucketed :: String -> String -> IO [String]
+ Darcs.Repository.Hashed: patchesDir :: String
+ Darcs.Repository.Hashed: patchesDirPath :: String
+ Darcs.Repository.Hashed: peekPristineHash :: ByteString -> String
+ Darcs.Repository.Hashed: pokePristineHash :: String -> ByteString -> Doc
+ Darcs.Repository.Hashed: pristineDir :: String
+ Darcs.Repository.Hashed: pristineDirPath :: String
+ Darcs.Repository.Hashed: readHashedPristineRoot :: Repository rt p wR wU wT -> IO (Maybe String)
+ Darcs.Repository.Hashed: readRepo :: (IsRepoType rt, RepoPatch p) => Repository rt p wR wU wT -> IO (PatchSet rt p Origin wR)
+ Darcs.Repository.Hashed: readRepoHashed :: (IsRepoType rt, RepoPatch p) => Repository rt p wR wU wT -> String -> IO (PatchSet rt p Origin wR)
+ Darcs.Repository.Hashed: readTentativeRepo :: (IsRepoType rt, RepoPatch p) => Repository rt p wR wU wT -> String -> IO (PatchSet rt p Origin wT)
+ Darcs.Repository.Hashed: reorderInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wR -> Compression -> UpdateWorking -> Verbosity -> IO ()
+ Darcs.Repository.Hashed: repoXor :: (IsRepoType rt, RepoPatch p) => Repository rt p wR wU wR -> IO SHA1
+ Darcs.Repository.Hashed: revertRepositoryChanges :: RepoPatch p => Repository rt p wR wU wT -> UpdateWorking -> IO ()
+ Darcs.Repository.Hashed: revertTentativeChanges :: IO ()
+ Darcs.Repository.Hashed: tentativelyAddPatch :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Compression -> Verbosity -> UpdateWorking -> PatchInfoAnd rt p wT wY -> IO (Repository rt p wR wU wY)
+ Darcs.Repository.Hashed: tentativelyAddPatch_ :: (RepoPatch p, ApplyState p ~ Tree) => UpdatePristine -> Repository rt p wR wU wT -> Compression -> Verbosity -> UpdateWorking -> PatchInfoAnd rt p wT wY -> IO (Repository rt p wR wU wY)
+ Darcs.Repository.Hashed: tentativelyAddPatches_ :: (RepoPatch p, ApplyState p ~ Tree) => UpdatePristine -> Repository rt p wR wU wT -> Compression -> Verbosity -> UpdateWorking -> FL (PatchInfoAnd rt p) wT wY -> IO (Repository rt p wR wU wY)
+ Darcs.Repository.Hashed: tentativelyRemovePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Compression -> UpdateWorking -> FL (PatchInfoAnd rt p) wX wT -> IO (Repository rt p wR wU wX)
+ Darcs.Repository.Hashed: tentativelyRemovePatches_ :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => UpdatePristine -> Repository rt p wR wU wT -> Compression -> UpdateWorking -> FL (PatchInfoAnd rt p) wX wT -> IO (Repository rt p wR wU wX)
+ Darcs.Repository.Hashed: tentativelyReplacePatches :: forall rt p wR wU wT wX. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Compression -> UpdateWorking -> Verbosity -> FL (PatchInfoAnd rt p) wX wT -> IO ()
+ Darcs.Repository.Hashed: unrevertUrl :: Repository rt p wR wU wT -> String
+ Darcs.Repository.Hashed: withRecorded :: Repository rt p wR wU wT -> ((AbsolutePath -> IO a) -> IO a) -> (AbsolutePath -> IO a) -> IO a
+ Darcs.Repository.Hashed: withTentative :: forall rt p a wR wU wT. Repository rt p wR wU wT -> ((AbsolutePath -> IO a) -> IO a) -> (AbsolutePath -> IO a) -> IO a
+ Darcs.Repository.Hashed: writeAndReadPatch :: (IsRepoType rt, RepoPatch p) => Cache -> Compression -> PatchInfoAnd rt p wX wY -> IO (PatchInfoAnd rt p wX wY)
+ Darcs.Repository.Hashed: writePatchIfNecessary :: RepoPatch p => Cache -> Compression -> PatchInfoAnd rt p wX wY -> IO InventoryEntry
+ Darcs.Repository.Hashed: writeTentativeInventory :: RepoPatch p => Cache -> Compression -> PatchSet rt p Origin wX -> IO ()
+ Darcs.Repository.HashedIO: instance Darcs.Patch.ApplyMonad.ApplyMonad Darcs.Util.Tree.Tree Darcs.Repository.HashedIO.HashedIO
+ Darcs.Repository.HashedIO: instance Darcs.Patch.ApplyMonad.ApplyMonadTree Darcs.Repository.HashedIO.HashedIO
+ Darcs.Repository.Identify: BadRepository :: String -> IdentifyRepo rt p wR wU wT
+ Darcs.Repository.Identify: GoodRepository :: (Repository rt p wR wU wT) -> IdentifyRepo rt p wR wU wT
+ Darcs.Repository.Identify: NonRepository :: String -> IdentifyRepo rt p wR wU wT
+ Darcs.Repository.Identify: amInHashedRepository :: WorkRepo -> IO (Either String ())
+ Darcs.Repository.Identify: amInRepository :: WorkRepo -> IO (Either String ())
+ Darcs.Repository.Identify: amNotInRepository :: WorkRepo -> IO (Either String ())
+ Darcs.Repository.Identify: data IdentifyRepo rt p wR wU wT
+ Darcs.Repository.Identify: findAllReposInDir :: FilePath -> IO [FilePath]
+ Darcs.Repository.Identify: findRepository :: WorkRepo -> IO (Either String ())
+ Darcs.Repository.Identify: identifyRepository :: forall rt p wR wU wT. UseCache -> String -> IO (Repository rt p wR wU wT)
+ Darcs.Repository.Identify: identifyRepositoryFor :: forall rt p wR wU wT vR vU vT. Repository rt p wR wU wT -> UseCache -> String -> IO (Repository rt p vR vU vT)
+ Darcs.Repository.Identify: maybeIdentifyRepository :: UseCache -> String -> IO (IdentifyRepo rt p wR wU wT)
+ Darcs.Repository.Identify: seekRepo :: IO (Maybe (Either String ()))
+ Darcs.Repository.InternalTypes: coerceR :: Repository rt p wR wU wT -> Repository rt p wR' wU wT
+ Darcs.Repository.InternalTypes: coerceT :: Repository rt p wR wU wT -> Repository rt p wR wU wT'
+ Darcs.Repository.InternalTypes: coerceU :: Repository rt p wR wU wT -> Repository rt p wR wU' wT
+ Darcs.Repository.InternalTypes: data PristineType
+ Darcs.Repository.InternalTypes: instance GHC.Classes.Eq Darcs.Repository.InternalTypes.PristineType
+ Darcs.Repository.InternalTypes: instance GHC.Show.Show Darcs.Repository.InternalTypes.PristineType
+ Darcs.Repository.InternalTypes: mkRepo :: String -> RepoFormat -> PristineType -> Cache -> Repository rt p wR wU wT
+ Darcs.Repository.InternalTypes: repoCache :: Repository rt p wR wU wT -> Cache
+ Darcs.Repository.InternalTypes: repoFormat :: Repository rt p wR wU wT -> RepoFormat
+ Darcs.Repository.InternalTypes: repoLocation :: Repository rt p wR wU wT -> String
+ Darcs.Repository.InternalTypes: repoPatchType :: Repository rt p wR wU wT -> PatchType rt p
+ Darcs.Repository.InternalTypes: repoPristineType :: Repository rt p wR wU wT -> PristineType
+ Darcs.Repository.InternalTypes: withRepoLocation :: Repository rt p wR wU wT -> IO a -> IO a
+ Darcs.Repository.Inventory: Inventory :: Maybe InventoryHash -> [InventoryEntry] -> Inventory
+ Darcs.Repository.Inventory: [inventoryParent] :: Inventory -> Maybe InventoryHash
+ Darcs.Repository.Inventory: [inventoryPatches] :: Inventory -> [InventoryEntry]
+ Darcs.Repository.Inventory: class ValidHash a
+ Darcs.Repository.Inventory: data Inventory
+ Darcs.Repository.Inventory: data InventoryHash
+ Darcs.Repository.Inventory: data PatchHash
+ Darcs.Repository.Inventory: data PristineHash
+ Darcs.Repository.Inventory: emptyInventory :: Inventory
+ Darcs.Repository.Inventory: getValidHash :: ValidHash a => a -> String
+ Darcs.Repository.Inventory: instance Darcs.Repository.Inventory.ValidHash Darcs.Repository.Inventory.InventoryHash
+ Darcs.Repository.Inventory: instance Darcs.Repository.Inventory.ValidHash Darcs.Repository.Inventory.PatchHash
+ Darcs.Repository.Inventory: instance Darcs.Repository.Inventory.ValidHash Darcs.Repository.Inventory.PristineHash
+ Darcs.Repository.Inventory: instance GHC.Classes.Eq Darcs.Repository.Inventory.Inventory
+ Darcs.Repository.Inventory: instance GHC.Classes.Eq Darcs.Repository.Inventory.InventoryHash
+ Darcs.Repository.Inventory: instance GHC.Classes.Eq Darcs.Repository.Inventory.PatchHash
+ Darcs.Repository.Inventory: instance GHC.Classes.Eq Darcs.Repository.Inventory.PristineHash
+ Darcs.Repository.Inventory: instance GHC.Show.Show Darcs.Repository.Inventory.Inventory
+ Darcs.Repository.Inventory: instance GHC.Show.Show Darcs.Repository.Inventory.InventoryHash
+ Darcs.Repository.Inventory: instance GHC.Show.Show Darcs.Repository.Inventory.PatchHash
+ Darcs.Repository.Inventory: instance GHC.Show.Show Darcs.Repository.Inventory.PristineHash
+ Darcs.Repository.Inventory: inventoryPatchNames :: Inventory -> [String]
+ Darcs.Repository.Inventory: mkValidHash :: ValidHash a => String -> a
+ Darcs.Repository.Inventory: parseInventory :: ByteString -> Maybe Inventory
+ Darcs.Repository.Inventory: peekPristineHash :: ByteString -> String
+ Darcs.Repository.Inventory: pokePristineHash :: String -> ByteString -> Doc
+ Darcs.Repository.Inventory: pristineName :: ByteString
+ Darcs.Repository.Inventory: prop_inventoryParseShow :: Inventory -> Bool
+ Darcs.Repository.Inventory: prop_peekPokePristineHash :: (PristineHash, ByteString) -> Bool
+ Darcs.Repository.Inventory: prop_skipPokePristineHash :: (PristineHash, ByteString) -> Bool
+ Darcs.Repository.Inventory: showInventory :: Inventory -> Doc
+ Darcs.Repository.Inventory: showInventoryEntry :: InventoryEntry -> Doc
+ Darcs.Repository.Inventory: showInventoryPatches :: [InventoryEntry] -> Doc
+ Darcs.Repository.Inventory: skipPristineHash :: ByteString -> ByteString
+ Darcs.Repository.Inventory: type HeadInventory = (PristineHash, Inventory)
+ Darcs.Repository.Inventory: type InventoryEntry = (PatchInfo, PatchHash)
+ Darcs.Repository.Job: checkRepoIsNoRebase :: forall rt p wR wU wT. IsRepoType rt => Repository rt p wR wU wT -> Maybe (Repository ( 'RepoType 'NoRebase) p wR wU wT)
+ Darcs.Repository.Job: class ApplyState p ~ Tree => IsPrimV1 p
+ Darcs.Repository.Job: instance Darcs.Repository.Job.IsPrimV1 Darcs.Patch.V1.Prim.Prim
+ Darcs.Repository.Job: instance Darcs.Repository.Job.IsPrimV1 Darcs.Patch.V2.Prim.Prim
+ Darcs.Repository.Job: toPrimV1 :: IsPrimV1 p => p wX wY -> Prim wX wY
+ Darcs.Repository.Job: withOldRepoLock :: RepoJob a -> IO a
+ Darcs.Repository.Job: withRepositoryLocation :: UseCache -> String -> RepoJob a -> IO a
+ Darcs.Repository.Job: withUMaskFlag :: UMask -> IO a -> IO a
+ Darcs.Repository.Merge: announceMergeConflicts :: (PrimPatch p) => String -> AllowConflicts -> ExternalMerge -> FL p wX wY -> IO Bool
+ Darcs.Repository.Merge: instance GHC.Classes.Eq Darcs.Repository.Merge.MakeChanges
+ Darcs.Repository.Packs: createPacks :: (IsRepoType rt, RepoPatch p) => Repository rt p wR wU wT -> IO ()
+ Darcs.Repository.Pending: finalizePending :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> Tree IO -> IO ()
+ Darcs.Repository.Pending: makeNewPending :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wT wY -> Tree IO -> IO ()
+ Darcs.Repository.Pending: prepend :: forall rt p wR wU wT wX wY. RepoPatch p => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wX wY -> IO ()
+ Darcs.Repository.Pending: setTentativePending :: forall rt p wR wU wT wX wY. RepoPatch p => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wX wY -> IO ()
+ Darcs.Repository.Pending: siftForPending :: forall prim wX wY. PrimPatch prim => FL prim wX wY -> Sealed (FL prim wX)
+ Darcs.Repository.Pending: tentativelyAddToPending :: forall rt p wR wU wT wX wY. RepoPatch p => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wX wY -> IO ()
+ Darcs.Repository.Pending: tentativelyRemoveFromPending :: forall rt p wR wU wT wX wY. (RepoPatch p) => Repository rt p wR wU wT -> UpdateWorking -> PatchInfoAnd rt p wX wY -> IO ()
+ Darcs.Repository.Prefs: getMotd :: String -> IO ByteString
+ Darcs.Repository.Prefs: prefsDirPath :: FilePath
+ Darcs.Repository.Prefs: prefsFilesHelp :: [(String, String)]
+ Darcs.Repository.Prefs: prefsUrl :: FilePath -> String
+ Darcs.Repository.Prefs: showMotd :: String -> IO ()
+ Darcs.Repository.State: addPendingDiffToPending :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> FreeLeft (FL (PrimOf p)) -> IO ()
+ Darcs.Repository.State: addToPending :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wU wY -> IO ()
+ Darcs.Repository.Working: applyToWorking :: (ApplyState p ~ Tree, RepoPatch p) => Repository rt p wR wU wT -> Verbosity -> FL (PrimOf p) wU wY -> IO (Repository rt p wR wY wT)
+ Darcs.Repository.Working: setScriptsExecutable :: IO ()
+ Darcs.Repository.Working: setScriptsExecutablePatches :: PatchInspect p => p wX wY -> IO ()
+ Darcs.UI.Commands: [commandCompleteArgs] :: DarcsCommand parsedFlags -> (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO [String]
+ Darcs.UI.Commands: wrappedCommandDescription :: WrappedCommand -> String
+ Darcs.UI.Commands.MarkConflicts: instance Data.Foldable.Foldable Darcs.UI.Commands.MarkConflicts.Only
+ Darcs.UI.Commands.MarkConflicts: instance Data.Traversable.Traversable Darcs.UI.Commands.MarkConflicts.Only
+ Darcs.UI.Commands.MarkConflicts: instance GHC.Base.Functor Darcs.UI.Commands.MarkConflicts.Only
+ Darcs.UI.Commands.MarkConflicts: instance GHC.Classes.Eq a => GHC.Classes.Eq (Darcs.UI.Commands.MarkConflicts.Only a)
+ Darcs.UI.Commands.MarkConflicts: instance GHC.Classes.Ord a => GHC.Classes.Ord (Darcs.UI.Commands.MarkConflicts.Only a)
+ Darcs.UI.Commands.MarkConflicts: instance GHC.Show.Show a => GHC.Show.Show (Darcs.UI.Commands.MarkConflicts.Only a)
+ Darcs.UI.Commands.Util: checkUnrelatedRepos :: RepoPatch p => Bool -> PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> IO ()
+ Darcs.UI.Commands.Util: doesDirectoryReallyExist :: FilePath -> IO Bool
+ Darcs.UI.Commands.Util: expandDirs :: Bool -> [SubPath] -> IO [SubPath]
+ Darcs.UI.Commands.Util: printDryRunMessageAndExit :: (RepoPatch p, ApplyState p ~ Tree) => String -> Verbosity -> Summary -> DryRun -> XmlOutput -> Bool -> FL (PatchInfoAnd rt p) wX wY -> IO ()
+ Darcs.UI.Commands.Util: repoTags :: PatchSet rt p wX wY -> IO [String]
+ Darcs.UI.Completion: fileArgs :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO [FilePath]
+ Darcs.UI.Completion: knownFileArgs :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO [FilePath]
+ Darcs.UI.Completion: modifiedFileArgs :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO [FilePath]
+ Darcs.UI.Completion: noArgs :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO [String]
+ Darcs.UI.Completion: prefArgs :: String -> (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO [String]
+ Darcs.UI.Completion: unknownFileArgs :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO [FilePath]
+ Darcs.UI.Email: prop_qp_roundtrip :: ByteString -> Bool
+ Darcs.UI.Flags: allowCaseDifferingFilenames :: PrimDarcsOption Bool
+ Darcs.UI.Flags: allowWindowsReservedFilenames :: PrimDarcsOption Bool
+ Darcs.UI.Flags: amendUnrecord :: PrimDarcsOption Bool
+ Darcs.UI.Flags: author :: PrimDarcsOption (Maybe String)
+ Darcs.UI.Flags: changesReverse :: PrimDarcsOption Bool
+ Darcs.UI.Flags: charset :: PrimDarcsOption (Maybe String)
+ Darcs.UI.Flags: compress :: PrimDarcsOption Compression
+ Darcs.UI.Flags: enumPatches :: PrimDarcsOption EnumPatches
+ Darcs.UI.Flags: enumeratePatches :: Config -> Bool
+ Darcs.UI.Flags: happyForwarding :: PrimDarcsOption Bool
+ Darcs.UI.Flags: matchAny :: MatchOption
+ Darcs.UI.Flags: onlyToFiles :: PrimDarcsOption Bool
+ Darcs.UI.Flags: patchIndexNo :: PrimDarcsOption WithPatchIndex
+ Darcs.UI.Flags: patchIndexYes :: PrimDarcsOption WithPatchIndex
+ Darcs.UI.Flags: quiet :: Config -> Bool
+ Darcs.UI.Flags: reply :: PrimDarcsOption (Maybe String)
+ Darcs.UI.Flags: verbose :: Config -> Bool
+ Darcs.UI.Flags: withContext :: PrimDarcsOption WithContext
+ Darcs.UI.Flags: xmlOutput :: PrimDarcsOption XmlOutput
+ Darcs.UI.Options.All: HookConfig :: Maybe String -> Bool -> HookConfig
+ Darcs.UI.Options.All: HooksConfig :: HookConfig -> HookConfig -> HooksConfig
+ Darcs.UI.Options.All: NoEnumPatches :: EnumPatches
+ Darcs.UI.Options.All: NotInDefaultRepo :: NotInRemote
+ Darcs.UI.Options.All: NotInRemotePath :: String -> NotInRemote
+ Darcs.UI.Options.All: YesEnumPatches :: EnumPatches
+ Darcs.UI.Options.All: [cmd] :: HookConfig -> Maybe String
+ Darcs.UI.Options.All: [diffCmd] :: ExternalDiff -> Maybe String
+ Darcs.UI.Options.All: [diffOpts] :: ExternalDiff -> [String]
+ Darcs.UI.Options.All: [diffUnified] :: ExternalDiff -> Bool
+ Darcs.UI.Options.All: [post] :: HooksConfig -> HookConfig
+ Darcs.UI.Options.All: [pre] :: HooksConfig -> HookConfig
+ Darcs.UI.Options.All: [prompt] :: HookConfig -> Bool
+ Darcs.UI.Options.All: askDeps :: PrimDarcsOption Bool
+ Darcs.UI.Options.All: class YesNo a
+ Darcs.UI.Options.All: cloneKind :: PrimDarcsOption CloneKind
+ Darcs.UI.Options.All: conflictsNo :: PrimDarcsOption (Maybe AllowConflicts)
+ Darcs.UI.Options.All: conflictsYes :: PrimDarcsOption (Maybe AllowConflicts)
+ Darcs.UI.Options.All: data EnumPatches
+ Darcs.UI.Options.All: data HookConfig
+ Darcs.UI.Options.All: data HooksConfig
+ Darcs.UI.Options.All: data NotInRemote
+ Darcs.UI.Options.All: enumPatches :: PrimDarcsOption EnumPatches
+ Darcs.UI.Options.All: externalMerge :: PrimDarcsOption ExternalMerge
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.Compression
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.DryRun
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.IncludeBoring
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.LeaveTestDir
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.LookForAdds
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.LookForMoves
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.LookForReplaces
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.Reorder
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.RunTest
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.SetScriptsExecutable
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.UseCache
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.UseIndex
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.WantGuiPause
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.WithPatchIndex
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.Repository.Flags.WithWorkingDir
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.UI.Options.All.EnumPatches
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.UI.Options.All.Summary
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.UI.Options.All.WithContext
+ Darcs.UI.Options.All: instance Darcs.UI.Options.All.YesNo Darcs.UI.Options.All.XmlOutput
+ Darcs.UI.Options.All: instance GHC.Classes.Eq Darcs.UI.Options.All.EnumPatches
+ Darcs.UI.Options.All: instance GHC.Show.Show Darcs.UI.Options.All.EnumPatches
+ Darcs.UI.Options.All: lookforadds :: LookForAdds -> PrimDarcsOption LookForAdds
+ Darcs.UI.Options.All: lookformoves :: PrimDarcsOption LookForMoves
+ Darcs.UI.Options.All: lookforreplaces :: PrimDarcsOption LookForReplaces
+ Darcs.UI.Options.All: maxCount :: PrimDarcsOption (Maybe Int)
+ Darcs.UI.Options.All: maybeSummary :: Maybe Summary -> PrimDarcsOption (Maybe Summary)
+ Darcs.UI.Options.All: no :: YesNo a => a -> Bool
+ Darcs.UI.Options.All: patchIndexNo :: PrimDarcsOption WithPatchIndex
+ Darcs.UI.Options.All: repoDir :: PrimDarcsOption (Maybe String)
+ Darcs.UI.Options.All: runTest :: PrimDarcsOption RunTest
+ Darcs.UI.Options.All: withWorkingDir :: PrimDarcsOption WithWorkingDir
+ Darcs.UI.Options.All: xmlOutput :: PrimDarcsOption XmlOutput
+ Darcs.UI.Options.All: yes :: YesNo a => a -> Bool
+ Darcs.UI.Options.Core: (?) :: (forall a. PrimOptSpec d f a v) -> [f] -> v
+ Darcs.UI.Options.Core: infix 5 ?
+ Darcs.UI.Options.Core: instance Data.Semigroup.Semigroup (Darcs.UI.Options.Core.PrimOptSpec d f a [v])
+ Darcs.UI.Options.Flags: EnumPatches :: DarcsFlag
+ Darcs.UI.Options.Flags: NoEnumPatches :: DarcsFlag
+ Darcs.UI.Options.Flags: To :: String -> DarcsFlag
+ Darcs.UI.Options.Matching: context :: MatchOption
+ Darcs.UI.Options.Matching: matchFrom :: MatchOption
+ Darcs.UI.Options.Matching: matchLast :: MatchOption
+ Darcs.UI.Usage: formatOptions :: [DarcsOptDescr a] -> [String]
+ Darcs.UI.Usage: getCommandHelp :: Maybe (DarcsCommand pf1) -> DarcsCommand pf2 -> Doc
+ Darcs.UI.Usage: getCommandMiniHelp :: Maybe (DarcsCommand pf1) -> DarcsCommand pf2 -> String
+ Darcs.UI.Usage: subusage :: DarcsCommand pf -> String
+ Darcs.UI.Usage: usage :: [CommandControl] -> Doc
+ Darcs.Util.ByteString: propHexConversion :: ByteString -> Bool
+ Darcs.Util.ByteString: prop_linesPS_length :: ByteString -> Bool
+ Darcs.Util.ByteString: prop_unlinesPS_length :: [ByteString] -> Bool
+ Darcs.Util.ByteString: prop_unlinesPS_linesPS_left_inverse :: ByteString -> Bool
+ Darcs.Util.ByteString: spec_betweenLinesPS :: ByteString -> ByteString -> ByteString -> Maybe ByteString
+ Darcs.Util.DateMatcher: testDate :: String -> IO ()
+ Darcs.Util.DateMatcher: testDateAt :: String -> String -> IO ()
+ Darcs.Util.Encoding: decode :: ByteString -> IO String
+ Darcs.Util.Encoding: decodeUtf8 :: ByteString -> IO String
+ Darcs.Util.Encoding: encode :: String -> IO ByteString
+ Darcs.Util.Encoding: encodeUtf8 :: String -> IO ByteString
+ Darcs.Util.Hash: data SHA1
+ Darcs.Util.Hash: instance Data.Binary.Class.Binary Darcs.Util.Hash.SHA1
+ Darcs.Util.Hash: instance GHC.Classes.Eq Darcs.Util.Hash.SHA1
+ Darcs.Util.Hash: instance GHC.Classes.Ord Darcs.Util.Hash.SHA1
+ Darcs.Util.Hash: instance GHC.Show.Show Darcs.Util.Hash.SHA1
+ Darcs.Util.Hash: sha1PS :: ByteString -> SHA1
+ Darcs.Util.Hash: sha1Xor :: SHA1 -> SHA1 -> SHA1
+ Darcs.Util.Hash: sha1short :: SHA1 -> Word32
+ Darcs.Util.Hash: sha1zero :: SHA1
+ Darcs.Util.Hash: sha256sum :: ByteString -> String
+ Darcs.Util.Hash: showAsHex :: Word32 -> String
+ Darcs.Util.IsoDate: readUTCDateOldFashioned :: String -> CalendarTime
+ Darcs.Util.IsoDate: showIsoDateTime :: CalendarTime -> String
+ Darcs.Util.Lock: appendTextFile :: FilePathLike p => p -> String -> IO ()
+ Darcs.Util.Lock: readTextFile :: FilePathLike p => p -> IO [String]
+ Darcs.Util.Lock: withNewDirectory :: FilePath -> IO () -> IO ()
+ Darcs.Util.Lock: writeTextFile :: FilePathLike p => p -> String -> IO ()
+ Darcs.Util.Path: data Name
+ Darcs.Util.Path: decodeWhiteName :: ByteString -> Name
+ Darcs.Util.Path: encodeWhiteName :: Name -> ByteString
+ Darcs.Util.Path: eqAnycase :: Name -> Name -> Bool
+ Darcs.Util.Path: unsafeMakeName :: ByteString -> Name
+ Darcs.Util.Printer: instance Data.Semigroup.Semigroup Darcs.Util.Printer.Doc
+ Darcs.Util.Text: showCommandLine :: [String] -> String
+ Darcs.Util.Tree.Monad: instance GHC.Base.Monad m => Darcs.Util.Tree.Monad.TreeRO (Darcs.Util.Tree.Monad.TreeMonad m)
+ Darcs.Util.Tree.Monad: instance GHC.Base.Monad m => Darcs.Util.Tree.Monad.TreeRW (Darcs.Util.Tree.Monad.TreeMonad m)
- Darcs.Patch: applyToTree :: (Apply p, Functor m, Monad m, ApplyState p ~ Tree) => p wX wY -> Tree m -> m (Tree m)
+ Darcs.Patch: applyToTree :: (Apply p, Monad m, ApplyState p ~ Tree) => p wX wY -> Tree m -> m (Tree m)
- Darcs.Patch: class Effect p where effect = reverseRL . effectRL effectRL = reverseFL . effect
+ Darcs.Patch: class Effect p
- Darcs.Patch: class (Patchy prim, MyEq prim, PatchListFormat prim, IsHunk prim, RepairToFL prim, PatchInspect prim, ReadPatch prim, ShowPatch prim, Show2 prim, PrimConstruct prim, PrimCanonize prim, PrimClassify prim, PrimDetails prim, PrimShow prim, PrimRead prim, PrimApply prim) => PrimPatch prim
+ Darcs.Patch: class (PrimPatchCommon prim, ReadPatch prim, ShowPatch prim, ShowContextPatch prim, PatchListFormat prim) => PrimPatch prim
- Darcs.Patch: plainSummary :: (Conflict e, Effect e, PrimPatchBase e) => e wX wY -> Doc
+ Darcs.Patch: plainSummary :: (Conflict e, PrimPatchBase e) => e wX wY -> Doc
- Darcs.Patch: plainSummaryPrims :: PrimDetails prim => Bool -> [FileName] -> FL prim wX wY -> Doc
+ Darcs.Patch: plainSummaryPrims :: PrimDetails prim => Bool -> FL prim wX wY -> Doc
- Darcs.Patch: showContextPatch :: (ShowPatch p, Monad m, ApplyMonad (ApplyState p) m) => p wX wY -> m Doc
+ Darcs.Patch: showContextPatch :: (ShowContextPatch p, (ApplyMonad (ApplyState p) m)) => ShowPatchFor -> p wX wY -> m Doc
- Darcs.Patch: showPatch :: ShowPatchBasic p => p wX wY -> Doc
+ Darcs.Patch: showPatch :: ShowPatchBasic p => ShowPatchFor -> p wX wY -> Doc
- Darcs.Patch: xmlSummary :: (Effect p, Conflict p, PrimPatchBase p) => p wX wY -> Doc
+ Darcs.Patch: xmlSummary :: (Conflict p, PrimPatchBase p) => p wX wY -> Doc
- Darcs.Patch.Annotate: annotate :: (Apply p, ApplyState p ~ Tree) => DiffAlgorithm -> FL (PatchInfoAnd rt p) wX wY -> FileName -> ByteString -> AnnotateResult
+ Darcs.Patch.Annotate: annotate :: Annotate p => p wX wY -> AnnotatedM ()
- Darcs.Patch.Annotate: annotateDirectory :: (Apply p, ApplyState p ~ Tree) => DiffAlgorithm -> FL (PatchInfoAnd rt p) wX wY -> FileName -> [FileName] -> AnnotateResult
+ Darcs.Patch.Annotate: annotateDirectory :: Annotate p => FL (PatchInfoAnd rt p) wX wY -> FileName -> [FileName] -> AnnotateResult
- Darcs.Patch.Apply: applyToTree :: (Apply p, Functor m, Monad m, ApplyState p ~ Tree) => p wX wY -> Tree m -> m (Tree m)
+ Darcs.Patch.Apply: applyToTree :: (Apply p, Monad m, ApplyState p ~ Tree) => p wX wY -> Tree m -> m (Tree m)
- Darcs.Patch.Apply: class Apply p where type ApplyState p :: (* -> *) -> * where {
+ Darcs.Patch.Apply: class Apply p where {
- Darcs.Patch.ApplyMonad: class (Functor m, Monad m, Functor (ApplyMonadBase m), Monad (ApplyMonadBase m), ApplyMonadStateOperations state m, ToTree state) => ApplyMonad (state :: (* -> *) -> *) m where type ApplyMonadBase m :: * -> * where {
+ Darcs.Patch.ApplyMonad: class (Functor m, Monad m, Functor (ApplyMonadBase m), Monad (ApplyMonadBase m), ApplyMonadStateOperations state m, ToTree state) => ApplyMonad (state :: (* -> *) -> *) m where {
- Darcs.Patch.ApplyMonad: class ApplyMonadState (state :: (* -> *) -> *) where type ApplyMonadStateOperations state :: (* -> *) -> Constraint where {
+ Darcs.Patch.ApplyMonad: class ApplyMonadState (state :: (* -> *) -> *) where {
- Darcs.Patch.ApplyMonad: class (Functor m, Monad m, ApplyMonad state (ApplyMonadOver state m)) => ApplyMonadTrans (state :: (* -> *) -> *) m where type ApplyMonadOver state m :: * -> * where {
+ Darcs.Patch.ApplyMonad: class (Functor m, Monad m, ApplyMonad state (ApplyMonadOver state m)) => ApplyMonadTrans (state :: (* -> *) -> *) m where {
- Darcs.Patch.ApplyMonad: class (Functor m, Monad m) => ApplyMonadTree m where mReadFilePSs f = linesPS `fmap` mReadFilePS f mCreateFile f = mModifyFilePS f $ \ _ -> return empty mModifyFilePSs f j = mModifyFilePS f (fmap unlinesPS . j . linesPS) mChangePref _ _ _ = return ()
+ Darcs.Patch.ApplyMonad: class (Functor m, Monad m) => ApplyMonadTree m
- Darcs.Patch.ApplyPatches: applyPatches :: (MonadProgress m, ApplyMonad (ApplyState p) m, Patchy p) => FL (PatchInfoAnd rt p) wX wY -> m ()
+ Darcs.Patch.ApplyPatches: applyPatches :: (MonadProgress m, ApplyMonad (ApplyState p) m, Apply p) => FL (PatchInfoAnd rt p) wX wY -> m ()
- Darcs.Patch.Bundle: contextPatches :: RepoPatch p => PatchSet rt p Origin wX -> (PatchSet rt p :> RL (PatchInfoAnd rt p)) Origin wX
+ Darcs.Patch.Bundle: contextPatches :: PatchSet rt p Origin wX -> (PatchSet rt p :> RL (PatchInfoAnd rt p)) Origin wX
- Darcs.Patch.Bundle: scanContextFile :: RepoPatch p => FilePath -> IO (PatchSet rt p Origin wX)
+ Darcs.Patch.Bundle: scanContextFile :: FilePath -> IO (PatchSet rt p Origin wX)
- Darcs.Patch.Choices: forceFirst :: Patchy p => Label -> PatchChoices p wA wB -> PatchChoices p wA wB
+ Darcs.Patch.Choices: forceFirst :: Commute p => Label -> PatchChoices p wA wB -> PatchChoices p wA wB
- Darcs.Patch.Choices: forceFirsts :: Patchy p => [Label] -> PatchChoices p wA wB -> PatchChoices p wA wB
+ Darcs.Patch.Choices: forceFirsts :: Commute p => [Label] -> PatchChoices p wA wB -> PatchChoices p wA wB
- Darcs.Patch.Choices: forceLast :: Patchy p => Label -> PatchChoices p wA wB -> PatchChoices p wA wB
+ Darcs.Patch.Choices: forceLast :: Commute p => Label -> PatchChoices p wA wB -> PatchChoices p wA wB
- Darcs.Patch.Choices: forceLasts :: Patchy p => [Label] -> PatchChoices p wA wB -> PatchChoices p wA wB
+ Darcs.Patch.Choices: forceLasts :: Commute p => [Label] -> PatchChoices p wA wB -> PatchChoices p wA wB
- Darcs.Patch.Choices: forceMatchingFirst :: forall p wA wB. Patchy p => (forall wX wY. LabelledPatch p wX wY -> Bool) -> PatchChoices p wA wB -> PatchChoices p wA wB
+ Darcs.Patch.Choices: forceMatchingFirst :: forall p wA wB. Commute p => (forall wX wY. LabelledPatch p wX wY -> Bool) -> PatchChoices p wA wB -> PatchChoices p wA wB
- Darcs.Patch.Choices: forceMatchingLast :: Patchy p => (forall wX wY. LabelledPatch p wX wY -> Bool) -> PatchChoices p wA wB -> PatchChoices p wA wB
+ Darcs.Patch.Choices: forceMatchingLast :: Commute p => (forall wX wY. LabelledPatch p wX wY -> Bool) -> PatchChoices p wA wB -> PatchChoices p wA wB
- Darcs.Patch.Choices: getChoices :: Patchy p => PatchChoices p wX wY -> (FL (LabelledPatch p) :> (FL (LabelledPatch p) :> FL (LabelledPatch p))) wX wY
+ Darcs.Patch.Choices: getChoices :: Commute p => PatchChoices p wX wY -> (FL (LabelledPatch p) :> (FL (LabelledPatch p) :> FL (LabelledPatch p))) wX wY
- Darcs.Patch.Choices: getLabelInt :: Label -> Integer
+ Darcs.Patch.Choices: getLabelInt :: Label -> Int
- Darcs.Patch.Choices: makeEverythingLater :: Patchy p => PatchChoices p wX wY -> PatchChoices p wX wY
+ Darcs.Patch.Choices: makeEverythingLater :: PatchChoices p wX wY -> PatchChoices p wX wY
- Darcs.Patch.Choices: makeEverythingSooner :: forall p wX wY. Patchy p => PatchChoices p wX wY -> PatchChoices p wX wY
+ Darcs.Patch.Choices: makeEverythingSooner :: forall p wX wY. Commute p => PatchChoices p wX wY -> PatchChoices p wX wY
- Darcs.Patch.Choices: patchChoices :: Patchy p => FL p wX wY -> PatchChoices p wX wY
+ Darcs.Patch.Choices: patchChoices :: FL p wX wY -> PatchChoices p wX wY
- Darcs.Patch.Choices: patchSlot :: forall p wA wB wX wY. Patchy p => LabelledPatch p wA wB -> PatchChoices p wX wY -> (Slot, PatchChoices p wX wY)
+ Darcs.Patch.Choices: patchSlot :: forall p wA wB wX wY. Commute p => LabelledPatch p wA wB -> PatchChoices p wX wY -> (Slot, PatchChoices p wX wY)
- Darcs.Patch.Choices: refineChoices :: (Patchy p, Monad m, Functor m) => (forall wU wV. FL (LabelledPatch p) wU wV -> PatchChoices p wU wV -> m (PatchChoices p wU wV)) -> PatchChoices p wX wY -> m (PatchChoices p wX wY)
+ Darcs.Patch.Choices: refineChoices :: (Commute p, Monad m) => (forall wU wV. FL (LabelledPatch p) wU wV -> PatchChoices p wU wV -> m (PatchChoices p wU wV)) -> PatchChoices p wX wY -> m (PatchChoices p wX wY)
- Darcs.Patch.Choices: selectAllMiddles :: forall p wX wY. Patchy p => Bool -> PatchChoices p wX wY -> PatchChoices p wX wY
+ Darcs.Patch.Choices: selectAllMiddles :: forall p wX wY. Commute p => Bool -> PatchChoices p wX wY -> PatchChoices p wX wY
- Darcs.Patch.Choices: separateFirstFromMiddleLast :: Patchy p => PatchChoices p wX wZ -> (FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wZ
+ Darcs.Patch.Choices: separateFirstFromMiddleLast :: PatchChoices p wX wZ -> (FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wZ
- Darcs.Patch.Choices: separateFirstMiddleFromLast :: Patchy p => PatchChoices p wX wZ -> (FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wZ
+ Darcs.Patch.Choices: separateFirstMiddleFromLast :: Commute p => PatchChoices p wX wZ -> (FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wZ
- Darcs.Patch.Choices: substitute :: forall p wX wY. Patchy p => Sealed2 (LabelledPatch p :||: FL (LabelledPatch p)) -> PatchChoices p wX wY -> PatchChoices p wX wY
+ Darcs.Patch.Choices: substitute :: forall p wX wY. Sealed2 (LabelledPatch p :||: FL (LabelledPatch p)) -> PatchChoices p wX wY -> PatchChoices p wX wY
- Darcs.Patch.Debug: class PatchDebug p where patchDebugDummy _ = ()
+ Darcs.Patch.Debug: class PatchDebug p
- Darcs.Patch.Depends: areUnrelatedRepos :: Patchy p => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> Bool
+ Darcs.Patch.Depends: areUnrelatedRepos :: Commute p => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> Bool
- Darcs.Patch.Depends: countUsThem :: Patchy p => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> (Int, Int)
+ Darcs.Patch.Depends: countUsThem :: Commute p => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> (Int, Int)
- Darcs.Patch.Depends: findCommonAndUncommon :: forall rt p wStart wX wY. Patchy p => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> Fork (PatchSet rt p) (FL (PatchInfoAnd rt p)) (FL (PatchInfoAnd rt p)) wStart wX wY
+ Darcs.Patch.Depends: findCommonAndUncommon :: forall rt p wStart wX wY. Commute p => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> Fork (PatchSet rt p) (FL (PatchInfoAnd rt p)) (FL (PatchInfoAnd rt p)) wStart wX wY
- Darcs.Patch.Depends: findCommonWithThem :: Patchy p => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> (PatchSet rt p :> FL (PatchInfoAnd rt p)) wStart wX
+ Darcs.Patch.Depends: findCommonWithThem :: Commute p => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> (PatchSet rt p :> FL (PatchInfoAnd rt p)) wStart wX
- Darcs.Patch.Depends: findUncommon :: Patchy p => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> (FL (PatchInfoAnd rt p) :\/: FL (PatchInfoAnd rt p)) wX wY
+ Darcs.Patch.Depends: findUncommon :: Commute p => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> (FL (PatchInfoAnd rt p) :\/: FL (PatchInfoAnd rt p)) wX wY
- Darcs.Patch.Depends: getDeps :: (RepoPatch p, ApplyState p ~ Tree) => FL (Named p) wA wR -> FL (PatchInfoAnd rt p) wX wY -> [SPatchAndDeps p]
+ Darcs.Patch.Depends: getDeps :: (RepoPatch p) => FL (Named p) wA wR -> FL (PatchInfoAnd rt p) wX wY -> [SPatchAndDeps p]
- Darcs.Patch.Depends: getPatchesBeyondTag :: Patchy p => PatchInfo -> PatchSet rt p wStart wX -> FlippedSeal (RL (PatchInfoAnd rt p)) wX
+ Darcs.Patch.Depends: getPatchesBeyondTag :: Commute p => PatchInfo -> PatchSet rt p wStart wX -> FlippedSeal (RL (PatchInfoAnd rt p)) wX
- Darcs.Patch.Depends: merge2FL :: (Patchy p, Merge p) => FL (PatchInfoAnd rt p) wX wY -> FL (PatchInfoAnd rt p) wX wZ -> (FL (PatchInfoAnd rt p) :/\: FL (PatchInfoAnd rt p)) wY wZ
+ Darcs.Patch.Depends: merge2FL :: (Merge p) => FL (PatchInfoAnd rt p) wX wY -> FL (PatchInfoAnd rt p) wX wZ -> (FL (PatchInfoAnd rt p) :/\: FL (PatchInfoAnd rt p)) wY wZ
- Darcs.Patch.Depends: mergeThem :: (Patchy p, Merge p) => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> Sealed (FL (PatchInfoAnd rt p) wX)
+ Darcs.Patch.Depends: mergeThem :: (Merge p) => PatchSet rt p wStart wX -> PatchSet rt p wStart wY -> Sealed (FL (PatchInfoAnd rt p) wX)
- Darcs.Patch.Depends: removeFromPatchSet :: Patchy p => FL (PatchInfoAnd rt p) wX wY -> PatchSet rt p wStart wY -> Maybe (PatchSet rt p wStart wX)
+ Darcs.Patch.Depends: removeFromPatchSet :: Commute p => FL (PatchInfoAnd rt p) wX wY -> PatchSet rt p wStart wY -> Maybe (PatchSet rt p wStart wX)
- Darcs.Patch.Depends: splitOnTag :: Patchy p => PatchInfo -> PatchSet rt p wStart wX -> Maybe ((PatchSet rt p :> RL (PatchInfoAnd rt p)) wStart wX)
+ Darcs.Patch.Depends: splitOnTag :: Commute p => PatchInfo -> PatchSet rt p wStart wX -> Maybe ((PatchSet rt p :> RL (PatchInfoAnd rt p)) wStart wX)
- Darcs.Patch.Effect: class Effect p where effect = reverseRL . effectRL effectRL = reverseFL . effect
+ Darcs.Patch.Effect: class Effect p
- Darcs.Patch.Format: class PatchListFormat p where patchListFormat = ListFormatDefault
+ Darcs.Patch.Format: class PatchListFormat p
- Darcs.Patch.Format: data ListFormat (p :: * -> * -> *)
+ Darcs.Patch.Format: data ListFormat (p :: (* -> * -> *))
- Darcs.Patch.Info: showPatchInfo :: PatchInfo -> Doc
+ Darcs.Patch.Info: showPatchInfo :: ShowPatchFor -> PatchInfo -> Doc
- Darcs.Patch.Match: addInternalMatcher :: (IsRepoType rt, Matchable p) => Maybe (Matcher rt p) -> Maybe (Matcher rt p)
+ Darcs.Patch.Match: addInternalMatcher :: (IsRepoType rt) => Maybe (Matcher rt p) -> Maybe (Matcher rt p)
- Darcs.Patch.Matchable: class (Patchy p, PatchInspect p) => Matchable p
+ Darcs.Patch.Matchable: class (Apply p, Commute p, Invert p, PatchInspect p) => Matchable p
- Darcs.Patch.Named.Wrapped: [RebaseP] :: (PrimPatchBase p, FromPrim p, Effect p) => !PatchInfo -> !(Suspended p wX wX) -> WrappedNamed (RepoType IsRebase) p wX wX
+ Darcs.Patch.Named.Wrapped: [RebaseP] :: (PrimPatchBase p, FromPrim p, Effect p) => !PatchInfo -> !(Suspended p wX wX) -> WrappedNamed ( 'RepoType 'IsRebase) p wX wX
- Darcs.Patch.Named.Wrapped: data (:~~:) (a :: RebaseType) b
+ Darcs.Patch.Named.Wrapped: data (a :: RebaseType) (:~~:) b
- Darcs.Patch.Named.Wrapped: fmapFL_WrappedNamed :: (FL p wA wB -> FL q wA wB) -> (RebaseTypeOf rt :~~: IsRebase -> p :~: q) -> WrappedNamed rt p wA wB -> WrappedNamed rt q wA wB
+ Darcs.Patch.Named.Wrapped: fmapFL_WrappedNamed :: (FL p wA wB -> FL q wA wB) -> (RebaseTypeOf rt :~~: 'IsRebase -> p :~: q) -> WrappedNamed rt p wA wB -> WrappedNamed rt q wA wB
- Darcs.Patch.Named.Wrapped: fromRebasing :: WrappedNamed (RepoType IsRebase) p wX wY -> Named p wX wY
+ Darcs.Patch.Named.Wrapped: fromRebasing :: WrappedNamed ( 'RepoType 'IsRebase) p wX wY -> Named p wX wY
- Darcs.Patch.Named.Wrapped: generaliseRepoTypeWrapped :: WrappedNamed (RepoType NoRebase) p wA wB -> WrappedNamed rt p wA wB
+ Darcs.Patch.Named.Wrapped: generaliseRepoTypeWrapped :: WrappedNamed ( 'RepoType 'NoRebase) p wA wB -> WrappedNamed rt p wA wB
- Darcs.Patch.Named.Wrapped: mkRebase :: (PrimPatchBase p, FromPrim p, Effect p) => Suspended p wX wX -> IO (WrappedNamed (RepoType IsRebase) p wX wX)
+ Darcs.Patch.Named.Wrapped: mkRebase :: (PrimPatchBase p, FromPrim p, Effect p) => Suspended p wX wX -> IO (WrappedNamed ( 'RepoType 'IsRebase) p wX wX)
- Darcs.Patch.Named.Wrapped: toRebasing :: Named p wX wY -> WrappedNamed (RepoType IsRebase) p wX wY
+ Darcs.Patch.Named.Wrapped: toRebasing :: Named p wX wY -> WrappedNamed ( 'RepoType 'IsRebase) p wX wY
- Darcs.Patch.PatchInfoAnd: fmapFLPIAP :: (FL p wX wY -> FL q wX wY) -> (RebaseTypeOf rt :~~: IsRebase -> p :~: q) -> PatchInfoAnd rt p wX wY -> PatchInfoAnd rt q wX wY
+ Darcs.Patch.PatchInfoAnd: fmapFLPIAP :: (FL p wX wY -> FL q wX wY) -> (RebaseTypeOf rt :~~: 'IsRebase -> p :~: q) -> PatchInfoAnd rt p wX wY -> PatchInfoAnd rt q wX wY
- Darcs.Patch.PatchInfoAnd: generaliseRepoTypePIAP :: PatchInfoAnd (RepoType NoRebase) p wA wB -> PatchInfoAnd rt p wA wB
+ Darcs.Patch.PatchInfoAnd: generaliseRepoTypePIAP :: PatchInfoAnd ( 'RepoType 'NoRebase) p wA wB -> PatchInfoAnd rt p wA wB
- Darcs.Patch.Permutations: removeCommon :: (MyEq p, Commute p) => (FL p :\/: FL p) wX wY -> (FL p :\/: FL p) wX wY
+ Darcs.Patch.Permutations: removeCommon :: (Eq2 p, Commute p) => (FL p :\/: FL p) wX wY -> (FL p :\/: FL p) wX wY
- Darcs.Patch.Permutations: removeFL :: (MyEq p, Commute p) => p wX wY -> FL p wX wZ -> Maybe (FL p wY wZ)
+ Darcs.Patch.Permutations: removeFL :: (Eq2 p, Commute p) => p wX wY -> FL p wX wZ -> Maybe (FL p wY wZ)
- Darcs.Patch.Permutations: removeRL :: (MyEq p, Commute p) => p wY wZ -> RL p wX wZ -> Maybe (RL p wX wY)
+ Darcs.Patch.Permutations: removeRL :: (Eq2 p, Commute p) => p wY wZ -> RL p wX wZ -> Maybe (RL p wX wY)
- Darcs.Patch.Permutations: removeSubsequenceFL :: (MyEq p, Commute p) => FL p wA wB -> FL p wA wC -> Maybe (FL p wB wC)
+ Darcs.Patch.Permutations: removeSubsequenceFL :: (Eq2 p, Commute p) => FL p wA wB -> FL p wA wC -> Maybe (FL p wB wC)
- Darcs.Patch.Permutations: removeSubsequenceRL :: (MyEq p, Commute p) => RL p wAb wAbc -> RL p wA wAbc -> Maybe (RL p wA wAb)
+ Darcs.Patch.Permutations: removeSubsequenceRL :: (Eq2 p, Commute p) => RL p wAb wAbc -> RL p wA wAbc -> Maybe (RL p wA wAb)
- Darcs.Patch.Prim: class (Patchy prim, MyEq prim, PatchListFormat prim, IsHunk prim, RepairToFL prim, PatchInspect prim, ReadPatch prim, ShowPatch prim, Show2 prim, PrimConstruct prim, PrimCanonize prim, PrimClassify prim, PrimDetails prim, PrimShow prim, PrimRead prim, PrimApply prim) => PrimPatch prim
+ Darcs.Patch.Prim: class (PrimPatchCommon prim, ReadPatch prim, ShowPatch prim, ShowContextPatch prim, PatchListFormat prim) => PrimPatch prim
- Darcs.Patch.Prim: class PrimPatch (PrimOf p) => PrimPatchBase p where type PrimOf (p :: * -> * -> *) :: * -> * -> * where {
+ Darcs.Patch.Prim: class PrimPatch (PrimOf p) => PrimPatchBase p where {
- Darcs.Patch.Prim: type family PrimOf (p :: * -> * -> *) :: * -> * -> *;
+ Darcs.Patch.Prim: type family PrimOf (p :: (* -> * -> *)) :: (* -> * -> *);
- Darcs.Patch.Prim.Class: class (Patchy prim, MyEq prim, PatchListFormat prim, IsHunk prim, RepairToFL prim, PatchInspect prim, ReadPatch prim, ShowPatch prim, Show2 prim, PrimConstruct prim, PrimCanonize prim, PrimClassify prim, PrimDetails prim, PrimShow prim, PrimRead prim, PrimApply prim) => PrimPatch prim
+ Darcs.Patch.Prim.Class: class (PrimPatchCommon prim, ReadPatch prim, ShowPatch prim, ShowContextPatch prim, PatchListFormat prim) => PrimPatch prim
- Darcs.Patch.Prim.Class: class PrimPatch (PrimOf p) => PrimPatchBase p where type PrimOf (p :: * -> * -> *) :: * -> * -> * where {
+ Darcs.Patch.Prim.Class: class PrimPatch (PrimOf p) => PrimPatchBase p where {
- Darcs.Patch.Prim.Class: type family PrimOf (p :: * -> * -> *) :: * -> * -> *;
+ Darcs.Patch.Prim.Class: type family PrimOf (p :: (* -> * -> *)) :: (* -> * -> *);
- Darcs.Patch.Prim.FileUUID.Core: Blob :: (m ByteString) -> !Hash -> Object
+ Darcs.Patch.Prim.FileUUID.Core: Blob :: (m FileContent) -> !Hash -> Object
- Darcs.Patch.Prim.FileUUID.Core: [Demanifest] :: !UUID -> Location -> Prim wX wY
+ Darcs.Patch.Prim.FileUUID.Core: [Demanifest] :: !UUID -> !Location -> Prim wX wY
- Darcs.Patch.Prim.FileUUID.Core: [Hunk] :: !Int -> ByteString -> ByteString -> Hunk wX wY
+ Darcs.Patch.Prim.FileUUID.Core: [Hunk] :: !UUID -> !(Hunk wX wY) -> Prim wX wY
- Darcs.Patch.Prim.FileUUID.Core: [Manifest] :: !UUID -> Location -> Prim wX wY
+ Darcs.Patch.Prim.FileUUID.Core: [Manifest] :: !UUID -> !Location -> Prim wX wY
- Darcs.Patch.Prim.FileUUID.ObjectMap: Blob :: (m ByteString) -> !Hash -> Object
+ Darcs.Patch.Prim.FileUUID.ObjectMap: Blob :: (m FileContent) -> !Hash -> Object
- Darcs.Patch.Prim.FileUUID.ObjectMap: type DirContent = Map ByteString UUID
+ Darcs.Patch.Prim.FileUUID.ObjectMap: type DirContent = Map Name UUID
- Darcs.Patch.Rebase: takeAnyRebase :: PatchSet (RepoType IsRebase) p wA wB -> (Sealed2 (PatchInfoAnd (RepoType IsRebase) p), Sealed2 (Suspended p))
+ Darcs.Patch.Rebase: takeAnyRebase :: PatchSet ( 'RepoType 'IsRebase) p wA wB -> (Sealed2 (PatchInfoAnd ( 'RepoType 'IsRebase) p), Sealed2 (Suspended p))
- Darcs.Patch.Rebase: takeAnyRebaseAndTrailingPatches :: PatchSet (RepoType IsRebase) p wA wB -> FlippedSeal (PatchInfoAnd (RepoType IsRebase) p :> RL (PatchInfoAnd (RepoType IsRebase) p)) wB
+ Darcs.Patch.Rebase: takeAnyRebaseAndTrailingPatches :: PatchSet ( 'RepoType 'IsRebase) p wA wB -> FlippedSeal (PatchInfoAnd ( 'RepoType 'IsRebase) p :> RL (PatchInfoAnd ( 'RepoType 'IsRebase) p)) wB
- Darcs.Patch.Rebase: takeHeadRebase :: PatchSet (RepoType IsRebase) p wA wB -> (PatchInfoAnd (RepoType IsRebase) p wB wB, Suspended p wB wB, PatchSet (RepoType IsRebase) p wA wB)
+ Darcs.Patch.Rebase: takeHeadRebase :: PatchSet ( 'RepoType 'IsRebase) p wA wB -> (PatchInfoAnd ( 'RepoType 'IsRebase) p wB wB, Suspended p wB wB, PatchSet ( 'RepoType 'IsRebase) p wA wB)
- Darcs.Patch.Rebase: takeHeadRebaseFL :: FL (PatchInfoAnd (RepoType IsRebase) p) wA wB -> (PatchInfoAnd (RepoType IsRebase) p wB wB, Suspended p wB wB, FL (PatchInfoAnd (RepoType IsRebase) p) wA wB)
+ Darcs.Patch.Rebase: takeHeadRebaseFL :: FL (PatchInfoAnd ( 'RepoType 'IsRebase) p) wA wB -> (PatchInfoAnd ( 'RepoType 'IsRebase) p wB wB, Suspended p wB wB, FL (PatchInfoAnd ( 'RepoType 'IsRebase) p) wA wB)
- Darcs.Patch.Rebase.Fixup: [PrimFixup] :: PrimOf p wX wY -> RebaseFixup p wX wY
+ Darcs.Patch.Rebase.Fixup: [PrimFixup] :: PrimPatch (PrimOf p) => PrimOf p wX wY -> RebaseFixup p wX wY
- Darcs.Patch.Rebase.Fixup: namedToFixups :: Effect p => Named p wX wY -> FL (RebaseFixup p) wX wY
+ Darcs.Patch.Rebase.Fixup: namedToFixups :: (PrimPatch (PrimOf p), Effect p) => Named p wX wY -> FL (RebaseFixup p) wX wY
- Darcs.Patch.Rebase.Name: commuteNamePrim :: PrimPatchBase p => (RebaseName p :> PrimOf p) wX wY -> (PrimOf p :> RebaseName p) wX wY
+ Darcs.Patch.Rebase.Name: commuteNamePrim :: (RebaseName p :> PrimOf p) wX wY -> (PrimOf p :> RebaseName p) wX wY
- Darcs.Patch.Rebase.Name: commutePrimName :: PrimPatchBase p => (PrimOf p :> RebaseName p) wX wY -> (RebaseName p :> PrimOf p) wX wY
+ Darcs.Patch.Rebase.Name: commutePrimName :: (PrimOf p :> RebaseName p) wX wY -> (RebaseName p :> PrimOf p) wX wY
- Darcs.Patch.Rebase.Viewing: extractRebaseSelect :: (Commute p, Merge p, Invert p, Effect p, FromPrim p, PrimPatchBase p) => FL (RebaseSelect p) wX wY -> (FL (WDDNamed p) :> FL (RebaseFixup p)) wX wY
+ Darcs.Patch.Rebase.Viewing: extractRebaseSelect :: (Merge p, Invert p, Effect p, FromPrim p, PrimPatchBase p) => FL (RebaseSelect p) wX wY -> (FL (WDDNamed p) :> FL (RebaseFixup p)) wX wY
- Darcs.Patch.Rebase.Viewing: reifyRebaseSelect :: forall p wX wY. (PrimPatchBase p, Commute p, Merge p, Invert p, Effect p, FromPrim p) => FL (RebaseSelect p) wX wY -> IO ((FL (WDDNamed p) :> FL (RebaseFixup p)) wX wY)
+ Darcs.Patch.Rebase.Viewing: reifyRebaseSelect :: forall p wX wY. (PrimPatchBase p, FromPrim p) => FL (RebaseSelect p) wX wY -> IO ((FL (WDDNamed p) :> FL (RebaseFixup p)) wX wY)
- Darcs.Patch.Rebase.Viewing: rsToPia :: RebaseSelect p wX wY -> Sealed2 (PatchInfoAnd (RepoType NoRebase) p)
+ Darcs.Patch.Rebase.Viewing: rsToPia :: RebaseSelect p wX wY -> Sealed2 (PatchInfoAnd ( 'RepoType 'NoRebase) p)
- Darcs.Patch.Rebase.Viewing: toRebaseChanges :: PrimPatchBase p => FL (RebaseItem p) wX wY -> FL (PatchInfoAnd (RepoType IsRebase) (RebaseChange p)) wX wY
+ Darcs.Patch.Rebase.Viewing: toRebaseChanges :: PrimPatchBase p => FL (RebaseItem p) wX wY -> FL (PatchInfoAnd ( 'RepoType 'IsRebase) (RebaseChange p)) wX wY
- Darcs.Patch.Repair: class Check p where isInconsistent _ = Nothing
+ Darcs.Patch.Repair: class Check p
- Darcs.Patch.Repair: class Apply p => RepairToFL p where applyAndTryToFixFL p = do { apply p; return Nothing }
+ Darcs.Patch.Repair: class Apply p => RepairToFL p
- Darcs.Patch.RepoPatch: class (Patchy p, Merge p, Effect p, IsHunk p, PatchInspect p, ReadPatch p, ShowPatch p, FromPrim p, Conflict p, CommuteNoConflicts p, Check p, RepairToFL p, PatchListFormat p, PrimPatchBase p, Patchy (PrimOf p), IsHunk (PrimOf p), Matchable p) => RepoPatch p
+ Darcs.Patch.RepoPatch: class (Apply p, Commute p, Invert p, Merge p, Effect p, IsHunk p, PatchInspect p, ReadPatch p, ShowPatch p, ShowContextPatch p, FromPrim p, Conflict p, CommuteNoConflicts p, Check p, RepairToFL p, PatchListFormat p, PrimPatchBase p, IsHunk (PrimOf p), Matchable p, Annotate p, ApplyState p ~ ApplyState (PrimOf p)) => RepoPatch p
- Darcs.Patch.RepoType: [SIsRebase] :: SRebaseType IsRebase
+ Darcs.Patch.RepoType: [SIsRebase] :: SRebaseType 'IsRebase
- Darcs.Patch.RepoType: [SNoRebase] :: SRebaseType NoRebase
+ Darcs.Patch.RepoType: [SNoRebase] :: SRebaseType 'NoRebase
- Darcs.Patch.RepoType: [SRepoType] :: SRebaseType rebaseType -> SRepoType (RepoType rebaseType)
+ Darcs.Patch.RepoType: [SRepoType] :: SRebaseType rebaseType -> SRepoType ( 'RepoType rebaseType)
- Darcs.Patch.Show: class ShowPatchBasic p => ShowPatch p where showNicely = showPatch showContextPatch p = return $ showPatch p description = showPatch thing _ = "patch" things x = plural (Noun $ thing x) ""
+ Darcs.Patch.Show: class ShowPatchBasic p => ShowPatch p
- Darcs.Patch.Show: showContextPatch :: (ShowPatch p, Monad m, ApplyMonad (ApplyState p) m) => p wX wY -> m Doc
+ Darcs.Patch.Show: showContextPatch :: (ShowContextPatch p, (ApplyMonad (ApplyState p) m)) => ShowPatchFor -> p wX wY -> m Doc
- Darcs.Patch.Show: showPatch :: ShowPatchBasic p => p wX wY -> Doc
+ Darcs.Patch.Show: showPatch :: ShowPatchBasic p => ShowPatchFor -> p wX wY -> Doc
- Darcs.Patch.Summary: plainSummary :: (Conflict e, Effect e, PrimPatchBase e) => e wX wY -> Doc
+ Darcs.Patch.Summary: plainSummary :: (Conflict e, PrimPatchBase e) => e wX wY -> Doc
- Darcs.Patch.Summary: plainSummaryPrims :: PrimDetails prim => Bool -> [FileName] -> FL prim wX wY -> Doc
+ Darcs.Patch.Summary: plainSummaryPrims :: PrimDetails prim => Bool -> FL prim wX wY -> Doc
- Darcs.Patch.Summary: xmlSummary :: (Effect p, Conflict p, PrimPatchBase p) => p wX wY -> Doc
+ Darcs.Patch.Summary: xmlSummary :: (Conflict p, PrimPatchBase p) => p wX wY -> Doc
- Darcs.Patch.TouchesFiles: choosePreTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree) => Maybe [FilePath] -> FL p wX wY -> Sealed (FL p wX)
+ Darcs.Patch.TouchesFiles: choosePreTouching :: (Apply p, Commute p, Invert p, PatchInspect p, ApplyState p ~ Tree) => Maybe [FilePath] -> FL p wX wY -> Sealed (FL p wX)
- Darcs.Patch.TouchesFiles: chooseTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree) => Maybe [FilePath] -> FL p wX wY -> Sealed (FL p wX)
+ Darcs.Patch.TouchesFiles: chooseTouching :: (Apply p, Commute p, PatchInspect p, ApplyState p ~ Tree) => Maybe [FilePath] -> FL p wX wY -> Sealed (FL p wX)
- Darcs.Patch.TouchesFiles: deselectNotTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree) => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY
+ Darcs.Patch.TouchesFiles: deselectNotTouching :: (Apply p, Commute p, PatchInspect p, ApplyState p ~ Tree) => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY
- Darcs.Patch.TouchesFiles: lookTouch :: (Patchy p, PatchInspect p, ApplyState p ~ Tree) => Maybe [(FilePath, FilePath)] -> [FilePath] -> p wX wY -> (Bool, [FilePath], [FilePath], [(FilePath, FilePath)])
+ Darcs.Patch.TouchesFiles: lookTouch :: (Apply p, ApplyState p ~ Tree) => Maybe [(FilePath, FilePath)] -> [FilePath] -> p wX wY -> (Bool, [FilePath], [FilePath], [(FilePath, FilePath)])
- Darcs.Patch.TouchesFiles: selectNotTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree) => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY
+ Darcs.Patch.TouchesFiles: selectNotTouching :: (Apply p, Commute p, PatchInspect p, ApplyState p ~ Tree) => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY
- Darcs.Patch.TouchesFiles: selectTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree) => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY
+ Darcs.Patch.TouchesFiles: selectTouching :: (Apply p, Commute p, PatchInspect p, ApplyState p ~ Tree) => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY
- Darcs.Patch.V1.Show: showPatch_ :: PrimPatch prim => RepoPatchV1 prim wA wB -> Doc
+ Darcs.Patch.V1.Show: showPatch_ :: ShowPatchBasic prim => prim wX wY -> Doc
- Darcs.Patch.V2.Non: (*>) :: (Patchy p, ToFromPrim p) => Non p wX -> p wX wY -> Maybe (Non p wY)
+ Darcs.Patch.V2.Non: (*>) :: (Commute p, Invert p, ToFromPrim p) => Non p wX -> p wX wY -> Maybe (Non p wY)
- Darcs.Patch.V2.Non: (*>>) :: (WL l, Patchy p, ToFromPrim p, PrimPatchBase p) => Non p wX -> l (PrimOf p) wX wY -> Maybe (Non p wY)
+ Darcs.Patch.V2.Non: (*>>) :: (WL l, Apply p, Commute p, Invert p, ToFromPrim p, PrimPatchBase p) => Non p wX -> l (PrimOf p) wX wY -> Maybe (Non p wY)
- Darcs.Patch.V2.Non: (>*) :: (Patchy p, ToFromPrim p) => p wX wY -> Non p wY -> Maybe (Non p wX)
+ Darcs.Patch.V2.Non: (>*) :: (Commute p, ToFromPrim p) => p wX wY -> Non p wY -> Maybe (Non p wX)
- Darcs.Patch.V2.Non: (>>*) :: (WL l, Patchy p, ToFromPrim p) => l (PrimOf p) wX wY -> Non p wY -> Maybe (Non p wX)
+ Darcs.Patch.V2.Non: (>>*) :: (WL l, Apply p, Commute p, Invert p, ToFromPrim p) => l (PrimOf p) wX wY -> Non p wY -> Maybe (Non p wX)
- Darcs.Patch.V2.Non: commuteOrAddToCtx :: (Patchy p, ToFromPrim p) => p wX wY -> Non p wY -> Non p wX
+ Darcs.Patch.V2.Non: commuteOrAddToCtx :: (Commute p, ToFromPrim p) => p wX wY -> Non p wY -> Non p wX
- Darcs.Patch.V2.Non: commuteOrAddToCtxRL :: (Patchy p, ToFromPrim p) => RL p wX wY -> Non p wY -> Non p wX
+ Darcs.Patch.V2.Non: commuteOrAddToCtxRL :: (Apply p, Commute p, Invert p, ToFromPrim p) => RL p wX wY -> Non p wY -> Non p wX
- Darcs.Patch.V2.Non: commuteOrRemFromCtx :: (Patchy p, MyEq p, ToFromPrim p) => p wX wY -> Non p wX -> Maybe (Non p wY)
+ Darcs.Patch.V2.Non: commuteOrRemFromCtx :: (Commute p, Invert p, Eq2 p, ToFromPrim p) => p wX wY -> Non p wX -> Maybe (Non p wY)
- Darcs.Patch.V2.Non: commuteOrRemFromCtxFL :: (Patchy p, MyEq p, ToFromPrim p) => FL p wX wY -> Non p wX -> Maybe (Non p wY)
+ Darcs.Patch.V2.Non: commuteOrRemFromCtxFL :: (Apply p, Commute p, Invert p, Eq2 p, ToFromPrim p) => FL p wX wY -> Non p wX -> Maybe (Non p wY)
- Darcs.Patch.V2.Non: commutePrimsOrAddToCtx :: (WL l, Patchy p, ToFromPrim p) => l (PrimOf p) wX wY -> Non p wY -> Non p wX
+ Darcs.Patch.V2.Non: commutePrimsOrAddToCtx :: (WL l, Apply p, Commute p, Invert p, ToFromPrim p) => l (PrimOf p) wX wY -> Non p wY -> Non p wX
- Darcs.Patch.V2.Non: remNons :: (Nonable p, Effect p, Patchy p, MyEq p, ToFromPrim p, PrimPatchBase p, MyEq (PrimOf p)) => [Non p wX] -> Non p wX -> Non p wX
+ Darcs.Patch.V2.Non: remNons :: (Nonable p, Effect p, Apply p, Commute p, Invert p, Eq2 p, ToFromPrim p, PrimPatchBase p) => [Non p wX] -> Non p wX -> Non p wX
- Darcs.Patch.V2.Non: showNon :: (ShowPatchBasic p, PatchListFormat p, PrimPatchBase p) => Non p wX -> Doc
+ Darcs.Patch.V2.Non: showNon :: (ShowPatchBasic p, PatchListFormat p, PrimPatchBase p) => ShowPatchFor -> Non p wX -> Doc
- Darcs.Patch.V2.Non: showNons :: (ShowPatchBasic p, PatchListFormat p, PrimPatchBase p) => [Non p wX] -> Doc
+ Darcs.Patch.V2.Non: showNons :: (ShowPatchBasic p, PatchListFormat p, PrimPatchBase p) => ShowPatchFor -> [Non p wX] -> Doc
- Darcs.Patch.Viewing: showContextHunk :: (ApplyMonad Tree m) => FileHunk wX wY -> m Doc
+ Darcs.Patch.Viewing: showContextHunk :: (ApplyMonad Tree m) => FileNameFormat -> FileHunk wX wY -> m Doc
- Darcs.Patch.Witnesses.Eq: (=/\=) :: MyEq p => p wA wC -> p wB wC -> EqCheck wA wB
+ Darcs.Patch.Witnesses.Eq: (=/\=) :: Eq2 p => p wA wC -> p wB wC -> EqCheck wA wB
- Darcs.Patch.Witnesses.Eq: (=\/=) :: MyEq p => p wA wB -> p wA wC -> EqCheck wB wC
+ Darcs.Patch.Witnesses.Eq: (=\/=) :: Eq2 p => p wA wB -> p wA wC -> EqCheck wB wC
- Darcs.Patch.Witnesses.Eq: unsafeCompare :: MyEq p => p wA wB -> p wC wD -> Bool
+ Darcs.Patch.Witnesses.Eq: unsafeCompare :: Eq2 p => p wA wB -> p wC wD -> Bool
- Darcs.Patch.Witnesses.Ordered: eqFL :: MyEq a => FL a wX wY -> FL a wX wZ -> EqCheck wY wZ
+ Darcs.Patch.Witnesses.Ordered: eqFL :: Eq2 a => FL a wX wY -> FL a wX wZ -> EqCheck wY wZ
- Darcs.Patch.Witnesses.Ordered: eqFLRev :: MyEq a => FL a wX wZ -> FL a wY wZ -> EqCheck wX wY
+ Darcs.Patch.Witnesses.Ordered: eqFLRev :: Eq2 a => FL a wX wZ -> FL a wY wZ -> EqCheck wX wY
- Darcs.Patch.Witnesses.Ordered: eqFLUnsafe :: MyEq a => FL a wX wY -> FL a wZ wW -> Bool
+ Darcs.Patch.Witnesses.Ordered: eqFLUnsafe :: Eq2 a => FL a wX wY -> FL a wZ wW -> Bool
- Darcs.Patch.Witnesses.Ordered: infixl 5 +<+
+ Darcs.Patch.Witnesses.Ordered: infixl 5 +<<+
- Darcs.Patch.Witnesses.Ordered: infixr 5 +>+
+ Darcs.Patch.Witnesses.Ordered: infixr 5 +>>+
- Darcs.Repository: PrimV1Job :: (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, PrimOf p ~ Prim) => Repository rt p wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository: PrimV1Job :: (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, IsPrimV1 (PrimOf p)) => Repository rt p wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository: RebaseAwareJob :: RebaseJobFlags -> (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository: RebaseAwareJob :: RebaseJobFlags -> (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository: RebaseJob :: RebaseJobFlags -> (forall p wR wU. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository (RepoType IsRebase) p wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository: RebaseJob :: RebaseJobFlags -> (forall p wR wU. (RepoPatch p, ApplyState p ~ Tree) => Repository ( 'RepoType 'IsRebase) p wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository: RepoJob :: (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository: RepoJob :: (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository: StartRebaseJob :: RebaseJobFlags -> (forall p wR wU. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository (RepoType IsRebase) p wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository: StartRebaseJob :: RebaseJobFlags -> (forall p wR wU. (RepoPatch p, ApplyState p ~ Tree) => Repository ( 'RepoType 'IsRebase) p wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository: V1Job :: (forall wR wU. Repository (RepoType NoRebase) (RepoPatchV1 Prim) wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository: V1Job :: (forall wR wU. Repository ( 'RepoType 'NoRebase) (RepoPatchV1 Prim) wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository: V2Job :: (forall rt wR wU. Repository rt (RepoPatchV2 Prim) wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository: V2Job :: (forall rt wR wU. IsRepoType rt => Repository rt (RepoPatchV2 Prim) wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository: addPendingDiffToPending :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> FreeLeft (FL (PrimOf p)) -> IO ()
+ Darcs.Repository: addPendingDiffToPending :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> FreeLeft (FL (PrimOf p)) -> IO ()
- Darcs.Repository: addToPending :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wU wY -> IO ()
+ Darcs.Repository: addToPending :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wU wY -> IO ()
- Darcs.Repository: applyToWorking :: (ApplyState (PrimOf p) ~ Tree, RepoPatch p) => Repository rt p wR wU wT -> Verbosity -> FL (PrimOf p) wU wY -> IO (Repository rt p wR wY wT)
+ Darcs.Repository: applyToWorking :: (ApplyState p ~ Tree, RepoPatch p) => Repository rt p wR wU wT -> Verbosity -> FL (PrimOf p) wU wY -> IO (Repository rt p wR wY wT)
- Darcs.Repository: cleanRepository :: RepoPatch p => Repository rt p wR wU wT -> IO ()
+ Darcs.Repository: cleanRepository :: Repository rt p wR wU wT -> IO ()
- Darcs.Repository: considerMergeToWorking :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wT -> String -> AllowConflicts -> UpdateWorking -> ExternalMerge -> WantGuiPause -> Compression -> Verbosity -> Reorder -> (UseIndex, ScanKnown, DiffAlgorithm) -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wY -> IO (Sealed (FL (PrimOf p) wU))
+ Darcs.Repository: considerMergeToWorking :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> String -> AllowConflicts -> UpdateWorking -> ExternalMerge -> WantGuiPause -> Compression -> Verbosity -> Reorder -> (UseIndex, ScanKnown, DiffAlgorithm) -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wY -> IO (Sealed (FL (PrimOf p) wU))
- Darcs.Repository: createPartialsPristineDirectoryTree :: (FilePathLike fp, RepoPatch p) => Repository rt p wR wU wT -> [fp] -> FilePath -> IO ()
+ Darcs.Repository: createPartialsPristineDirectoryTree :: (FilePathLike fp) => Repository rt p wR wU wT -> [fp] -> FilePath -> IO ()
- Darcs.Repository: createPristineDirectoryTree :: RepoPatch p => Repository rt p wR wU wT -> FilePath -> WithWorkingDir -> IO ()
+ Darcs.Repository: createPristineDirectoryTree :: Repository rt p wR wU wT -> FilePath -> WithWorkingDir -> IO ()
- Darcs.Repository: createRepository :: PatchFormat -> WithWorkingDir -> WithPatchIndex -> IO ()
+ Darcs.Repository: createRepository :: PatchFormat -> WithWorkingDir -> WithPatchIndex -> UseCache -> IO EmptyRepository
- Darcs.Repository: filterOutConflicts :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => RL (PatchInfoAnd rt p) wX wT -> Repository rt p wR wU wT -> FL (PatchInfoAnd rt p) wX wZ -> IO (Bool, Sealed (FL (PatchInfoAnd rt p) wX))
+ Darcs.Repository: filterOutConflicts :: (RepoPatch p, ApplyState p ~ Tree) => RL (PatchInfoAnd rt p) wX wT -> Repository rt p wR wU wT -> FL (PatchInfoAnd rt p) wX wZ -> IO (Bool, Sealed (FL (PatchInfoAnd rt p) wX))
- Darcs.Repository: identifyRepositoryFor :: forall rt p wR wU wT vR vU vT. RepoPatch p => Repository rt p wR wU wT -> UseCache -> String -> IO (Repository rt p vR vU vT)
+ Darcs.Repository: identifyRepositoryFor :: forall rt p wR wU wT vR vU vT. Repository rt p wR wU wT -> UseCache -> String -> IO (Repository rt p vR vU vT)
- Darcs.Repository: modifyCache :: forall rt p wR wU wT. (RepoPatch p) => Repository rt p wR wU wT -> (Cache -> Cache) -> Repository rt p wR wU wT
+ Darcs.Repository: modifyCache :: forall rt p wR wU wT. Repository rt p wR wU wT -> (Cache -> Cache) -> Repository rt p wR wU wT
- Darcs.Repository: prefsUrl :: Repository rt p wR wU wT -> String
+ Darcs.Repository: prefsUrl :: FilePath -> String
- Darcs.Repository: readPending :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (Tree IO, Sealed (FL p wT))
+ Darcs.Repository: readPending :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (Tree IO, Sealed (FL (PrimOf p) wT))
- Darcs.Repository: readRecorded :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (Tree IO)
+ Darcs.Repository: readRecorded :: Repository rt p wR wU wT -> IO (Tree IO)
- Darcs.Repository: readRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (PatchSet rt p Origin wR)
+ Darcs.Repository: readRepo :: (IsRepoType rt, RepoPatch p) => Repository rt p wR wU wT -> IO (PatchSet rt p Origin wR)
- Darcs.Repository: readTentativeRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (PatchSet rt p Origin wT)
+ Darcs.Repository: readTentativeRepo :: (IsRepoType rt, RepoPatch p) => Repository rt p wR wU wT -> String -> IO (PatchSet rt p Origin wT)
- Darcs.Repository: tentativelyMergePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wT -> String -> AllowConflicts -> UpdateWorking -> ExternalMerge -> WantGuiPause -> Compression -> Verbosity -> Reorder -> (UseIndex, ScanKnown, DiffAlgorithm) -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wY -> IO (Sealed (FL (PrimOf p) wU))
+ Darcs.Repository: tentativelyMergePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> String -> AllowConflicts -> UpdateWorking -> ExternalMerge -> WantGuiPause -> Compression -> Verbosity -> Reorder -> (UseIndex, ScanKnown, DiffAlgorithm) -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wY -> IO (Sealed (FL (PrimOf p) wU))
- Darcs.Repository: testTentative :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> RunTest -> LeaveTestDir -> SetScriptsExecutable -> Verbosity -> IO ExitCode
+ Darcs.Repository: testTentative :: Repository rt p wR wU wT -> RunTest -> LeaveTestDir -> SetScriptsExecutable -> Verbosity -> IO ExitCode
- Darcs.Repository: unrecordedChanges :: forall rt p wR wU wT. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => (UseIndex, ScanKnown, DiffAlgorithm) -> Repository rt p wR wU wT -> Maybe [SubPath] -> IO (FL (PrimOf p) wT wU)
+ Darcs.Repository: unrecordedChanges :: (RepoPatch p, ApplyState p ~ Tree) => (UseIndex, ScanKnown, DiffAlgorithm) -> LookForMoves -> LookForReplaces -> Repository rt p wR wU wT -> Maybe [SubPath] -> IO (FL (PrimOf p) wT wU)
- Darcs.Repository: withRecorded :: RepoPatch p => Repository rt p wR wU wT -> ((AbsolutePath -> IO a) -> IO a) -> (AbsolutePath -> IO a) -> IO a
+ Darcs.Repository: withRecorded :: Repository rt p wR wU wT -> ((AbsolutePath -> IO a) -> IO a) -> (AbsolutePath -> IO a) -> IO a
- Darcs.Repository: withRepoLockCanFail :: UseCache -> UpdateWorking -> UMask -> RepoJob () -> IO ()
+ Darcs.Repository: withRepoLockCanFail :: UseCache -> RepoJob () -> IO ()
- Darcs.Repository: writePatchSet :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => PatchSet rt p Origin wX -> UseCache -> IO (Repository rt p wR wU wT)
+ Darcs.Repository: writePatchSet :: (IsRepoType rt, RepoPatch p) => PatchSet rt p Origin wX -> UseCache -> IO (Repository rt p wR wU wT)
- Darcs.Repository.ApplyPatches: applyPatches :: (MonadProgress m, ApplyMonad (ApplyState p) m, Patchy p) => FL (PatchInfoAnd rt p) wX wY -> m ()
+ Darcs.Repository.ApplyPatches: applyPatches :: (MonadProgress m, ApplyMonad (ApplyState p) m, Apply p) => FL (PatchInfoAnd rt p) wX wY -> m ()
- Darcs.Repository.Clone: writePatchSet :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => PatchSet rt p Origin wX -> UseCache -> IO (Repository rt p wR wU wT)
+ Darcs.Repository.Clone: writePatchSet :: (IsRepoType rt, RepoPatch p) => PatchSet rt p Origin wX -> UseCache -> IO (Repository rt p wR wU wT)
- Darcs.Repository.Diff: treeDiff :: forall m w prim. (Functor m, Monad m, Gap w, PrimPatch prim) => DiffAlgorithm -> (FilePath -> FileType) -> Tree m -> Tree m -> m (w (FL prim))
+ Darcs.Repository.Diff: treeDiff :: forall m w prim. (Monad m, Gap w, PrimPatch prim) => DiffAlgorithm -> (FilePath -> FileType) -> Tree m -> Tree m -> m (w (FL prim))
- Darcs.Repository.InternalTypes: HashedPristine :: Pristine
+ Darcs.Repository.InternalTypes: HashedPristine :: PristineType
- Darcs.Repository.InternalTypes: NoPristine :: Pristine
+ Darcs.Repository.InternalTypes: NoPristine :: PristineType
- Darcs.Repository.InternalTypes: PlainPristine :: Pristine
+ Darcs.Repository.InternalTypes: PlainPristine :: PristineType
- Darcs.Repository.InternalTypes: modifyCache :: forall rt p wR wU wT. (RepoPatch p) => Repository rt p wR wU wT -> (Cache -> Cache) -> Repository rt p wR wU wT
+ Darcs.Repository.InternalTypes: modifyCache :: forall rt p wR wU wT. Repository rt p wR wU wT -> (Cache -> Cache) -> Repository rt p wR wU wT
- Darcs.Repository.Job: PrimV1Job :: (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, PrimOf p ~ Prim) => Repository rt p wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository.Job: PrimV1Job :: (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, IsPrimV1 (PrimOf p)) => Repository rt p wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository.Job: RebaseAwareJob :: RebaseJobFlags -> (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository.Job: RebaseAwareJob :: RebaseJobFlags -> (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository.Job: RebaseJob :: RebaseJobFlags -> (forall p wR wU. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository (RepoType IsRebase) p wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository.Job: RebaseJob :: RebaseJobFlags -> (forall p wR wU. (RepoPatch p, ApplyState p ~ Tree) => Repository ( 'RepoType 'IsRebase) p wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository.Job: RepoJob :: (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository.Job: RepoJob :: (forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository.Job: StartRebaseJob :: RebaseJobFlags -> (forall p wR wU. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository (RepoType IsRebase) p wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository.Job: StartRebaseJob :: RebaseJobFlags -> (forall p wR wU. (RepoPatch p, ApplyState p ~ Tree) => Repository ( 'RepoType 'IsRebase) p wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository.Job: V1Job :: (forall wR wU. Repository (RepoType NoRebase) (RepoPatchV1 Prim) wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository.Job: V1Job :: (forall wR wU. Repository ( 'RepoType 'NoRebase) (RepoPatchV1 Prim) wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository.Job: V2Job :: (forall rt wR wU. Repository rt (RepoPatchV2 Prim) wR wU wR -> IO a) -> RepoJob a
+ Darcs.Repository.Job: V2Job :: (forall rt wR wU. IsRepoType rt => Repository rt (RepoPatchV2 Prim) wR wU wR -> IO a) -> RepoJob a
- Darcs.Repository.Job: withRepoLockCanFail :: UseCache -> UpdateWorking -> UMask -> RepoJob () -> IO ()
+ Darcs.Repository.Job: withRepoLockCanFail :: UseCache -> RepoJob () -> IO ()
- Darcs.Repository.Match: getOnePatchset :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> [MatchFlag] -> IO (SealedPatchSet rt p Origin)
+ Darcs.Repository.Match: getOnePatchset :: (IsRepoType rt, RepoPatch p) => Repository rt p wR wU wT -> [MatchFlag] -> IO (SealedPatchSet rt p Origin)
- Darcs.Repository.Merge: considerMergeToWorking :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wT -> String -> AllowConflicts -> UpdateWorking -> ExternalMerge -> WantGuiPause -> Compression -> Verbosity -> Reorder -> (UseIndex, ScanKnown, DiffAlgorithm) -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wY -> IO (Sealed (FL (PrimOf p) wU))
+ Darcs.Repository.Merge: considerMergeToWorking :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> String -> AllowConflicts -> UpdateWorking -> ExternalMerge -> WantGuiPause -> Compression -> Verbosity -> Reorder -> (UseIndex, ScanKnown, DiffAlgorithm) -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wY -> IO (Sealed (FL (PrimOf p) wU))
- Darcs.Repository.Merge: tentativelyMergePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wT -> String -> AllowConflicts -> UpdateWorking -> ExternalMerge -> WantGuiPause -> Compression -> Verbosity -> Reorder -> (UseIndex, ScanKnown, DiffAlgorithm) -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wY -> IO (Sealed (FL (PrimOf p) wU))
+ Darcs.Repository.Merge: tentativelyMergePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> String -> AllowConflicts -> UpdateWorking -> ExternalMerge -> WantGuiPause -> Compression -> Verbosity -> Reorder -> (UseIndex, ScanKnown, DiffAlgorithm) -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wY -> IO (Sealed (FL (PrimOf p) wU))
- Darcs.Repository.PatchIndex: attemptCreatePatchIndex :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO ()
+ Darcs.Repository.PatchIndex: attemptCreatePatchIndex :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> PatchSet rt p Origin wR -> IO ()
- Darcs.Repository.PatchIndex: canUsePatchIndex :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO Bool
+ Darcs.Repository.PatchIndex: canUsePatchIndex :: Repository rt p wR wU wT -> IO Bool
- Darcs.Repository.PatchIndex: createOrUpdatePatchIndexDisk :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO ()
+ Darcs.Repository.PatchIndex: createOrUpdatePatchIndexDisk :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> PatchSet rt p Origin wR -> IO ()
- Darcs.Repository.PatchIndex: createPIWithInterrupt :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO ()
+ Darcs.Repository.PatchIndex: createPIWithInterrupt :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> PatchSet rt p Origin wR -> IO ()
- Darcs.Repository.PatchIndex: getRelevantSubsequence :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, a ~ PatchInfoAnd rt p) => Sealed ((RL a) wK) -> Repository rt p wR wU wR -> [FileName] -> IO (Sealed ((RL a) Origin))
+ Darcs.Repository.PatchIndex: getRelevantSubsequence :: (RepoPatch p, ApplyState p ~ Tree, a ~ PatchInfoAnd rt p) => Sealed ((RL a) wK) -> Repository rt p wR wU wR -> PatchSet rt p Origin wR -> [FileName] -> IO (Sealed ((RL a) Origin))
- Darcs.Repository.PatchIndex: isPatchIndexInSync :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO Bool
+ Darcs.Repository.PatchIndex: isPatchIndexInSync :: Repository rt p wR wU wT -> IO Bool
- Darcs.Repository.PatchIndex: maybeFilterPatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> PatchFilter rt p
+ Darcs.Repository.PatchIndex: maybeFilterPatches :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> PatchSet rt p Origin wR -> PatchFilter rt p
- Darcs.Repository.PatchIndex: piTest :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO ()
+ Darcs.Repository.PatchIndex: piTest :: FilePath -> IO ()
- Darcs.Repository.Rebase: maybeDisplaySuspendedStatus :: (RepoPatch p, ApplyState p ~ Tree) => SRebaseType rebaseType -> Repository (RepoType rebaseType) p wR wU wR -> IO ()
+ Darcs.Repository.Rebase: maybeDisplaySuspendedStatus :: RepoPatch p => SRebaseType rebaseType -> Repository ( 'RepoType rebaseType) p wR wU wR -> IO ()
- Darcs.Repository.Rebase: rebaseJob :: (RepoPatch p, ApplyState p ~ Tree) => (Repository (RepoType IsRebase) p wR wU wR -> IO a) -> Repository (RepoType IsRebase) p wR wU wR -> RebaseJobFlags -> IO a
+ Darcs.Repository.Rebase: rebaseJob :: (RepoPatch p, ApplyState p ~ Tree) => (Repository ( 'RepoType 'IsRebase) p wR wU wR -> IO a) -> Repository ( 'RepoType 'IsRebase) p wR wU wR -> RebaseJobFlags -> IO a
- Darcs.Repository.Rebase: startRebaseJob :: (RepoPatch p, ApplyState p ~ Tree) => (Repository (RepoType IsRebase) p wR wU wR -> IO a) -> Repository (RepoType IsRebase) p wR wU wR -> RebaseJobFlags -> IO a
+ Darcs.Repository.Rebase: startRebaseJob :: (RepoPatch p, ApplyState p ~ Tree) => (Repository ( 'RepoType 'IsRebase) p wR wU wR -> IO a) -> Repository ( 'RepoType 'IsRebase) p wR wU wR -> RebaseJobFlags -> IO a
- Darcs.Repository.State: filterOutConflicts :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => RL (PatchInfoAnd rt p) wX wT -> Repository rt p wR wU wT -> FL (PatchInfoAnd rt p) wX wZ -> IO (Bool, Sealed (FL (PatchInfoAnd rt p) wX))
+ Darcs.Repository.State: filterOutConflicts :: (RepoPatch p, ApplyState p ~ Tree) => RL (PatchInfoAnd rt p) wX wT -> Repository rt p wR wU wT -> FL (PatchInfoAnd rt p) wX wZ -> IO (Bool, Sealed (FL (PatchInfoAnd rt p) wX))
- Darcs.Repository.State: maybeRestrictSubpaths :: forall rt p m wR wU wT. (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Maybe [SubPath] -> IO (TreeFilter m)
+ Darcs.Repository.State: maybeRestrictSubpaths :: (RepoPatch p, ApplyState p ~ Tree) => FL (PrimOf p) wT wP -> Repository rt p wR wU wT -> Maybe [SubPath] -> IO (TreeFilter m)
- Darcs.Repository.State: readPending :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (Tree IO, Sealed (FL p wT))
+ Darcs.Repository.State: readPending :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (Tree IO, Sealed (FL (PrimOf p) wT))
- Darcs.Repository.State: readPendingAndWorking :: forall rt p wR wU wT. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => (UseIndex, ScanKnown, DiffAlgorithm) -> Repository rt p wR wU wT -> Maybe [SubPath] -> IO ((FL (PrimOf p) :> FL (PrimOf p)) wT wU)
+ Darcs.Repository.State: readPendingAndWorking :: forall rt p wR wU wT. (RepoPatch p, ApplyState p ~ Tree) => (UseIndex, ScanKnown, DiffAlgorithm) -> LookForMoves -> LookForReplaces -> Repository rt p wR wU wT -> Maybe [SubPath] -> IO ((FL (PrimOf p) :> FL (PrimOf p)) wT wU)
- Darcs.Repository.State: readRecorded :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (Tree IO)
+ Darcs.Repository.State: readRecorded :: Repository rt p wR wU wT -> IO (Tree IO)
- Darcs.Repository.State: readUnrecordedFiltered :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UseIndex -> ScanKnown -> Maybe [SubPath] -> IO (Tree IO)
+ Darcs.Repository.State: readUnrecordedFiltered :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> UseIndex -> ScanKnown -> LookForMoves -> Maybe [SubPath] -> IO (Tree IO)
- Darcs.Repository.State: restrictBoring :: forall m. Tree m -> IO (TreeFilter m)
+ Darcs.Repository.State: restrictBoring :: Tree m -> IO (TreeFilter m)
- Darcs.Repository.State: restrictDarcsdir :: forall m. TreeFilter m
+ Darcs.Repository.State: restrictDarcsdir :: TreeFilter m
- Darcs.Repository.State: restrictSubpaths :: forall rt p m wR wU wT. (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> [SubPath] -> IO (TreeFilter m)
+ Darcs.Repository.State: restrictSubpaths :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> [SubPath] -> IO (TreeFilter m)
- Darcs.Repository.State: unrecordedChanges :: forall rt p wR wU wT. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => (UseIndex, ScanKnown, DiffAlgorithm) -> Repository rt p wR wU wT -> Maybe [SubPath] -> IO (FL (PrimOf p) wT wU)
+ Darcs.Repository.State: unrecordedChanges :: (RepoPatch p, ApplyState p ~ Tree) => (UseIndex, ScanKnown, DiffAlgorithm) -> LookForMoves -> LookForReplaces -> Repository rt p wR wU wT -> Maybe [SubPath] -> IO (FL (PrimOf p) wT wU)
- Darcs.Repository.Test: runPosthook :: Maybe String -> Bool -> Verbosity -> AbsolutePath -> IO ExitCode
+ Darcs.Repository.Test: runPosthook :: HookConfig -> Verbosity -> AbsolutePath -> IO ExitCode
- Darcs.Repository.Test: runPrehook :: Maybe String -> Bool -> Verbosity -> AbsolutePath -> IO ExitCode
+ Darcs.Repository.Test: runPrehook :: HookConfig -> Verbosity -> AbsolutePath -> IO ExitCode
- Darcs.Repository.Test: testTentative :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> RunTest -> LeaveTestDir -> SetScriptsExecutable -> Verbosity -> IO ExitCode
+ Darcs.Repository.Test: testTentative :: Repository rt p wR wU wT -> RunTest -> LeaveTestDir -> SetScriptsExecutable -> Verbosity -> IO ExitCode
- Darcs.UI.ApplyPatches: applyPatches :: forall rt p wR wU wT wX wZ. (PatchApplier pa, ApplierRepoTypeConstraint pa rt, IsRepoType rt, RepoPatch p, ApplyState (PrimOf p) ~ Tree, ApplyState p ~ Tree) => pa -> PatchProxy p -> String -> [DarcsFlag] -> String -> Repository rt p wR wU wT -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wZ -> IO ()
+ Darcs.UI.ApplyPatches: applyPatches :: forall rt p wR wU wT wX wZ. (PatchApplier pa, ApplierRepoTypeConstraint pa rt, IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => pa -> PatchProxy p -> String -> [DarcsFlag] -> String -> Repository rt p wR wU wT -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wZ -> IO ()
- Darcs.UI.ApplyPatches: class PatchApplier pa where type ApplierRepoTypeConstraint pa (rt :: RepoType) :: Constraint where {
+ Darcs.UI.ApplyPatches: class PatchApplier pa where {
- Darcs.UI.ApplyPatches: repoJob :: PatchApplier pa => pa -> [DarcsFlag] -> (forall rt p wR wU. (IsRepoType rt, ApplierRepoTypeConstraint pa rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => (PatchProxy p -> Repository rt p wR wU wR -> IO ())) -> RepoJob ()
+ Darcs.UI.ApplyPatches: repoJob :: PatchApplier pa => pa -> [DarcsFlag] -> (forall rt p wR wU. (IsRepoType rt, ApplierRepoTypeConstraint pa rt, RepoPatch p, ApplyState p ~ Tree) => (PatchProxy p -> Repository rt p wR wU wR -> IO ())) -> RepoJob ()
- Darcs.UI.ApplyPatches: type family ApplierRepoTypeConstraint pa
+ Darcs.UI.ApplyPatches: type family ApplierRepoTypeConstraint pa (rt :: RepoType) :: Constraint;
- Darcs.UI.Commands: DarcsCommand :: String -> Int -> [String] -> ((AbsolutePath, AbsolutePath) -> parsedFlags -> [String] -> IO ()) -> ([DarcsFlag] -> IO (Either String ())) -> IO [String] -> ([DarcsFlag] -> AbsolutePath -> [String] -> IO [String]) -> [DarcsOptDescr DarcsFlag] -> [DarcsOptDescr DarcsFlag] -> [DarcsFlag] -> ([DarcsFlag] -> [String]) -> ([DarcsFlag] -> parsedFlags) -> DarcsCommand parsedFlags
+ Darcs.UI.Commands: DarcsCommand :: String -> Int -> [String] -> ((AbsolutePath, AbsolutePath) -> parsedFlags -> [String] -> IO ()) -> ([DarcsFlag] -> IO (Either String ())) -> ((AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO [String]) -> ([DarcsFlag] -> AbsolutePath -> [String] -> IO [String]) -> [DarcsOptDescr DarcsFlag] -> [DarcsOptDescr DarcsFlag] -> [DarcsFlag] -> ([DarcsFlag] -> [String]) -> ([DarcsFlag] -> parsedFlags) -> DarcsCommand parsedFlags
- Darcs.UI.Commands: setEnvDarcsFiles :: (PatchInspect p, Patchy p) => p wX wY -> IO ()
+ Darcs.UI.Commands: setEnvDarcsFiles :: (PatchInspect p) => p wX wY -> IO ()
- Darcs.UI.Commands: withStdOpts :: DarcsOption (Maybe StdCmdAction -> Bool -> Bool -> Verbosity -> Bool -> b) c -> DarcsOption (UseCache -> Maybe String -> Bool -> Maybe String -> Bool -> a) b -> DarcsOption a c
+ Darcs.UI.Commands: withStdOpts :: DarcsOption (Maybe StdCmdAction -> Bool -> Bool -> Verbosity -> Bool -> b) c -> DarcsOption (UseCache -> HooksConfig -> a) b -> DarcsOption a c
- Darcs.UI.Commands.Pull: fetchPatches :: forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => AbsolutePath -> [DarcsFlag] -> [String] -> String -> Repository rt p wR wU wR -> IO (SealedPatchSet rt p Origin, Sealed ((FL (PatchInfoAnd rt p) :\/: FL (PatchInfoAnd rt p)) wR))
+ Darcs.UI.Commands.Pull: fetchPatches :: forall rt p wR wU. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => AbsolutePath -> [DarcsFlag] -> [String] -> String -> Repository rt p wR wU wR -> IO (SealedPatchSet rt p Origin, Sealed ((FL (PatchInfoAnd rt p) :\/: FL (PatchInfoAnd rt p)) wR))
- Darcs.UI.Commands.Util: filterExistingPaths :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Verbosity -> UseIndex -> ScanKnown -> [SubPath] -> IO ([SubPath], [SubPath])
+ Darcs.UI.Commands.Util: filterExistingPaths :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Verbosity -> UseIndex -> ScanKnown -> LookForMoves -> [SubPath] -> IO ([SubPath], [SubPath])
- Darcs.UI.Commands.Util: testTentativeAndMaybeExit :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> Verbosity -> TestChanges -> SetScriptsExecutable -> Bool -> String -> String -> Maybe String -> IO ()
+ Darcs.UI.Commands.Util: testTentativeAndMaybeExit :: Repository rt p wR wU wT -> Verbosity -> TestChanges -> SetScriptsExecutable -> Bool -> String -> String -> Maybe String -> IO ()
- Darcs.UI.Commands.Util.Tree: treeHas :: (Functor m, Monad m) => Tree m -> FilePath -> m Bool
+ Darcs.UI.Commands.Util.Tree: treeHas :: Monad m => Tree m -> FilePath -> m Bool
- Darcs.UI.Commands.Util.Tree: treeHasAnycase :: (Functor m, Monad m) => Tree m -> FilePath -> m Bool
+ Darcs.UI.Commands.Util.Tree: treeHasAnycase :: Monad m => Tree m -> FilePath -> m Bool
- Darcs.UI.Commands.Util.Tree: treeHasDir :: (Functor m, Monad m) => Tree m -> FilePath -> m Bool
+ Darcs.UI.Commands.Util.Tree: treeHasDir :: Monad m => Tree m -> FilePath -> m Bool
- Darcs.UI.Commands.Util.Tree: treeHasFile :: (Functor m, Monad m) => Tree m -> FilePath -> m Bool
+ Darcs.UI.Commands.Util.Tree: treeHasFile :: Monad m => Tree m -> FilePath -> m Bool
- Darcs.UI.External: execDocPipe :: RenderMode -> String -> [String] -> Doc -> IO Doc
+ Darcs.UI.External: execDocPipe :: String -> [String] -> Doc -> IO Doc
- Darcs.UI.External: execPipeIgnoreError :: RenderMode -> String -> [String] -> Doc -> IO Doc
+ Darcs.UI.External: execPipeIgnoreError :: String -> [String] -> Doc -> IO Doc
- Darcs.UI.External: pipeDoc :: RenderMode -> String -> [String] -> Doc -> IO ExitCode
+ Darcs.UI.External: pipeDoc :: String -> [String] -> Doc -> IO ExitCode
- Darcs.UI.External: pipeDocSSH :: Compression -> RenderMode -> SshFilePath -> [String] -> Doc -> IO ExitCode
+ Darcs.UI.External: pipeDocSSH :: Compression -> SshFilePath -> [String] -> Doc -> IO ExitCode
- Darcs.UI.External: viewDocWith :: Printers -> RenderMode -> Doc -> IO ()
+ Darcs.UI.External: viewDocWith :: Printers -> Doc -> IO ()
- Darcs.UI.Flags: applyAs :: Config -> Maybe String
+ Darcs.UI.Flags: applyAs :: PrimDarcsOption (Maybe String)
- Darcs.UI.Flags: cloneKind :: Config -> CloneKind
+ Darcs.UI.Flags: cloneKind :: PrimDarcsOption CloneKind
- Darcs.UI.Flags: diffAlgorithm :: Config -> DiffAlgorithm
+ Darcs.UI.Flags: diffAlgorithm :: PrimDarcsOption DiffAlgorithm
- Darcs.UI.Flags: dryRun :: Config -> DryRun
+ Darcs.UI.Flags: dryRun :: PrimDarcsOption DryRun
- Darcs.UI.Flags: editDescription :: Config -> Bool
+ Darcs.UI.Flags: editDescription :: PrimDarcsOption Bool
- Darcs.UI.Flags: externalMerge :: Config -> ExternalMerge
+ Darcs.UI.Flags: externalMerge :: PrimDarcsOption ExternalMerge
- Darcs.UI.Flags: hasXmlOutput :: Config -> XmlOutput
+ Darcs.UI.Flags: hasXmlOutput :: Config -> Bool
- Darcs.UI.Flags: leaveTestDir :: Config -> LeaveTestDir
+ Darcs.UI.Flags: leaveTestDir :: PrimDarcsOption LeaveTestDir
- Darcs.UI.Flags: maxCount :: Config -> Maybe Int
+ Darcs.UI.Flags: maxCount :: PrimDarcsOption (Maybe Int)
- Darcs.UI.Flags: minimize :: Config -> Bool
+ Darcs.UI.Flags: minimize :: PrimDarcsOption Bool
- Darcs.UI.Flags: patchFormat :: Config -> PatchFormat
+ Darcs.UI.Flags: patchFormat :: PrimDarcsOption PatchFormat
- Darcs.UI.Flags: remoteRepos :: Config -> RemoteRepos
+ Darcs.UI.Flags: remoteRepos :: PrimDarcsOption RemoteRepos
- Darcs.UI.Flags: reorder :: Config -> Reorder
+ Darcs.UI.Flags: reorder :: PrimDarcsOption Reorder
- Darcs.UI.Flags: runTest :: Config -> RunTest
+ Darcs.UI.Flags: runTest :: PrimDarcsOption RunTest
- Darcs.UI.Flags: selectDeps :: Config -> SelectDeps
+ Darcs.UI.Flags: selectDeps :: PrimDarcsOption SelectDeps
- Darcs.UI.Flags: setScriptsExecutable :: Config -> SetScriptsExecutable
+ Darcs.UI.Flags: setScriptsExecutable :: PrimDarcsOption SetScriptsExecutable
- Darcs.UI.Flags: siblings :: Config -> [AbsolutePath]
+ Darcs.UI.Flags: siblings :: PrimDarcsOption [AbsolutePath]
- Darcs.UI.Flags: testChanges :: Config -> TestChanges
+ Darcs.UI.Flags: testChanges :: PrimDarcsOption TestChanges
- Darcs.UI.Flags: umask :: Config -> UMask
+ Darcs.UI.Flags: umask :: PrimDarcsOption UMask
- Darcs.UI.Flags: useCache :: Config -> UseCache
+ Darcs.UI.Flags: useCache :: PrimDarcsOption UseCache
- Darcs.UI.Flags: useIndex :: Config -> UseIndex
+ Darcs.UI.Flags: useIndex :: PrimDarcsOption UseIndex
- Darcs.UI.Flags: usePacks :: Config -> Bool
+ Darcs.UI.Flags: usePacks :: PrimDarcsOption Bool
- Darcs.UI.Flags: verbosity :: Config -> Verbosity
+ Darcs.UI.Flags: verbosity :: PrimDarcsOption Verbosity
- Darcs.UI.Flags: withWorkingDir :: Config -> WithWorkingDir
+ Darcs.UI.Flags: withWorkingDir :: PrimDarcsOption WithWorkingDir
- Darcs.UI.Flags: workRepo :: Config -> WorkRepo
+ Darcs.UI.Flags: workRepo :: PrimDarcsOption WorkRepo
- Darcs.UI.Options.All: ExternalDiff :: Maybe String -> [String] -> ExternalDiff
+ Darcs.UI.Options.All: ExternalDiff :: Maybe String -> [String] -> Bool -> ExternalDiff
- Darcs.UI.Options.All: hooks :: DarcsOption a (Maybe String -> Bool -> Maybe String -> Bool -> a)
+ Darcs.UI.Options.All: hooks :: DarcsOption a (HooksConfig -> a)
- Darcs.UI.Options.All: notInRemote :: PrimDarcsOption [Maybe String]
+ Darcs.UI.Options.All: notInRemote :: PrimDarcsOption [NotInRemote]
- Darcs.UI.Options.All: postHook :: DarcsOption a (Maybe String -> Bool -> a)
+ Darcs.UI.Options.All: postHook :: DarcsOption a (HookConfig -> a)
- Darcs.UI.Options.All: preHook :: DarcsOption a (Maybe String -> Bool -> a)
+ Darcs.UI.Options.All: preHook :: DarcsOption a (HookConfig -> a)
- Darcs.UI.Options.All: summary :: PrimDarcsOption (Maybe Summary)
+ Darcs.UI.Options.All: summary :: PrimDarcsOption Summary
- Darcs.UI.Options.Flags: MaxCount :: Int -> DarcsFlag
+ Darcs.UI.Options.Flags: MaxCount :: String -> DarcsFlag
- Darcs.UI.PatchHeader: getLog :: forall prim wX wY. (Patchy prim, PrimPatch prim) => Maybe String -> Bool -> Logfile -> Maybe AskLongComment -> Maybe (String, [String]) -> FL prim wX wY -> IO (String, [String], Maybe String)
+ Darcs.UI.PatchHeader: getLog :: forall prim wX wY. PrimPatch prim => Maybe String -> Bool -> Logfile -> Maybe AskLongComment -> Maybe (String, [String]) -> FL prim wX wY -> IO (String, [String], Maybe String)
- Darcs.UI.PrintPatch: contextualPrintPatch :: (ShowPatch p, ApplyState p ~ Tree) => Tree IO -> p wX wY -> IO ()
+ Darcs.UI.PrintPatch: contextualPrintPatch :: (ShowContextPatch p, ApplyState p ~ Tree) => Tree IO -> p wX wY -> IO ()
- Darcs.UI.PrintPatch: printFriendly :: (ShowPatch p, ApplyState p ~ Tree) => Maybe (Tree IO) -> Verbosity -> Summary -> WithContext -> p wX wY -> IO ()
+ Darcs.UI.PrintPatch: printFriendly :: (ShowPatch p, ShowContextPatch p, ApplyState p ~ Tree) => Maybe (Tree IO) -> Verbosity -> Summary -> WithContext -> p wX wY -> IO ()
- Darcs.UI.SelectChanges: askAboutDepends :: forall rt p wR wU wT wY. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> FL (PrimOf p) wT wY -> PatchSelectionOptions -> [PatchInfo] -> IO [PatchInfo]
+ Darcs.UI.SelectChanges: askAboutDepends :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> FL (PrimOf p) wT wY -> PatchSelectionOptions -> [PatchInfo] -> IO [PatchInfo]
- Darcs.UI.SelectChanges: backAll :: forall p wX wY. Patchy p => InteractiveSelectionM p wX wY ()
+ Darcs.UI.SelectChanges: backAll :: InteractiveSelectionM p wX wY ()
- Darcs.UI.SelectChanges: backOne :: forall p wX wY. Patchy p => InteractiveSelectionM p wX wY ()
+ Darcs.UI.SelectChanges: backOne :: InteractiveSelectionM p wX wY ()
- Darcs.UI.SelectChanges: currentFile :: forall p wX wY. (Patchy p, PatchInspect p) => InteractiveSelectionM p wX wY (Maybe FilePath)
+ Darcs.UI.SelectChanges: currentFile :: (PatchInspect p) => InteractiveSelectionM p wX wY (Maybe FilePath)
- Darcs.UI.SelectChanges: currentPatch :: forall p wX wY. Patchy p => InteractiveSelectionM p wX wY (Maybe (Sealed2 (LabelledPatch p)))
+ Darcs.UI.SelectChanges: currentPatch :: InteractiveSelectionM p wX wY (Maybe (Sealed2 (LabelledPatch p)))
- Darcs.UI.SelectChanges: decide :: forall p wX wY wT wU. Patchy p => Bool -> LabelledPatch p wT wU -> InteractiveSelectionM p wX wY ()
+ Darcs.UI.SelectChanges: decide :: Commute p => Bool -> LabelledPatch p wT wU -> InteractiveSelectionM p wX wY ()
- Darcs.UI.SelectChanges: decideWholeFile :: forall p wX wY. (Patchy p, PatchInspect p) => FilePath -> Bool -> InteractiveSelectionM p wX wY ()
+ Darcs.UI.SelectChanges: decideWholeFile :: (Commute p, PatchInspect p) => FilePath -> Bool -> InteractiveSelectionM p wX wY ()
- Darcs.UI.SelectChanges: printSummary :: forall p wX wY. ShowPatch p => p wX wY -> IO ()
+ Darcs.UI.SelectChanges: printSummary :: ShowPatch p => p wX wY -> IO ()
- Darcs.UI.SelectChanges: prompt :: (Patchy p, ShowPatch p) => InteractiveSelectionM p wX wY String
+ Darcs.UI.SelectChanges: prompt :: (ShowPatch p) => InteractiveSelectionM p wX wY String
- Darcs.UI.SelectChanges: promptUser :: forall p wX wY. (Patchy p, ShowPatch p) => Bool -> Char -> InteractiveSelectionM p wX wY Char
+ Darcs.UI.SelectChanges: promptUser :: (ShowPatch p) => Bool -> Char -> InteractiveSelectionM p wX wY Char
- Darcs.UI.SelectChanges: runSelection :: forall p wX wY. (Patchy p, PatchInspect p, ShowPatch p, ApplyState p ~ Tree) => FL p wX wY -> PatchSelectionContext p -> IO ((FL p :> FL p) wX wY)
+ Darcs.UI.SelectChanges: runSelection :: forall p wX wY. (Invert p, Commute p, Apply p, PatchInspect p, ShowPatch p, ShowContextPatch p, ApplyState p ~ Tree) => FL p wX wY -> PatchSelectionContext p -> IO ((FL p :> FL p) wX wY)
- Darcs.UI.SelectChanges: selectionContextPrim :: PrimPatch prim => WhichChanges -> String -> PatchSelectionOptions -> Maybe (Splitter prim) -> Maybe [FilePath] -> Maybe (Tree IO) -> PatchSelectionContext prim
+ Darcs.UI.SelectChanges: selectionContextPrim :: WhichChanges -> String -> PatchSelectionOptions -> Maybe (Splitter prim) -> Maybe [FilePath] -> Maybe (Tree IO) -> PatchSelectionContext prim
- Darcs.UI.SelectChanges: showCur :: forall p wX wY. (Patchy p, ShowPatch p, ApplyState p ~ Tree) => InteractiveSelectionM p wX wY ()
+ Darcs.UI.SelectChanges: showCur :: (Invert p, ShowPatch p, ShowContextPatch p, ApplyState p ~ Tree) => InteractiveSelectionM p wX wY ()
- Darcs.UI.SelectChanges: skipMundane :: (Patchy p, ShowPatch p) => InteractiveSelectionM p wX wY ()
+ Darcs.UI.SelectChanges: skipMundane :: (Commute p, ShowPatch p) => InteractiveSelectionM p wX wY ()
- Darcs.UI.SelectChanges: skipOne :: forall p wX wY. Patchy p => InteractiveSelectionM p wX wY ()
+ Darcs.UI.SelectChanges: skipOne :: InteractiveSelectionM p wX wY ()
- Darcs.UI.SelectChanges: viewChanges :: (Patchy p, ShowPatch p, ApplyState p ~ Tree) => PatchSelectionOptions -> [Sealed2 p] -> IO ()
+ Darcs.UI.SelectChanges: viewChanges :: (ShowPatch p, ShowContextPatch p, ApplyState p ~ Tree) => PatchSelectionOptions -> [Sealed2 p] -> IO ()
- Darcs.UI.SelectChanges: withSelectedPatchFromRepo :: forall rt p wR wU wT. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => String -> Repository rt p wR wU wT -> PatchSelectionOptions -> (forall wA. (FL (PatchInfoAnd rt p) :> PatchInfoAnd rt p) wA wR -> IO ()) -> IO ()
+ Darcs.UI.SelectChanges: withSelectedPatchFromRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => String -> Repository rt p wR wU wT -> PatchSelectionOptions -> (forall wA. (FL (PatchInfoAnd rt p) :> PatchInfoAnd rt p) wA wR -> IO ()) -> IO ()
- Darcs.Util.Lock: appendBinFile :: FilePathLike p => p -> String -> IO ()
+ Darcs.Util.Lock: appendBinFile :: FilePathLike p => p -> ByteString -> IO ()
- Darcs.Util.Lock: readBinFile :: FilePathLike p => p -> IO String
+ Darcs.Util.Lock: readBinFile :: FilePathLike p => p -> IO ByteString
- Darcs.Util.Lock: withDelayedDir :: String -> (AbsolutePath -> IO a) -> IO a
+ Darcs.Util.Lock: withDelayedDir :: FilePath -> (AbsolutePath -> IO a) -> IO a
- Darcs.Util.Lock: withNamedTemp :: String -> (String -> IO a) -> IO a
+ Darcs.Util.Lock: withNamedTemp :: FilePath -> (FilePath -> IO a) -> IO a
- Darcs.Util.Lock: withOpenTemp :: ((Handle, String) -> IO a) -> IO a
+ Darcs.Util.Lock: withOpenTemp :: ((Handle, FilePath) -> IO a) -> IO a
- Darcs.Util.Lock: withPermDir :: String -> (AbsolutePath -> IO a) -> IO a
+ Darcs.Util.Lock: withPermDir :: FilePath -> (AbsolutePath -> IO a) -> IO a
- Darcs.Util.Lock: withStdoutTemp :: (String -> IO a) -> IO a
+ Darcs.Util.Lock: withStdoutTemp :: (FilePath -> IO a) -> IO a
- Darcs.Util.Lock: withTemp :: (String -> IO a) -> IO a
+ Darcs.Util.Lock: withTemp :: (FilePath -> IO a) -> IO a
- Darcs.Util.Lock: withTempDir :: String -> (AbsolutePath -> IO a) -> IO a
+ Darcs.Util.Lock: withTempDir :: FilePath -> (AbsolutePath -> IO a) -> IO a
- Darcs.Util.Lock: writeBinFile :: FilePathLike p => p -> String -> IO ()
+ Darcs.Util.Lock: writeBinFile :: FilePathLike p => p -> ByteString -> IO ()
- Darcs.Util.Printer: (<>) :: Monoid m => m -> m -> m
+ Darcs.Util.Printer: (<>) :: Semigroup a => a -> a -> a
- Darcs.Util.Printer: hPutDoc :: RenderMode -> Handle -> Doc -> IO ()
+ Darcs.Util.Printer: hPutDoc :: Handle -> Doc -> IO ()
- Darcs.Util.Printer: hPutDocCompr :: RenderMode -> Handle -> Doc -> IO ()
+ Darcs.Util.Printer: hPutDocCompr :: Handle -> Doc -> IO ()
- Darcs.Util.Printer: hPutDocLn :: RenderMode -> Handle -> Doc -> IO ()
+ Darcs.Util.Printer: hPutDocLn :: Handle -> Doc -> IO ()
- Darcs.Util.Printer: hPutDocLnWith :: Printers -> RenderMode -> Handle -> Doc -> IO ()
+ Darcs.Util.Printer: hPutDocLnWith :: Printers -> Handle -> Doc -> IO ()
- Darcs.Util.Printer: hPutDocWith :: Printers -> RenderMode -> Handle -> Doc -> IO ()
+ Darcs.Util.Printer: hPutDocWith :: Printers -> Handle -> Doc -> IO ()
- Darcs.Util.Printer: renderPS :: RenderMode -> Doc -> ByteString
+ Darcs.Util.Printer: renderPS :: Doc -> ByteString
- Darcs.Util.Printer: renderPSWith :: Printers' -> RenderMode -> Doc -> ByteString
+ Darcs.Util.Printer: renderPSWith :: Printers' -> Doc -> ByteString
- Darcs.Util.Printer: renderPSs :: RenderMode -> Doc -> [ByteString]
+ Darcs.Util.Printer: renderPSs :: Doc -> [ByteString]
- Darcs.Util.Printer: renderPSsWith :: Printers' -> RenderMode -> Doc -> [ByteString]
+ Darcs.Util.Printer: renderPSsWith :: Printers' -> Doc -> [ByteString]
- Darcs.Util.Printer: renderString :: RenderMode -> Doc -> String
+ Darcs.Util.Printer: renderString :: Doc -> String
- Darcs.Util.Printer: renderStringWith :: Printers' -> RenderMode -> Doc -> String
+ Darcs.Util.Printer: renderStringWith :: Printers' -> Doc -> String
- Darcs.Util.Printer.Color: showDoc :: RenderMode -> Doc -> String
+ Darcs.Util.Printer.Color: showDoc :: Doc -> String
- Darcs.Util.Tree: addMissingHashes :: (Monad m, Functor m) => (TreeItem m -> m Hash) -> Tree m -> m (Tree m)
+ Darcs.Util.Tree: addMissingHashes :: (Monad m) => (TreeItem m -> m Hash) -> Tree m -> m (Tree m)
- Darcs.Util.Tree: diffTrees :: forall m. (Functor m, Monad m) => Tree m -> Tree m -> m (Tree m, Tree m)
+ Darcs.Util.Tree: diffTrees :: forall m. (Monad m) => Tree m -> Tree m -> m (Tree m, Tree m)
- Darcs.Util.Tree: emptyTree :: (Monad m) => Tree m
+ Darcs.Util.Tree: emptyTree :: Tree m
- Darcs.Util.Tree: makeTree :: (Monad m) => [(Name, TreeItem m)] -> Tree m
+ Darcs.Util.Tree: makeTree :: [(Name, TreeItem m)] -> Tree m
- Darcs.Util.Tree: makeTreeWithHash :: (Monad m) => [(Name, TreeItem m)] -> Hash -> Tree m
+ Darcs.Util.Tree: makeTreeWithHash :: [(Name, TreeItem m)] -> Hash -> Tree m
- Darcs.Util.Tree: overlay :: (Functor m, Monad m) => Tree m -> Tree m -> Tree m
+ Darcs.Util.Tree: overlay :: (Monad m) => Tree m -> Tree m -> Tree m
- Darcs.Util.Tree: partiallyUpdateTree :: (Functor m, Monad m) => (TreeItem m -> m (TreeItem m)) -> (AnchoredPath -> TreeItem m -> Bool) -> Tree m -> m (Tree m)
+ Darcs.Util.Tree: partiallyUpdateTree :: (Monad m) => (TreeItem m -> m (TreeItem m)) -> (AnchoredPath -> TreeItem m -> Bool) -> Tree m -> m (Tree m)
- Darcs.Util.Tree: restrict :: (FilterTree t m, Monad n) => Tree n -> t m -> t m
+ Darcs.Util.Tree: restrict :: (FilterTree t m) => Tree n -> t m -> t m
- Darcs.Util.Tree: updateTree :: (Functor m, Monad m) => (TreeItem m -> m (TreeItem m)) -> Tree m -> m (Tree m)
+ Darcs.Util.Tree: updateTree :: (Monad m) => (TreeItem m -> m (TreeItem m)) -> Tree m -> m (Tree m)
- Darcs.Util.Tree.Hashed: darcsAddMissingHashes :: (Monad m, Functor m) => Tree m -> m (Tree m)
+ Darcs.Util.Tree.Hashed: darcsAddMissingHashes :: (Monad m) => Tree m -> m (Tree m)
- Darcs.Util.Tree.Hashed: darcsUpdateHashes :: (Monad m, Functor m) => Tree m -> m (Tree m)
+ Darcs.Util.Tree.Hashed: darcsUpdateHashes :: (Monad m) => Tree m -> m (Tree m)
- Darcs.Util.Tree.Monad: findFileM :: (Monad m, Functor m) => Tree m -> AnchoredPath -> m (Maybe (Blob m))
+ Darcs.Util.Tree.Monad: findFileM :: (Monad m) => Tree m -> AnchoredPath -> m (Maybe (Blob m))
- Darcs.Util.Tree.Monad: findM :: (Monad m, Functor m) => Tree m -> AnchoredPath -> m (Maybe (TreeItem m))
+ Darcs.Util.Tree.Monad: findM :: (Monad m) => Tree m -> AnchoredPath -> m (Maybe (TreeItem m))
- Darcs.Util.Tree.Monad: findTreeM :: (Monad m, Functor m) => Tree m -> AnchoredPath -> m (Maybe (Tree m))
+ Darcs.Util.Tree.Monad: findTreeM :: (Monad m) => Tree m -> AnchoredPath -> m (Maybe (Tree m))
- Darcs.Util.Tree.Monad: replaceItem :: (Functor m, Monad m) => AnchoredPath -> Maybe (TreeItem m) -> TreeMonad m ()
+ Darcs.Util.Tree.Monad: replaceItem :: (Monad m) => AnchoredPath -> Maybe (TreeItem m) -> TreeMonad m ()
- Darcs.Util.Tree.Monad: runTreeMonad :: (Functor m, Monad m) => TreeMonad m a -> TreeState m -> m (a, Tree m)
+ Darcs.Util.Tree.Monad: runTreeMonad :: (Monad m) => TreeMonad m a -> TreeState m -> m (a, Tree m)
- Darcs.Util.Tree.Monad: virtualTreeMonad :: (Functor m, Monad m) => TreeMonad m a -> Tree m -> m (a, Tree m)
+ Darcs.Util.Tree.Monad: virtualTreeMonad :: (Monad m) => TreeMonad m a -> Tree m -> m (a, Tree m)

Files

CHANGELOG view
@@ -1,3 +1,55 @@+Darcs 2.14.0, 4 April 2018++  * fix encoding business, make DARCS_DONT_ESCAPE_8BIT=1 default (Ben, Ganesh Sittampalam)+  * show explicit dependencies in `darcs log -s` (Gian Piero Carrubba)+  * improve bash/zsh completion (Ben, Gian Piero)+  * no longer print an error message when ctrlc'ing pager (Guillaume Hoffmann)+  * `darcs help markdown` mentions all files in `_darcs/prefs/` (Guillaume)+  * add patch index status to `show repo` command (Ben)+  * per-file conflict marking (Ben Franksen)+  * make it possible to use DARCS_SCP=rsync (Ben)+  * add --not-in-remote option to unrecord command (Ben)+  * plug memory leak and improve efficiency in annotate (Ben)+  * save unneeded FL/RL reverses in SelectChanges module (Ben)+  * optimize token replace code and --look-for-replaces (Ben)+  * no longer show conflicting files on `whatsnew -s`, will reintrodue this+    feature when it is done efficiently (Guillaume)+  * separate display and storage of patches (Ben)+  * support GHC 8.2 and GHC 8.4 (Ganesh)+  * many refactorings in Darcs.Repository modules and API (Ben, Guillaume)+  * no longer track build dependencies in Setup.hs, nor use+    alpha, beta, rc names (Guillaume)+  * refactor `pull --reorder-patches` (Ben)+  * refactor SelectChanges (Ben)+  * remove Patchy typeclass and redundant constaints where possible (Guillaume)+  * fix build with cabal new-build (Francesco Ariis)+  * unit and quickcheck tests for inventories (Ben)+  * throw out all access to bytestring internals from Darcs.Util.ByteString (Ben)+  * refactor, simplify, and document hunk application (Ben)+  * drop support of old cache location and SHA1-hashed repos (Guillaume)+  * rely on GHC's own stack traces for bug reporting (Guillaume)+  * fixed the following bugs:+    * fix mail encoding with '.' or '=' as last character (Timo von Holtz)+    * 2526: whatsnew -l --boring should list boring files (Ben)+    * 2208: replace detects existing force hunks in working (Ben)+    * 2512: author name is written to repository after multiple-choice+      prompt (Stephan-A. Posselt)+    * 2359: convert --export mishandles Unicode filenames (Ben)+    * 2545: prevent argument smuggling in SSH repository URLs (Gian Piero)+    * 2581: fix rebase pull --reorder (Ben)+    * 2575: fix unrevert with rebase (Ben)+    * 2579: allow darcs send to work even if no MTA is installed+    * 2555: include explicit dependencies in the output of `log -v` (Gian Piero)+    * 2569: decoding multibyte characters (Ben)+    * 2563: create remote repo in correct format in ssh tests (Ben)+    * 2565: create _darcs dir after searching for an existing one (Ben)+    * 2567: darcs whatsnew --unified (Ben)+    * 2566: avoid renaming across file systems (Ben)+    * 2564: delete wrong and irrelevant propConcatPS (Guillaume)+    * 2559: remove trailing empty lines in patch header edition (Guillaume)+    * 2536: mask out internal matchers in `show files` routing logic (Gian Piero)++ Darcs 2.12.5, 11 January 2017   * Bump some dependency upper bounds (Ganesh Sittampalam)
+ Setup.hs view
@@ -0,0 +1,241 @@+-- copyright (c) 2008 Duncan Coutts+-- portions copyright (c) 2008 David Roundy+-- portions copyright (c) 2007-2009 Judah Jacobson++import Distribution.Simple+         ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )+import Distribution.ModuleName( toFilePath )+import Distribution.PackageDescription+         ( PackageDescription(executables, testSuites), Executable(exeName)+         , emptyBuildInfo+         , TestSuite(testBuildInfo)+         , updatePackageDescription+         , cppOptions, ccOptions+         , library, libBuildInfo, otherModules )+import Distribution.Package+         ( packageVersion )+import Distribution.Version( Version )+import Distribution.Simple.LocalBuildInfo+         ( LocalBuildInfo(..), absoluteInstallDirs )+import Distribution.Simple.InstallDirs (mandir, CopyDest (NoCopyDest))+import Distribution.Simple.Setup+    (buildVerbosity, copyDest, copyVerbosity, fromFlag,+     haddockVerbosity, installVerbosity, sDistVerbosity, replVerbosity )+import Distribution.Simple.BuildPaths ( autogenModulesDir )+import Distribution.System+         ( OS(Windows), buildOS )+import Distribution.Simple.Utils+    (copyFiles, createDirectoryIfMissingVerbose, rawSystemStdout,+     rewriteFile )+import Distribution.Verbosity+         ( Verbosity )+import Distribution.Text+         ( display )+import Control.Monad ( unless, void )++import System.Directory+    ( doesDirectoryExist, doesFileExist )+import System.IO+    ( openFile, IOMode(..) )+import System.Process (runProcess)+import Data.List( isInfixOf, lines )+import System.FilePath       ( (</>) )+import Foreign.Marshal.Utils ( with )+import Foreign.Storable      ( peek )+import Foreign.Ptr           ( castPtr )+import Data.Monoid           ( mappend )+import Data.Word             ( Word8, Word32 )++import qualified Control.Exception as Exception++catchAny :: IO a -> (Exception.SomeException -> IO a) -> IO a+catchAny f h = Exception.catch f (\e -> h (e :: Exception.SomeException))++main :: IO ()+main = defaultMainWithHooks $ simpleUserHooks {++  buildHook = \ pkg lbi hooks flags ->+              let verb = fromFlag $ buildVerbosity flags+               in commonBuildHook buildHook pkg lbi hooks verb >>= ($ flags),++  haddockHook = \ pkg lbi hooks flags ->+                let verb = fromFlag $ haddockVerbosity flags+                 in commonBuildHook haddockHook pkg lbi hooks verb >>= ($ flags) ,+  replHook = \pkg lbi hooks flags args ->+                let verb = fromFlag $ replVerbosity flags+                 in commonBuildHook replHook pkg lbi hooks verb >>= (\f -> f flags args) ,+  postBuild = \ _ _ _ lbi -> buildManpage lbi,+  postCopy = \ _ flags pkg lbi ->+             installManpage pkg lbi (fromFlag $ copyVerbosity flags) (fromFlag $ copyDest flags),+  postInst = \ _ flags pkg lbi ->+             installManpage pkg lbi (fromFlag $ installVerbosity flags) NoCopyDest,++  sDistHook = \ pkg lbi hooks flags -> do+    let pkgVer = packageVersion pkg+        verb = fromFlag $ sDistVerbosity flags+    x <- versionPatches verb pkgVer+    y <- context verb+    rewriteFile "release/distributed-version" $ show x+    rewriteFile "release/distributed-context" $ show y+    putStrLn "about to hand over"+    let pkg' = pkg { library = sanity (library pkg) }+        sanity (Just lib) = Just $ lib { libBuildInfo = sanity' $ libBuildInfo lib }+        sanity _ = error "eh"+        sanity' bi = bi { otherModules = [ m | m <- otherModules bi, toFilePath m /= "Version" ] }++    sDistHook simpleUserHooks pkg' lbi hooks flags+             ,+  postConf = \_ _ _ _ -> return () --- Usually this checked for external C+             --- dependencies, but we already have performed such+             --- check in the confHook+}++-- | For @./Setup build@ and @./Setup haddock@, do some unusual+-- things, then invoke the base behaviour ("simple hook").+commonBuildHook :: (UserHooks -> PackageDescription -> LocalBuildInfo -> t -> a)+                -> PackageDescription -> LocalBuildInfo -> t -> Verbosity -> IO a+commonBuildHook runHook pkg lbi hooks verbosity = do+  (version, state) <- determineVersion verbosity pkg++  -- Create our own context file.+  generateVersionModule verbosity lbi version state++  -- Add custom -DFOO[=BAR] flags to the cpp (for .hs) and cc (for .c)+  -- invocations, doing a dance to make the base hook aware of them.+  littleEndian <- testEndianness+  let args = ("-DPACKAGE_VERSION=" ++ show' version) :+             [arg | (arg, True) <-         -- include fst iff snd.+              [-- We have MAPI iff building on/for Windows.+               ("-DHAVE_MAPI", buildOS == Windows),+               ("-DLITTLEENDIAN", littleEndian),+               ("-DBIGENDIAN", not littleEndian)]]+      bi = emptyBuildInfo { cppOptions = args, ccOptions = args }+      hbi = (Just bi, [(exeName exe, bi) | exe <- executables pkg])+      pkg' = updatePackageDescription hbi pkg++      -- updatePackageDescription doesn't handle test suites so we+      -- need to do this manually+      updateTestSuiteBI bi' testSuite+          = testSuite { testBuildInfo = bi' `mappend` testBuildInfo testSuite }+      pkg'' = pkg' { testSuites = map (updateTestSuiteBI bi) (testSuites pkg') }++      lbi' = lbi { localPkgDescr = pkg'' }+  return $ runHook simpleUserHooks pkg'' lbi' hooks++  where+    show' :: String -> String   -- Petr was worried that we might+    show' = show                -- allow non-String arguments.+    testEndianness :: IO Bool+    testEndianness = with (1 :: Word32) $ \p -> do o <- peek $ castPtr p+                                                   return $ o == (1 :: Word8)++-- ---------------------------------------------------------------------+-- man page+-- ---------------------------------------------------------------------++buildManpage :: LocalBuildInfo -> IO ()+buildManpage lbi = do+  let darcs = buildDir lbi </> "darcs/darcs"+      manpage = buildDir lbi </> "darcs/darcs.1"+  manpageHandle <- openFile manpage WriteMode+  void $ runProcess darcs ["help","manpage"]+             Nothing Nothing Nothing (Just manpageHandle) Nothing++installManpage :: PackageDescription -> LocalBuildInfo+                  -> Verbosity -> CopyDest -> IO ()+installManpage pkg lbi verbosity copy =+    copyFiles verbosity+              (mandir (absoluteInstallDirs pkg lbi copy) </> "man1")+              [(buildDir lbi </> "darcs", "darcs.1")]++-- ---------------------------------------------------------------------+-- version module+-- ---------------------------------------------------------------------++determineVersion :: Verbosity -> PackageDescription -> IO (String, String)+determineVersion verbosity pkg = do+  let darcsVersion  =  packageVersion pkg+  numPatches <- versionPatches verbosity darcsVersion+  return (display darcsVersion, versionStateString numPatches)++  where+    versionStateString :: Maybe Int -> String+    versionStateString Nothing  = "unknown"+    versionStateString (Just 0) = "release"+    versionStateString (Just 1) = "+ 1 patch"+    versionStateString (Just n) = "+ " ++ show n ++ " patches"++versionPatches :: Verbosity -> Version -> IO (Maybe Int)+versionPatches verbosity darcsVersion = do+  numPatchesDarcs <- do+      out <- rawSystemStdout verbosity "darcs"+               ["log", "-a", "--from-tag", display darcsVersion, "--count"]+      case reads out of+        ((n,_):_) -> return $ Just ((n :: Int) - 1)+        _         -> return Nothing+    `catchAny` \_ -> return Nothing++  numPatchesDist <- parseFile versionFile+  return $ case (numPatchesDarcs, numPatchesDist) of+             (Just x, _) -> Just x+             (Nothing, Just x) -> Just x+             (Nothing, Nothing) -> Nothing++ where+  versionFile = "release/distributed-version"++generateVersionModule :: Verbosity -> LocalBuildInfo+                      -> String -> String -> IO ()+generateVersionModule verbosity lbi version state = do+  let dir = autogenModulesDir lbi+  createDirectoryIfMissingVerbose verbosity True dir+  ctx <- context verbosity+  hash <- weakhash verbosity+  rewriteFile (dir </> "Version.hs") $ unlines+    ["module Version where"+    ,"version, weakhash, context :: String"+    ,"version = \"" ++ version ++ " (" ++ state ++ ")\""+    ,"weakhash = " ++ case hash of+                        Just x -> show x+                        Nothing -> show "not available"+    ,"context = " ++ case ctx of+                       Just x -> show x+                       Nothing -> show "context not available"+    ]++weakhash :: Verbosity -> IO (Maybe String)+weakhash verbosity = do+  inrepo <- doesDirectoryExist "_darcs"+  unless inrepo $ fail "Not a repository."+  out <- rawSystemStdout verbosity "darcs" ["show", "repo"]+  let line = filter ("Weak Hash:" `isInfixOf`) $ lines out+  return $ case (length line) of+                0 -> Nothing+                _ -> Just $ last $ words $ head line+ `catchAny` \_ -> return Nothing++context :: Verbosity -> IO (Maybe String)+context verbosity = do+  contextDarcs <- do+      inrepo <- doesDirectoryExist "_darcs"+      unless inrepo $ fail "Not a repository."+      out <- rawSystemStdout verbosity "darcs" ["log", "-a", "--context"]+      return $ Just out+   `catchAny` \_ -> return Nothing++  contextDist <- parseFile contextFile+  return $ case (contextDarcs, contextDist) of+             (Just x, _) -> Just x+             (Nothing, Just x) -> Just x+             (Nothing, Nothing) -> Nothing+ where contextFile = "release/distributed-context"++parseFile :: (Read a) => String -> IO (Maybe a)+parseFile f = do+  exist <- doesFileExist f+  if exist then do+             content <- readFile f -- ^ ratify readFile: we don't care here.+             case reads content of+               ((s,_):_) -> return s+               _         -> return Nothing+             else return Nothing
− Setup.lhs
@@ -1,382 +0,0 @@-\begin{code}-{-# LANGUAGE TemplateHaskell #-}--- copyright (c) 2008 Duncan Coutts--- portions copyright (c) 2008 David Roundy--- portions copyright (c) 2007-2009 Judah Jacobson--import qualified Distribution.InstalledPackageInfo as Installed-import Distribution.Simple-         ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )-import Distribution.Simple.Configure-         ( checkForeignDeps )-import Distribution.ModuleName( toFilePath )-import Distribution.PackageDescription-         ( PackageDescription(executables, testSuites), Executable(buildInfo, exeName)-         , BuildInfo(customFieldsBI), emptyBuildInfo-         , TestSuite(testBuildInfo)-         , FlagName(FlagName)-         , updatePackageDescription-         , cppOptions, ccOptions, ldOptions-         , library, libBuildInfo, otherModules-         , extraLibs, extraLibDirs, includeDirs )-import Distribution.Package-         ( packageVersion, packageName, PackageName(..), Package )-import Distribution.Version-         ( Version(Version, versionBranch) )-import Data.Version( showVersion )-import Distribution.Simple.LocalBuildInfo-         ( LocalBuildInfo(..), absoluteInstallDirs, externalPackageDeps )-import Distribution.Simple.InstallDirs (mandir, CopyDest (NoCopyDest))-import Distribution.Simple.PackageIndex ( topologicalOrder )-import Distribution.Simple.Program ( gccProgram, rawSystemProgramStdoutConf )-import Distribution.Simple.Setup-    (buildVerbosity, copyDest, copyVerbosity, fromFlag,-     haddockVerbosity, installVerbosity, sDistVerbosity,-     configVerbosity, ConfigFlags, configConfigurationsFlags)-import qualified Distribution.Simple.Setup as DSS -- to get replVerbosity in Cabal > 1.18-import Distribution.Simple.BuildPaths-         ( autogenModulesDir, exeExtension )-import Distribution.System-         ( OS(Windows), buildOS )-import Distribution.Simple.Utils-    (copyFiles, createDirectoryIfMissingVerbose, rawSystemStdout,-     rewriteFile, withTempFile, cabalVersion)-import Distribution.Verbosity-         ( Verbosity )-import Distribution.Text-         ( display )-import Control.Monad ( zipWithM_, when, unless, filterM )-import Control.Exception ( bracket, handle, IOException )--import Language.Haskell.TH ( mkName, newName, recUpdE, varE, appE, lamE, varP )--import System.Directory-    (copyFile, createDirectory, createDirectoryIfMissing,-     doesDirectoryExist, doesFileExist,-     getCurrentDirectory, getDirectoryContents,-     removeDirectoryRecursive, removeFile, setCurrentDirectory,-     getTemporaryDirectory-    )-import System.Exit ( ExitCode(ExitSuccess) )-import System.IO-    ( openFile, IOMode (..), stdout-    , hPutStr, hFlush, hClose-    )-import System.Process (runProcess)-import System.IO.Error ( isDoesNotExistError )-import Data.List( isPrefixOf, isSuffixOf, sort )-import System.Process( rawSystem )-import System.FilePath       ( (</>), (<.>), splitDirectories, isAbsolute )-import Foreign.Marshal.Utils ( with )-import Foreign.Storable      ( peek )-import Foreign.Ptr           ( castPtr )-import Data.Monoid           ( mappend )-import Data.Word             ( Word8, Word32 )--import qualified Control.Exception as Exception--catchAny f h = Exception.catch f (\e -> h (e :: Exception.SomeException))--{- Template Haskell hackery for replHook while we want to support Cabal < 1.18 -}-replVerbosity =-  $(if cabalVersion >= Version [1,18,0] []-        then varE (mkName "DSS.replVerbosity")-        else [| error "This shouldn't be called" |]-   )--replHookBody replHookSel =-  \pkg lbi hooks flags args ->-    let verb = fromFlag $ replVerbosity flags-    in commonBuildHook replHookSel pkg lbi hooks verb >>= (\f -> f flags args)--addReplHook =-  $(if cabalVersion >= Version [1,18,0] []-        then-            do hooks <- newName "hooks"-               let replHook = mkName "replHook"-               app <- appE (varE (mkName "replHookBody")) (varE replHook)-               lamE [varP hooks] (recUpdE (varE hooks) [return (replHook, app)])-        else [| \hooks -> hooks |]-   )-{- End of Template Haskell hackery -}--main :: IO ()-main = defaultMainWithHooks $ addReplHook $ simpleUserHooks {--  buildHook = \ pkg lbi hooks flags ->-              let verb = fromFlag $ buildVerbosity flags-               in commonBuildHook buildHook pkg lbi hooks verb >>= ($ flags),--  haddockHook = \ pkg lbi hooks flags ->-                let verb = fromFlag $ haddockVerbosity flags-                 in commonBuildHook haddockHook pkg lbi hooks verb >>= ($ flags) ,-{--  -- this is the actual replHook code we want-  replHook = \pkg lbi hooks flags args ->-                let verb = fromFlag $ replVerbosity flags-                 in commonBuildHook replHook pkg lbi hooks verb >>= (\f -> f flags args) ,--}-  postBuild = \ _ _ _ lbi -> buildManpage lbi,-  postCopy = \ _ flags pkg lbi ->-             installManpage pkg lbi (fromFlag $ copyVerbosity flags) (fromFlag $ copyDest flags),-  postInst = \ _ flags pkg lbi ->-             installManpage pkg lbi (fromFlag $ installVerbosity flags) NoCopyDest,--  sDistHook = \ pkg lbi hooks flags -> do-    let pkgVer = packageVersion pkg-        verb = fromFlag $ sDistVerbosity flags-    x <- versionPatches verb pkgVer-    y <- context verb pkgVer-    rewriteFile "release/distributed-version" $ show x-    rewriteFile "release/distributed-context" $ show y-    putStrLn "about to hand over"-    let pkg' = pkg { library = sanity (library pkg) }-        sanity (Just lib) = Just $ lib { libBuildInfo = sanity' $ libBuildInfo lib }-        sanity _ = error "eh"-        sanity' bi = bi { otherModules = [ m | m <- otherModules bi, toFilePath m /= "Version" ] }--    sDistHook simpleUserHooks pkg' lbi hooks flags-             ,-  confHook =-    if buildOS == Windows-      then confHook simpleUserHooks-      else-        \genericDescript flags -> do-          lbi <- confHook simpleUserHooks genericDescript flags-          let pkgDescr = localPkgDescr lbi-          let verb = fromFlag (configVerbosity flags)-          checkForeignDeps pkgDescr lbi verb-          let lib = maybe (error "darcs library was not configured - did it end up unbuildable?") id-                          (library pkgDescr)-          let bi = libBuildInfo lib-          bi' <- maybeSetLibiconv flags bi lbi-          return lbi {localPkgDescr = pkgDescr {-                                  library = Just lib {-                                      libBuildInfo = bi'}}}-              ,-  postConf = \_ _ _ _ -> return () --- Usually this checked for external C-             --- dependencies, but we already have performed such-             --- check in the confHook-}---- | For @./Setup build@ and @./Setup haddock@, do some unusual--- things, then invoke the base behaviour ("simple hook").-commonBuildHook :: (UserHooks -> PackageDescription -> LocalBuildInfo -> t -> a)-                -> PackageDescription -> LocalBuildInfo -> t -> Verbosity -> IO a-commonBuildHook runHook pkg lbi hooks verbosity = do-  (version, state) <- determineVersion verbosity pkg--  -- Create our own context file.-  generateVersionModule verbosity pkg lbi version state--  -- Add custom -DFOO[=BAR] flags to the cpp (for .hs) and cc (for .c)-  -- invocations, doing a dance to make the base hook aware of them.-  littleEndian <- testEndianness-  let args = ("-DPACKAGE_VERSION=" ++ show' version) :-             [arg | (arg, True) <-         -- include fst iff snd.-              [-- We have MAPI iff building on/for Windows.-               ("-DHAVE_MAPI", buildOS == Windows),-               ("-DLITTLEENDIAN", littleEndian),-               ("-DBIGENDIAN", not littleEndian)]]-      bi = emptyBuildInfo { cppOptions = args, ccOptions = args }-      hbi = (Just bi, [(exeName exe, bi) | exe <- executables pkg])-      pkg' = updatePackageDescription hbi pkg--      -- updatePackageDescription doesn't handle test suites so we-      -- need to do this manually-      updateTestSuiteBI bi testSuite-          = testSuite { testBuildInfo = bi `mappend` testBuildInfo testSuite }-      pkg'' = pkg' { testSuites = map (updateTestSuiteBI bi) (testSuites pkg') }--      lbi' = lbi { localPkgDescr = pkg'' }-  return $ runHook simpleUserHooks pkg'' lbi' hooks--  where-    customFields = map fst . customFieldsBI . buildInfo $ darcsExe-    darcsExe = head [e | e <- executables pkg, exeName e == "darcs"]-    show' :: String -> String   -- Petr was worried that we might-    show' = show                -- allow non-String arguments.-    testEndianness :: IO Bool-    testEndianness = with (1 :: Word32) $ \p -> do o <- peek $ castPtr p-                                                   return $ o == (1 :: Word8)---- ------------------------------------------------------------------------ man page--- -----------------------------------------------------------------------buildManpage :: LocalBuildInfo -> IO ()-buildManpage lbi = do-  let darcs = buildDir lbi </> "darcs/darcs"-      manpage = buildDir lbi </> "darcs/darcs.1"-  manpageHandle <- openFile manpage WriteMode-  runProcess darcs ["help","manpage"]-             Nothing Nothing Nothing (Just manpageHandle) Nothing-  return ()--installManpage :: PackageDescription -> LocalBuildInfo-                  -> Verbosity -> CopyDest -> IO ()-installManpage pkg lbi verbosity copy =-    copyFiles verbosity-              (mandir (absoluteInstallDirs pkg lbi copy) </> "man1")-              [(buildDir lbi </> "darcs", "darcs.1")]---- ------------------------------------------------------------------------ version module--- -----------------------------------------------------------------------determineVersion :: Verbosity -> PackageDescription -> IO (String, String)-determineVersion verbosity pkg = do-  let darcsVersion  =  packageVersion pkg-  numPatches <- versionPatches verbosity darcsVersion-  return (display darcsVersion, versionStateString numPatches darcsVersion)--  where-    versionStateString :: Maybe Int -> Version -> String-    versionStateString Nothing  _ = "unknown"-    versionStateString (Just 0) v = case versionBranch v of-                         x | 97 `elem` x -> "alpha " ++ show (after 97 x)-                           | 98 `elem` x -> "beta " ++ show (after 98 x)-                           | 99 `elem` x  ->-                               "release candidate " ++ show (after 99 x)-                         _ -> "release"-    versionStateString (Just 1) _ = "+ 1 patch"-    versionStateString (Just n) _ = "+ " ++ show n ++ " patches"-    after w (x:r) | w == x = head r-                  | otherwise = after w r-    after _ [] = undefined--versionPatches :: Verbosity -> Version -> IO (Maybe Int)-versionPatches verbosity darcsVersion = do-  numPatchesDarcs <- do-      out <- rawSystemStdout verbosity "darcs"-               ["log", "-a", "--from-tag", display darcsVersion, "--count"]-      case reads (out) of-        ((n,_):_) -> return $ Just ((n :: Int) - 1)-        _         -> return Nothing-    `catchAny` \_ -> return Nothing--  numPatchesDist <- parseFile versionFile-  return $ case (numPatchesDarcs, numPatchesDist) of-             (Just x, _) -> Just x-             (Nothing, Just x) -> Just x-             (Nothing, Nothing) -> Nothing-- where-  versionFile = "release/distributed-version"--generateVersionModule :: Verbosity -> PackageDescription -> LocalBuildInfo-                      -> String -> String -> IO ()-generateVersionModule verbosity pkg lbi version state = do-  let dir = autogenModulesDir lbi-  createDirectoryIfMissingVerbose verbosity True dir-  ctx <- context verbosity (packageVersion pkg)-  rewriteFile (dir </> "Version.hs") $ unlines-    ["module Version where"-    ,"builddeps, version, context :: String"-    ,"version = \"" ++ version ++ " (" ++ state ++ ")\""-    ,"builddeps = " ++ show ( formatdeps (externalPackageDeps lbi))-    ,"context = " ++ case ctx of-                       Just x -> show x-                       Nothing -> show "context not available"-    ]-  where formatdeps = unlines . map (formatone . snd)-        formatone p = case packageName p of PackageName n -> n ++ "-" ++ showVersion (packageVersion p)--context :: Verbosity -> Version -> IO (Maybe String)-context verbosity version = do-  contextDarcs <- do-      inrepo <- doesDirectoryExist "_darcs"-      unless inrepo $ fail "Not a repository."-      out <- rawSystemStdout verbosity "darcs" ["log", "-a", "--context"]-      return $ Just out-   `catchAny` \_ -> return Nothing--  contextDist <- parseFile contextFile-  return $ case (contextDarcs, contextDist) of-             (Just x, _) -> Just x-             (Nothing, Just x) -> Just x-             (Nothing, Nothing) -> Nothing- where contextFile = "release/distributed-context"--parseFile :: (Read a) => String -> IO (Maybe a)-parseFile f = do-  exist <- doesFileExist f-  if exist then do-             content <- readFile f -- ^ ratify readFile: we don't care here.-             case reads content of-               ((s,_):_) -> return s-               _         -> return Nothing-             else return Nothing---- Test whether compiling a c program that links against libiconv needs -liconv.-maybeSetLibiconv :: ConfigFlags -> BuildInfo -> LocalBuildInfo -> IO BuildInfo-maybeSetLibiconv flags bi lbi = do-    let biWithIconv = addIconv bi-    let verb = fromFlag (configVerbosity flags)-    if hasFlagSet flags (FlagName "libiconv")-        then do-            putStrLn "Using -liconv."-            return biWithIconv-        else do-    putStr "checking whether to use -liconv... "-    hFlush stdout-    worksWithout <- tryCompile iconv_prog bi lbi verb-    if worksWithout-        then do-            putStrLn "not needed."-            return bi-        else do-    worksWith <- tryCompile iconv_prog biWithIconv lbi verb-    if worksWith-        then do-            putStrLn "using -liconv."-            return biWithIconv-        else error "Unable to link against the iconv library."--hasFlagSet :: ConfigFlags -> FlagName -> Bool-hasFlagSet cflags flag = Just True == lookup flag (configConfigurationsFlags cflags)--tryCompile :: String -> BuildInfo -> LocalBuildInfo -> Verbosity -> IO Bool-tryCompile program bi lbi verb = handle processExit $ handle processException $ do-    tempDir <- getTemporaryDirectory-    withTempFile tempDir ".c" $ \fname cH ->-      withTempFile tempDir "" $ \execName oH -> do-        hPutStr cH program-        hClose cH-        hClose oH-        -- TODO take verbosity from the args.-        rawSystemProgramStdoutConf verb gccProgram (withPrograms lbi)-                        (fname : "-o" : execName : args)-        return True-  where-    processException :: IOException -> IO Bool-    processException e = return False-    processExit = return . (==ExitSuccess)-    -- Mimicing Distribution.Simple.Configure-    deps = topologicalOrder (installedPkgs lbi)-    args = concat-                  [ ccOptions bi-                  , cppOptions bi-                  , ldOptions bi-                  -- --extra-include-dirs and --extra-lib-dirs are included-                  -- in the below fields.-                  -- Also sometimes a dependency like rts points to a nonstandard-                  -- include/lib directory where iconv can be found. -                  , map ("-I" ++) (includeDirs bi ++ concatMap Installed.includeDirs deps)-                  , map ("-L" ++) (extraLibDirs bi ++ concatMap Installed.libraryDirs deps)-                  , map ("-l" ++) (extraLibs bi)-                  ]--addIconv :: BuildInfo -> BuildInfo-addIconv bi = bi {extraLibs = "iconv" : extraLibs bi}--iconv_prog :: String-iconv_prog = unlines -    [ "#include <iconv.h>"-    , "int main(void) {"-    , "    iconv_t t = iconv_open(\"UTF-8\", \"UTF-8\");"-    , "    return 0;"-    , "}"-    ]--\end{code}
contrib/_darcs.zsh view
@@ -1,35 +1,38 @@ #compdef darcs-## Darcs completion snippet for zsh.+## Darcs completion for zsh. ##+## Originally derived from a version by ## Copyright (C) 2009  Nicolas Pouillard-##-## 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 of the License, 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. +local -a darcs_options darcs_non_options darcs_arguments+ if (($CURRENT == 2)); then-  # We're completing the first word after "darcs" -- the command.-  _wanted command expl 'darcs command' \-    compadd -- $( darcs --commands )+  compadd -- $(darcs --commands) else+  case "${words[2]}"; in+    get|clone)+      _urls+      ;;+  esac   case "${words[$CURRENT]}"; in-    # If it looks like an URL...-    ht*|ft*)-        _arguments '*:URL:_urls'-        ;;-    # If it looks like an explicit path...     /*|./*|\~*|../*)-        _arguments '*:file:_files'-        ;;-    # Otherwise, let's ask darcs for all possible options+      _files+      ;;+    -*)+      # advanced zsh (array) parameter expansion fu:+      # - ${(f)...} means split into array elements at line endings+      #   instead of white space+      # - ${arr:#pat} drops elements matching pat from arr, whereas+      #   ${(M)arr:#pat} drops non-matching elements+      # - ${arr/pat/repl} replaces pat with repl for all elements of arr+      darcs_arguments=(${(f)"$(words[$CURRENT]=--list-options && $words 2>/dev/null)"})+      darcs_options=(${${(M)darcs_arguments:#-*}/;/:})+      _describe '' darcs_options+      ;;     *)-        _arguments '*: :($(words[$CURRENT]="--list-options" && $words))'+      darcs_arguments=(${(f)"$(words[$CURRENT]=--list-options && $words 2>/dev/null)"})+      darcs_non_options=(${darcs_arguments:#-*})+      _multi_parts -i -S ' ' / darcs_non_options       ;;   esac fi
contrib/darcs_completion view
@@ -16,9 +16,27 @@         return 0     fi -    local IFS=$'\n' # So that the following "command-output to array" operation splits only at newlines, not at each space, tab or newline.-    COMPREPLY=( $( darcs ${COMP_WORDS[1]} --list-option | command grep "^${cur//./\\.}") )+    # Store the whole command line substituting the (possibly empty)+    # to-be-completed word with '--list-options'.+    local -a words=("${COMP_WORDS[@]}")+    words[$COMP_CWORD]="--list-options" +    # Options are processed from left to right, so avoid to display the help+    # page when trying to complete a command line that includes '--help'. It+    # could be tricked by things like '--repodir --hell', but, come on... you+    # don't deserve a working completion if you name a directory '--hell'.+    for w in "${words[@]}"; do+        case "$w" in+            (--he*) return 0;;+        esac+    done++    # So that the following "command-output to array" operation splits only at+    # newlines, not at each space, tab or newline.+    local IFS=$'\n'+    COMPREPLY=( $( "${words[@]}" 2>/dev/null |\+        command grep "^${cur//./\\.}" | cut -d ';' -f 1) )+ 	# Then, we adapt the resulting strings to be reusable by bash. If we don't 	# do this, in the case where we have two repositories named 	# ~/space in there-0.1 and ~/space in there-0.2, the first completion will@@ -42,11 +60,8 @@     local colonprefixes=${cur%"${cur##*:}"}     while [ $((--i)) -ge 0 ]; do       COMPREPLY[$i]=`printf %q "${COMPREPLY[$i]}"`-       COMPREPLY[$i]=${COMPREPLY[$i]#"$colonprefixes"}      done     return 0- } complete -F _darcs -o default darcs-
darcs.cabal view
@@ -1,6 +1,6 @@ Name:           darcs-version:        2.12.5-License:        GPL+version:        2.14.0+License:        GPL-2 License-file:   COPYING Author:         David Roundy <droundy@darcs.net>, <darcs-devel@darcs.net> Maintainer:     <darcs-devel@darcs.net>@@ -33,7 +33,7 @@ Homepage:       http://darcs.net/  Build-Type:     Custom-Cabal-Version:  >= 1.16+Cabal-Version:  >= 1.24  extra-source-files:   -- C headers@@ -107,16 +107,16 @@   manual:      True   description: Build with warnings-as-errors --- Note that the Setup script checks whether -liconv is necessary.  This flag--- lets us override that decision.  When it is True, we use -liconv.  When it--- is False, we run tests to decide.-flag libiconv-    Description: Explicitly link against the libiconv library.-    Default: False+-- ----------------------------------------------------------------------+-- setup+-- ---------------------------------------------------------------------- -flag network-uri-  description: Get Network.URI from the network-uri package-  default: True+custom-setup+    setup-depends: base      >= 4.9 && < 4.12,+                   Cabal     >= 1.24,+                   process   >= 1.2.3.0 && < 1.7,+                   filepath  >= 1.4.1 && < 1.5.0.0,+                   directory >= 1.2.6.2 && < 1.4  -- ---------------------------------------------------------------------- -- darcs library@@ -158,10 +158,7 @@                       Darcs.Patch.MonadProgress                       Darcs.Patch.Named                       Darcs.Patch.Named.Wrapped-                      Darcs.Patch.OldDate                       Darcs.Patch.PatchInfoAnd-                      Darcs.Patch.Patchy-                      Darcs.Patch.Patchy.Instances                       Darcs.Patch.Permutations                       Darcs.Patch.Prim                       Darcs.Patch.Prim.Class@@ -208,11 +205,13 @@                       Darcs.Patch.V1.Apply                       Darcs.Patch.V1.Commute                       Darcs.Patch.V1.Core+                      Darcs.Patch.V1.Prim                       Darcs.Patch.V1.Read                       Darcs.Patch.V1.Show                       Darcs.Patch.V1.Viewing                       Darcs.Patch.V2                       Darcs.Patch.V2.Non+                      Darcs.Patch.V2.Prim                       Darcs.Patch.V2.RepoPatch                       Darcs.Patch.Witnesses.Eq                       Darcs.Patch.Witnesses.Ordered@@ -225,18 +224,19 @@                       Darcs.Repository.ApplyPatches                       Darcs.Repository.Cache                       Darcs.Repository.Clone+                      Darcs.Repository.Create                       Darcs.Repository.PatchIndex                       Darcs.Repository.Diff                       Darcs.Repository.Flags                       Darcs.Repository.Format                       Darcs.Repository.HashedIO-                      Darcs.Repository.HashedRepo-                      Darcs.Repository.Internal+                      Darcs.Repository.Hashed+                      Darcs.Repository.Inventory+                      Darcs.Repository.Identify                       Darcs.Repository.Job                       Darcs.Repository.Merge                       Darcs.Repository.InternalTypes                       Darcs.Repository.Match-                      Darcs.Repository.Motd                       Darcs.Repository.Old                       Darcs.Repository.Packs                       Darcs.Repository.Pending@@ -246,6 +246,7 @@                       Darcs.Repository.Resolution                       Darcs.Repository.State                       Darcs.Repository.Test+                      Darcs.Repository.Working                       Darcs.UI.ApplyPatches                       Darcs.UI.Commands                       Darcs.UI.Commands.Add@@ -277,7 +278,6 @@                       Darcs.UI.Commands.SetPref                       Darcs.UI.Commands.Show                       Darcs.UI.Commands.ShowAuthors-                      Darcs.UI.Commands.ShowBug                       Darcs.UI.Commands.ShowContents                       Darcs.UI.Commands.ShowDependencies                       Darcs.UI.Commands.ShowFiles@@ -293,6 +293,7 @@                       Darcs.UI.Commands.Unrecord                       Darcs.UI.Commands.Unrevert                       Darcs.UI.Commands.WhatsNew+                      Darcs.UI.Completion                       Darcs.UI.Email                       Darcs.UI.External                       Darcs.UI.Defaults@@ -311,14 +312,10 @@                       Darcs.UI.SelectChanges                       Darcs.UI.TheCommands                       Darcs.UI.Usage-                      Darcs.UI.Message.Send                       Darcs.Util.AtExit-                      Darcs.Util.Bug                       Darcs.Util.ByteString                       Darcs.Util.CommandLine                       Darcs.Util.Compat-                      Darcs.Util.Crypt.SHA1-                      Darcs.Util.Crypt.SHA256                       Darcs.Util.DateMatcher                       Darcs.Util.DateTime                       Darcs.Util.Diff@@ -327,8 +324,8 @@                       Darcs.Util.Download                       Darcs.Util.Download.Request                       Darcs.Util.Download.HTTP+                      Darcs.Util.Encoding                       Darcs.Util.English-                      Darcs.Util.Environment                       Darcs.Util.Exception                       Darcs.Util.Exec                       Darcs.Util.External@@ -354,14 +351,11 @@                       Darcs.Util.Tree.Plain                       Darcs.Util.URL                       Darcs.Util.Workaround-                      Bundled.Posix      other-modules:    Version                       Darcs.Util.Download.Curl-                      Darcs.Util.Encoding      c-sources:        src/atomic_create.c-                      src/fpstring.c                       src/maybe_relink.c                       src/umask.c                       src/system_encoding.c@@ -382,98 +376,81 @@                       System.Posix.IO       cpp-options:    -DWIN32       c-sources:      src/win32/send_email.c-      build-depends:  Win32 >= 2.3 && < 2.4+      build-depends:  Win32 >= 2.3.1 && < 2.4     else-      other-modules:  Darcs.Util.Encoding.IConv-      c-sources:      src/h_iconv.c-      build-depends:  unix >= 2.6.0.1 && < 2.8+      build-depends:  unix >= 2.7.1.0 && < 2.8 -    build-depends:   base >= 4.8 && < 4.10,-                     binary >= 0.5 && < 0.9,-                     containers >= 0.5 && < 0.6,-                     regex-compat-tdfa >= 0.95.1 && < 0.96,-                     regex-applicative >= 0.2 && < 0.4,-                     mtl          >= 2.1.2 && < 2.3,-                     transformers >= 0.3 && < 0.4.0.0 || > 0.4.0.0 && < 0.6,-                     -- for the Control.Monad.Error -> Control.Monad.Except-                     -- transition-                     transformers-compat >= 0.4 && < 0.6,-                     parsec       >= 3.1 && < 3.2,-                     fgl          >= 5.5.0.1 && < 5.6,-                     graphviz     >= 2999.17.0.1 && < 2999.19,-                     html         >= 1.0.1.2 && < 1.1,-                     filepath     >= 1.3.0.1 && < 1.5.0.0,-                     haskeline    >= 0.6.3 && < 0.8,-                     cryptohash   >= 0.4 && < 0.12,-                     base16-bytestring >= 0.1 && < 0.2,-                     utf8-string  >= 0.3.6 && < 1.1,-                     vector       >= 0.10.0.1 && < 0.13,-                     tar          >= 0.4 && < 0.6,-                     data-ordlist == 0.4.*,-                     attoparsec   >= 0.11 && < 0.14,-                     zip-archive  >= 0.2.3 && < 0.4,-                     async        >= 2.0.1.4 && < 2.2,-                     sandi        >= 0.4 && < 0.5,-                     unix-compat  >= 0.1.2 && < 0.5,-                     bytestring   >= 0.10.0.2 && < 0.11,-                     old-time     >= 1.1 && < 1.2,-                     time         >= 1.5 && < 1.8,-    -- release notes of GHC 7.10.2 recommends to use text >= 1.2.1.3:-    -- https://mail.haskell.org/pipermail/haskell/2015-July/024641.html-                     text         >= 1.2.1.3 && < 1.3,-                     directory    >= 1.2.0.1 && < 1.4.0.0,-                     process      >= 1.1.0.2 && < 1.5.0.0,-                     array        >= 0.4.0.1 && < 0.6,-                     random       >= 1.0.1.1 && < 1.2,-                     hashable     >= 1.1.2.5 && < 1.3,-                     mmap         >= 0.5 && < 0.6,-                     zlib         >= 0.5.4.1 && < 0.7.0.0+    build-depends:    base              >= 4.9 && < 4.12,+                      stm               >= 2.1 && < 2.5,+                      binary            >= 0.5 && < 0.9,+                      containers        >= 0.5.6.2 && < 0.6,+                      regex-compat-tdfa >= 0.95.1 && < 0.96,+                      regex-applicative >= 0.2 && < 0.4,+                      mtl               >= 2.2.1 && < 2.3,+                      transformers      >= 0.4.2.0 && < 0.6,+                      parsec            >= 3.1.9 && < 3.2,+                      fgl               >= 5.5.2.3 && < 5.6,+                      graphviz          >= 2999.18.1 && < 2999.20,+                      html              >= 1.0.1.2 && < 1.1,+                      filepath          >= 1.4.1 && < 1.5.0.0,+                      haskeline         >= 0.7.2 && < 0.8,+                      cryptohash        >= 0.11 && < 0.12,+                      base16-bytestring >= 0.1 && < 0.2,+                      utf8-string       >= 1 && < 1.1,+                      vector            >= 0.11 && < 0.13,+                      tar               >= 0.5 && < 0.6,+                      data-ordlist      == 0.4.*,+                      attoparsec        >= 0.13.0.1 && < 0.14,+                      zip-archive       >= 0.3 && < 0.4,+                      async             >= 2.0.2 && < 2.2,+                      sandi             >= 0.4 && < 0.5,+                      unix-compat       >= 0.4.2 && < 0.6,+                      bytestring        >= 0.10.6 && < 0.11,+                      old-time          >= 1.1.0.3 && < 1.2,+                      time              >= 1.5.0.1 && < 1.9,+                      text              >= 1.2.1.3 && < 1.3,+                      directory         >= 1.2.6.2 && < 1.4,+                      temporary         >= 1.2.0.4 && < 1.3,+                      process           >= 1.2.3.0 && < 1.7,+                      array             >= 0.5.1.0 && < 0.6,+                      random            >= 1.1 && < 1.2,+                      hashable          >= 1.2.3.3 && < 1.3,+                      mmap              >= 0.5.9 && < 0.6,+                      zlib              >= 0.6.1.2 && < 0.7.0.0,+                      network-uri       == 2.6.*,+                      network           == 2.6.*,+                      HTTP              >= 4000.2.20 && < 4000.4      if flag(optimize)-      ghc-options:      -O2+      ghc-options:    -O2     else-      ghc-options:      -O0+      ghc-options:    -O0      if flag(warn-as-error)-      ghc-options:      -Werror--    -- Note: "if true" works around a cabal bug with order of flag composition-    -- fixed in Cabal 1.18 https://github.com/haskell/cabal/commit/cf0cf077ab6836584fc3bf51d867e63824811d4d-    if true-      ghc-options:      -Wall -funbox-strict-fields -fwarn-tabs -fno-warn-dodgy-imports+      ghc-options:    -Werror -    if impl(ghc>=8.0)-      -- This warning is new in GHC 8.0 and is not easy to fix-      ghc-options:      -fno-warn-redundant-constraints+    ghc-options:      -Wall -funbox-strict-fields -fwarn-tabs      if flag(curl)-      cpp-options:       -DHAVE_CURL-      c-sources:         src/hscurl.c-      cc-options:        -DHAVE_CURL+      cpp-options:          -DHAVE_CURL+      c-sources:            src/hscurl.c+      cc-options:           -DHAVE_CURL       if flag(pkgconfig)-        pkgconfig-depends: libcurl+        pkgconfig-depends:  libcurl       else-        extra-libraries:   curl-        includes:          curl/curl.h--    if flag(network-uri)-      build-depends:    network-uri == 2.6.*, network == 2.6.*-    else-      build-depends:    network >= 2.4.1.2 && < 2.6--    build-depends:    HTTP    >= 4000.2.8 && < 4000.4+        extra-libraries:    curl+        includes:           curl/curl.h      -- The terminfo package cannot be built on Windows.     if flag(terminfo) && !os(windows)-      build-depends:    terminfo >= 0.3 && < 0.5-      cpp-options:      -DHAVE_TERMINFO+      build-depends:  terminfo >= 0.4.0.2 && < 0.5+      cpp-options:    -DHAVE_TERMINFO -    -- if true to work around cabal bug with flag ordering-    if true-      default-extensions:+    default-extensions:         BangPatterns         PatternGuards-        GADTs+        GADTSyntax+        ExistentialQuantification         TypeOperators         FlexibleContexts         FlexibleInstances@@ -501,50 +478,29 @@   hs-source-dirs:   darcs    if flag(optimize)-    ghc-options:      -O2+    ghc-options:    -O2   else-    ghc-options:      -O0+    ghc-options:    -O0    if flag(warn-as-error)-    ghc-options:      -Werror+    ghc-options:    -Werror -  -- Note: "if true" works around a cabal bug with order of flag composition-  if true-    ghc-options:      -Wall -funbox-strict-fields -fwarn-tabs -fno-warn-dodgy-imports+  ghc-options:      -Wall -funbox-strict-fields -fwarn-tabs    if flag(threaded)     ghc-options:    -threaded    if flag(static)-    ghc-options: -static -optl-static -optl-pthread+    ghc-options:    -static -optl-static -optl-pthread    if flag(rts)-    ghc-options: -rtsopts--  if impl(ghc>=8.0)-    -- This warning is new in GHC 8.0 and is not easy to fix-    ghc-options:      -fno-warn-redundant-constraints+    ghc-options:    -rtsopts    -- see http://bugs.darcs.net/issue1037   cc-options:       -D_REENTRANT -  build-depends:   darcs,-                   base              >= 4.8 && < 4.10--  -- if true to work around cabal bug with flag ordering-  if true-    default-extensions:-      BangPatterns-      PatternGuards-      GADTs-      TypeOperators-      FlexibleContexts-      FlexibleInstances-      ScopedTypeVariables-      KindSignatures-      RankNTypes-      TypeFamilies-      NoMonoLocalBinds+  build-depends:    darcs,+                    base              >= 4.9 && < 4.12  -- ---------------------------------------------------------------------- -- unit test driver@@ -558,32 +514,33 @@   hs-source-dirs:   harness    if os(windows)-    cpp-options:   -DWIN32-    build-depends:  Win32 >= 2.2 && < 2.4+    cpp-options:    -DWIN32+    build-depends:  Win32 >= 2.3.1 && < 2.4 -  build-depends:   darcs,-                   base         >= 4.8 && < 4.10,-                   array        >= 0.4.0.1 && < 0.6,-                   bytestring   >= 0.10.0.2 && < 0.11,-                   cmdargs      >= 0.10 && < 0.11,-                   containers   >= 0.1 && < 0.6,-                   filepath     >= 1.3.0.1 && < 1.5.0.0,-                   mtl          >= 2.1 && < 2.3,-                   shelly       >= 1.6.2 && < 1.7,-                   split        >= 0.2.2 && < 0.3,-                   text         >= 1.2.1.3 && < 1.3,-                   directory    >= 1.2.0.1 && < 1.4.0.0,-                   FindBin      >= 0.0 && < 0.1,-                   QuickCheck   >= 2.6 && < 2.10,-                   HUnit        >= 1.2.5.2 && < 1.6,-                   test-framework             >= 0.4.0 && < 0.9,-                   test-framework-hunit       >= 0.2.2 && < 0.4,-                   test-framework-quickcheck2 >= 0.3 && < 0.4,-                   zip-archive  >= 0.2.3 && < 0.4+  build-depends:    darcs,+                    base         >= 4.9 && < 4.12,+                    array        >= 0.5.1.0 && < 0.6,+                    bytestring   >= 0.10.6 && < 0.11,+                    cmdargs      >= 0.10.10 && < 0.11,+                    containers   >= 0.5.6.2 && < 0.6,+                    filepath     >= 1.4.1 && < 1.5.0.0,+                    mtl          >= 2.2.1 && < 2.3,+                    shelly       >= 1.6.8 && < 1.7,+                    split        >= 0.2.2 && < 0.3,+                    text         >= 1.2.1.3 && < 1.3,+                    directory    >= 1.2.6.2 && < 1.4,+                    FindBin      >= 0.0.5 && < 0.1,+                    QuickCheck   >= 2.8.2 && < 2.11,+                    HUnit        >= 1.3 && < 1.7,+                    test-framework             >= 0.8.1.1 && < 0.9,+                    test-framework-hunit       >= 0.3.0.2 && < 0.4,+                    test-framework-quickcheck2 >= 0.3.0.3 && < 0.4,+                    zip-archive  >= 0.3 && < 0.4    -- list all unit test modules not exported by libdarcs; otherwise Cabal won't   -- include them in the tarball   other-modules:    Darcs.Test.Email+                    Darcs.Test.HashedStorage                     Darcs.Test.Patch.Check                     Darcs.Test.Patch.Examples.Set1                     Darcs.Test.Patch.Examples.Set2Unwitnessed@@ -609,37 +566,34 @@                     Darcs.Test.Patch.WithState                     Darcs.Test.Patch                     Darcs.Test.Misc+                    Darcs.Test.Misc.CommandLine+                    Darcs.Test.Misc.Encoding+                    Darcs.Test.Repository.Inventory                     Darcs.Test.Util.TestResult                     Darcs.Test.Util.QuickCheck-                    Storage.Hashed.Test    if flag(optimize)-    ghc-options:      -O2+    ghc-options:    -O2   else-    ghc-options:      -O0+    ghc-options:    -O0    if flag(warn-as-error)-    ghc-options:      -Werror+    ghc-options:    -Werror -  -- Note: "if true" works around a cabal bug with order of flag composition-  if true-    ghc-options:      -Wall -funbox-strict-fields -fwarn-tabs+  ghc-options:      -Wall -funbox-strict-fields -fwarn-tabs -fno-warn-orphans    if flag(threaded)     ghc-options:    -threaded    if flag(rts)-    ghc-options: -rtsopts+    ghc-options:    -rtsopts    -- see http://bugs.darcs.net/issue1037   cc-options:       -D_REENTRANT -  -- if true to work around cabal bug with flag ordering-  if true-    default-extensions:-      BangPatterns-      PatternGuards-      GADTs+  default-extensions:+      GADTSyntax+      ExistentialQuantification       TypeOperators       FlexibleContexts       FlexibleInstances@@ -650,5 +604,3 @@       RankNTypes       TypeFamilies       NoMonoLocalBinds--
darcs/darcs.hs view
@@ -27,27 +27,24 @@  module Main ( main ) where +import Prelude ()+import Darcs.Prelude+ import Control.Exception ( AssertionFailed(..), handle )-import Control.Monad ( forM_ )-import System.IO ( stdin, stdout, stderr, hSetBinaryMode ) import System.Exit ( exitWith, ExitCode(..) ) import System.Environment ( getArgs )  import Darcs.UI.RunCommand ( runTheCommand ) import Darcs.UI.Commands.Help ( helpCmd, listAvailableCommands, printVersion,                              commandControlList )-import Darcs.UI.Flags ( DarcsFlag(Verbose) ) import Darcs.Util.AtExit ( withAtexit, atexit ) import Darcs.Repository( reportBadSources ) import Darcs.Util.SignalHandler ( withSignalsHandled ) -import Darcs.Util.ByteString ( decodeString ) import Darcs.UI.External ( setDarcsEncodings ) import Darcs.Util.Exec ( ExecException(..) ) import Darcs.Util.Path ( getCurrentDirectory )-import Version ( version, context, builddeps )--#include "impossible.h"+import Version ( version, context, weakhash )  execExceptionHandler :: ExecException -> IO a execExceptionHandler (ExecException cmd args redirects reason) = do@@ -62,7 +59,7 @@ main = withAtexit . withSignalsHandled . handleExecFail . handleAssertFail $ do     atexit reportBadSources     setDarcsEncodings-    argv <- getArgs >>= mapM decodeString+    argv <- getArgs     here <- getCurrentDirectory     let runHelpCmd = helpCmd (here, here) [] []     -- Explicitly handle no-args and special "help" arguments.@@ -70,20 +67,17 @@         [] -> printVersion >> runHelpCmd         ["-h"] -> runHelpCmd         ["--help"] -> runHelpCmd-        ["--overview"] -> helpCmd (here, here) [Verbose] []         ["--commands"] -> listAvailableCommands         ["-v"] -> putStrLn version+        ["-V"] -> putStrLn version         ["--version"] -> putStrLn version         ["--exact-version"] -> printExactVersion-        _ -> do-            forM_ [stdout, stdin, stderr] $ \h -> hSetBinaryMode h True-            runTheCommand commandControlList (head argv) (tail argv)+        _ -> runTheCommand commandControlList (head argv) (tail argv)   where     handleExecFail = handle execExceptionHandler     handleAssertFail = handle $ \(AssertionFailed e) -> bug e     printExactVersion =  do-        putStrLn $ "darcs compiled on " ++ __DATE__ ++ ", at " ++ __TIME__+        putStrLn $ "darcs compiled on " ++ __DATE__ ++ ", at " ++ __TIME__ ++ "\n"+        putStrLn $ "Weak Hash: " ++ weakhash         putStrLn context-        putStrLn "Compiled with:\n"-        putStr builddeps 
harness/Darcs/Test/Email.hs view
@@ -21,15 +21,17 @@ -- These tests check whether the emails generated by darcs meet a few criteria. -- We check for line length and non-ASCII characters. We apparently do not have -- to check for CR-LF newlines because that's handled by sendmail.+ module Darcs.Test.Email ( testSuite ) where import Data.Char ( isPrint )-import qualified Data.ByteString as B ( length, unpack, null, head,+import qualified Data.ByteString as B ( length, unpack, null, head, pack,                                         cons, empty, foldr, ByteString )-import qualified Data.ByteString.Char8 as BC ( unpack )+import qualified Data.ByteString.Char8 as BC ( unlines ) import Test.Framework ( Test, testGroup ) import Test.Framework.Providers.QuickCheck2 ( testProperty )-import Darcs.Util.Printer ( text, renderPS, RenderMode(..) )-import Darcs.UI.Email ( makeEmail, readEmail, formatHeader )+import Test.QuickCheck ( Arbitrary(..) )+import Darcs.Util.Printer ( text, renderPS, packedString )+import Darcs.UI.Email ( makeEmail, readEmail, formatHeader, prop_qp_roundtrip )  testSuite :: Test testSuite = testGroup "Darcs.Email"@@ -38,16 +40,17 @@   , emailHeaderAsciiChars   , emailHeaderLinesStart   , emailHeaderNoEmptyLines+  , emailCodecRoundtrip   ]  -- | Checks that darcs can read the emails it generates emailParsing :: Test-emailParsing = testProperty "Checking that email can be parsed" $ \s ->-    unlines ("":s++["", ""]) ==-              BC.unpack (readEmail (renderPS Standard+emailParsing = testProperty "Checking that email can be parsed" $ \bs ->+    BC.unlines (B.empty:bs++[B.empty,B.empty]) ==+              readEmail (renderPS                     $ makeEmail "reponame" [] (Just (text "contents\n"))                                  Nothing-                                 (text $ unlines s) (Just "filename")))+                                 (packedString $ BC.unlines bs) (Just "filename"))  -- | Check that formatHeader never creates lines longer than 78 characters -- (excluding the carriage return and line feed)@@ -81,6 +84,13 @@       let headerLines = bsLines (formatHeader cleanField value)           cleanField  = cleanFieldString field           in all (not . B.null) headerLines --(not . B.null . B.filter (not . (`elem` [10, 32, 9]))) headerLines++instance Arbitrary B.ByteString where+  arbitrary = fmap B.pack arbitrary++emailCodecRoundtrip :: Test+emailCodecRoundtrip =+    testProperty "Checking that quoted printable en- then decoding is id" $ prop_qp_roundtrip  bsLines :: B.ByteString -> [B.ByteString] bsLines = finalizeFold . B.foldr splitAtLines (B.empty, [])
+ harness/Darcs/Test/HashedStorage.hs view
@@ -0,0 +1,501 @@+{-# LANGUAGE ScopedTypeVariables, FlexibleInstances #-}+module Darcs.Test.HashedStorage( tests ) where++import Prelude hiding ( filter, readFile, writeFile, lookup, (<$>) )+import qualified Prelude+import qualified Data.ByteString.Lazy.Char8 as BLC+import qualified Data.ByteString.Char8 as BC+import System.Directory( doesFileExist, removeFile, doesDirectoryExist )+import System.FilePath( (</>) )+import Control.Monad.Identity+import Control.Monad.Trans( lift )+import Control.Applicative( (<$>) )+import Codec.Archive.Zip( extractFilesFromArchive, toArchive )++import Data.Maybe+import Data.Word+import Data.List( sort, intercalate, intersperse )++import Darcs.Util.Path hiding ( setCurrentDirectory )+import Darcs.Util.Lock ( withTempDir )+import Darcs.Util.Tree hiding ( lookup )+import Darcs.Util.Index+import Darcs.Util.Tree.Hashed+import Darcs.Util.Hash+import Darcs.Util.Tree.Monad hiding ( tree, createDirectory )+import Darcs.Util.Tree.Plain++import System.Mem( performGC )++import qualified Data.Set as S++import Test.HUnit hiding ( path )+import Test.Framework( testGroup )+import qualified Test.Framework as TF ( Test )+import Test.QuickCheck++import Test.Framework.Providers.HUnit+import Test.Framework.Providers.QuickCheck2++------------------------+-- Test Data+--++blobs :: [(AnchoredPath, BLC.ByteString)]+blobs = [ (floatPath "foo_a", BLC.pack "a\n")+        , (floatPath "foo_dir/foo_a", BLC.pack "a\n")+        , (floatPath "foo_dir/foo_b", BLC.pack "b\n")+        , (floatPath "foo_dir/foo_subdir/foo_a", BLC.pack "a\n")+        , (floatPath "foo space/foo\nnewline", BLC.pack "newline\n")+        , (floatPath "foo space/foo\\backslash", BLC.pack "backslash\n")+        , (floatPath "foo space/foo_a", BLC.pack "a\n") ]++files :: [AnchoredPath]+files = map fst blobs++dirs :: [AnchoredPath]+dirs = [ floatPath "foo_dir"+       , floatPath "foo_dir/foo_subdir"+       , floatPath "foo space" ]++emptyStub :: TreeItem IO+emptyStub = Stub (return emptyTree) NoHash++testTree :: Tree IO+testTree =+    makeTree [ (makeName "foo", emptyStub)+             , (makeName "subtree", SubTree sub)+             , (makeName "substub", Stub getsub NoHash) ]+    where sub = makeTree [ (makeName "stub", emptyStub)+                         , (makeName "substub", Stub getsub2 NoHash)+                         , (makeName "x", SubTree emptyTree) ]+          getsub = return sub+          getsub2 = return $ makeTree [ (makeName "file", File emptyBlob)+                                      , (makeName "file2",+                                         File $ Blob (return $ BLC.pack "foo") NoHash) ]++equals_testdata :: Tree IO -> IO ()+equals_testdata t = sequence_ [+                     do isJust (findFile t p) @? show p ++ " in tree"+                        ours <- readBlob (fromJust $ findFile t p)+                        ours @?= stored+                     | (p, stored) <- blobs ] >>+                    sequence_ [ isJust (Prelude.lookup p blobs) @? show p ++ " extra in tree"+                                | (p, File _) <- list t ]++---------------------------+-- Test list+--++tests :: [TF.Test]+tests = [ testGroup "Darcs.Util.Hash" hash+        , testGroup "Darcs.Util.Tree" tree+        , testGroup "Darcs.Util.Index" index+        , testGroup "Darcs.Util.Tree.Monad" monad+        , testGroup "Hashed Storage" hashed ]++--------------------------+-- Tests+--++hashed :: [TF.Test]+hashed = [ testCase "plain has all files" have_files+         , testCase "pristine has all files" have_pristine_files+         , testCase "pristine has no extras" pristine_no_extra+         , testCase "pristine file contents match" pristine_contents+         , testCase "plain file contents match" plain_contents+         , testCase "writePlainTree works" write_plain ]+    where+      check_file t f = assertBool+                       ("path " ++ show f ++ " is missing in tree " ++ show t)+                       (isJust $ find t f)+      check_files = forM_ files . check_file++      pristine_no_extra = extractRepoAndRun $+       do+        t <- readDarcsPristine "." >>= expand+        forM_ (list t) $ \(path,_) -> assertBool (show path ++ " is extraneous in tree")+                                                 (path `elem` (dirs ++ files))+      have_files = extractRepoAndRun ( readPlainTree "." >>= expand >>= check_files )+      have_pristine_files = extractRepoAndRun ( readDarcsPristine "." >>= expand >>= check_files )++      pristine_contents = extractRepoAndRun $+       do+        t <- readDarcsPristine "." >>= expand+        equals_testdata t++      plain_contents = extractRepoAndRun $+       do+        t <- expand =<< filter nondarcs `fmap` readPlainTree "."+        equals_testdata t++      write_plain = extractRepoAndRun $+       do+        orig <- readDarcsPristine "." >>= expand+        writePlainTree orig "_darcs/plain"+        t <- expand =<< readPlainTree "_darcs/plain"+        equals_testdata t++index :: [TF.Test]+index = [ testCase "index versioning" check_index_versions+        , testCase "index listing" check_index+        , testCase "index content" check_index_content+        , testProperty "xlate32" prop_xlate32+        , testProperty "xlate64" prop_xlate64+        , testProperty "align bounded" prop_align_bounded+        , testProperty "align aligned" prop_align_aligned ]+    where pristine = readDarcsPristine "." >>= expand+          build_index =+            do x <- pristine+               exist <- doesFileExist "_darcs/index"+               performGC -- required in win32 to trigger file close+               when exist $ removeFile "_darcs/index"+               idx <- updateIndex =<< updateIndexFrom "_darcs/index" darcsTreeHash x+               return (x, idx)+          check_index = extractRepoAndRun $+            do (pris, idx) <- build_index+               (sort $ map fst $ list idx) @?= (sort $ map fst $ list pris)+          check_blob_pair p x y =+              do a <- readBlob x+                 b <- readBlob y+                 assertEqual ("content match on " ++ show p) a b+          check_index_content = extractRepoAndRun $+            do (_, idx) <- build_index+               plain <- readPlainTree "."+               x <- sequence $ zipCommonFiles check_blob_pair plain idx+               assertBool "files match" (length x > 0)+          check_index_versions = extractRepoAndRun $+            do performGC -- required in win32 to trigger file close+               Prelude.writeFile "_darcs/index" "nonsense index... do not crash!"+               valid <- indexFormatValid "_darcs/index"+               assertBool "index format invalid" $ not valid+          prop_xlate32 x = (xlate32 . xlate32) x == x where _types = x :: Word32+          prop_xlate64 x = (xlate64 . xlate64) x == x where _types = x :: Word64+          prop_align_bounded (bound, x) =+              bound > 0 && bound < 1024 && x >= 0 ==>+                    align bound x >= x && align bound x < x + bound+              where _types = (bound, x) :: (Int, Int)+          prop_align_aligned (bound, x) =+              bound > 0 && bound < 1024 && x >= 0 ==>+                    align bound x `rem` bound == 0+              where _types = (bound, x) :: (Int, Int)++tree :: [TF.Test]+tree = [ testCase "modifyTree" check_modify+       , testCase "complex modifyTree" check_modify_complex+       , testCase "modifyTree removal" check_modify_remove+       , testCase "expand" check_expand+       , testCase "expandPath" check_expand_path+       , testCase "expandPath of sub" check_expand_path_sub+       , testCase "diffTrees" check_diffTrees+       , testCase "diffTrees identical" check_diffTrees_ident+       , testProperty "expandPath" prop_expandPath+       , testProperty "shapeEq" prop_shape_eq+       , testProperty "expandedShapeEq" prop_expanded_shape_eq+       , testProperty "expand is identity" prop_expand_id+       , testProperty "filter True is identity" prop_filter_id+       , testProperty "filter False is empty" prop_filter_empty+       , testProperty "restrict both ways keeps shape" prop_restrict_shape_commutative+       , testProperty "restrict is a subtree of both" prop_restrict_subtree+       , testProperty "overlay keeps shape" prop_overlay_shape+       , testProperty "overlay is superset of over" prop_overlay_super ]+    where blob x = File $ Blob (return (BLC.pack x)) (sha256 $ BLC.pack x)+          name = makeName+          check_modify =+              let t = makeTree [(name "foo", blob "bar")]+                  modify = modifyTree t (floatPath "foo") (Just $ blob "bla")+               in do x <- readBlob $ fromJust $ findFile t (floatPath "foo")+                     y <- readBlob $ fromJust $ findFile modify (floatPath "foo")+                     assertEqual "old version" x (BLC.pack "bar")+                     assertEqual "new version" y (BLC.pack "bla")+                     assertBool "list has foo" $+                                isJust (Prelude.lookup (floatPath "foo") $ list modify)+                     length (list modify) @?= 1+          check_modify_complex =+              let t = makeTree [ (name "foo", blob "bar")+                               , (name "bar", SubTree t1) ]+                  t1 = makeTree [ (name "foo", blob "bar") ]+                  modify = modifyTree t (floatPath "bar/foo") (Just $ blob "bla")+               in do foo <- readBlob $ fromJust $ findFile t (floatPath "foo")+                     foo' <- readBlob $ fromJust $ findFile modify (floatPath "foo")+                     bar_foo <- readBlob $ fromJust $+                                findFile t (floatPath "bar/foo")+                     bar_foo' <- readBlob $ fromJust $+                                 findFile modify (floatPath "bar/foo")+                     assertEqual "old foo" foo (BLC.pack "bar")+                     assertEqual "old bar/foo" bar_foo (BLC.pack "bar")+                     assertEqual "new foo" foo' (BLC.pack "bar")+                     assertEqual "new bar/foo" bar_foo' (BLC.pack "bla")+                     assertBool "list has bar/foo" $+                                isJust (Prelude.lookup (floatPath "bar/foo") $ list modify)+                     assertBool "list has foo" $+                                isJust (Prelude.lookup (floatPath "foo") $ list modify)+                     length (list modify) @?= length (list t)+          check_modify_remove =+              let t1 = makeTree [(name "foo", blob "bar")]+                  t2 :: Tree Identity = makeTree [ (name "foo", blob "bar")+                                                 , (name "bar", SubTree t1) ]+                  modify1 = modifyTree t1 (floatPath "foo") Nothing+                  modify2 = modifyTree t2 (floatPath "bar") Nothing+                  file = findFile modify1 (floatPath "foo")+                  subtree = findTree modify2 (floatPath "bar")+               in do assertBool "file is gone" (isNothing file)+                     assertBool "subtree is gone" (isNothing subtree)++          no_stubs t = null [ () | (_, Stub _ _) <- list t ]+          path = floatPath "substub/substub/file"+          badpath = floatPath "substub/substub/foo"+          check_expand = do+            x <- expand testTree+            assertBool "no stubs in testTree" $ not (no_stubs testTree)+            assertBool "stubs in expanded tree" $ no_stubs x+            assertBool "path reachable" $ path `elem` (map fst $ list x)+            assertBool "badpath not reachable" $+                       badpath `notElem` (map fst $ list x)+          check_expand_path = do+            test_exp <- expand testTree+            t <- expandPath testTree path+            t' <- expandPath test_exp path+            t'' <- expandPath testTree $ floatPath "substub/x"+            assertBool "path not reachable in testTree" $ path `notElem` (map fst $ list testTree)+            assertBool "path reachable in t" $ path `elem` (map fst $ list t)+            assertBool "path reachable in t'" $ path `elem` (map fst $ list t')+            assertBool "path reachable in t (with findFile)" $+                       isJust $ findFile t path+            assertBool "path reachable in t' (with findFile)" $+                       isJust $ findFile t' path+            assertBool "path not reachable in t''" $ path `notElem` (map fst $ list t'')+            assertBool "badpath not reachable in t" $+                       badpath `notElem` (map fst $ list t)+            assertBool "badpath not reachable in t'" $+                       badpath `notElem` (map fst $ list t')++          check_expand_path_sub = do+            t <- expandPath testTree $ floatPath "substub"+            t' <- expandPath testTree $ floatPath "substub/stub"+            t'' <- expandPath testTree $ floatPath "subtree/stub"+            assertBool "leaf is not a Stub" $+                isNothing (findTree testTree $ floatPath "substub")+            assertBool "leaf is not a Stub" $ isJust (findTree t $ floatPath "substub")+            assertBool "leaf is not a Stub (2)" $ isJust (findTree t' $ floatPath "substub/stub")+            assertBool "leaf is not a Stub (3)" $ isJust (findTree t'' $ floatPath "subtree/stub")++          check_diffTrees = extractRepoAndRun $+                 do Prelude.writeFile "foo_dir/foo_a" "b\n"+                    working_plain <- filter nondarcs `fmap` readPlainTree "."+                    working <- updateIndex =<<+                                 updateIndexFrom "_darcs/index" darcsTreeHash working_plain+                    pristine <- readDarcsPristine "."+                    (working', pristine') <- diffTrees working pristine+                    let foo_work = findFile working' (floatPath "foo_dir/foo_a")+                        foo_pris = findFile pristine' (floatPath "foo_dir/foo_a")+                    working' `shapeEq` pristine'+                             @? show working' ++ " `shapeEq` " ++ show pristine'+                    assertBool "foo_dir/foo_a is in working'" $ isJust foo_work+                    assertBool "foo_dir/foo_a is in pristine'" $ isJust foo_pris+                    foo_work_c <- readBlob (fromJust foo_work)+                    foo_pris_c <- readBlob (fromJust foo_pris)+                    BLC.unpack foo_work_c @?= "b\n"+                    BLC.unpack foo_pris_c @?= "a\n"+                    assertEqual "working' tree is minimal" 2 (length $ list working')+                    assertEqual "pristine' tree is minimal" 2 (length $ list pristine')++          check_diffTrees_ident = do+            pristine <- readDarcsPristine "."+            (t1, t2) <- diffTrees pristine pristine+            assertBool "t1 is empty" $ null (list t1)+            assertBool "t2 is empty" $ null (list t2)++          prop_shape_eq x = no_stubs x ==> x `shapeEq` x+              where _types = x :: Tree Identity+          prop_expanded_shape_eq x = runIdentity $ expandedShapeEq x x+              where _types = x :: Tree Identity+          prop_expand_id x = no_stubs x ==> runIdentity (expand x) `shapeEq` x+              where _types = x :: Tree Identity+          prop_filter_id x = runIdentity $ expandedShapeEq x $ filter (\_ _ -> True) x+              where _types = x :: Tree Identity+          prop_filter_empty x = runIdentity $ expandedShapeEq emptyTree $ filter (\_ _ -> False) x+              where _types = x :: Tree Identity+          prop_restrict_shape_commutative (t1, t2) =+              no_stubs t1 && no_stubs t2 && not (restrict t1 t2 `shapeEq` emptyTree) ==>+                  restrict t1 t2 `shapeEq` restrict t2 t1+              where _types = (t1 :: Tree Identity, t2 :: Tree Identity)+          prop_restrict_subtree (t1, t2) =+              no_stubs t1 && not (restrict t1 t2 `shapeEq` emptyTree) ==>+                  let restricted = S.fromList (map fst $ list $ restrict t1 t2)+                      orig1 = S.fromList (map fst $ list t1)+                      orig2 = S.fromList (map fst $ list t2)+                   in and [restricted `S.isSubsetOf` orig1, restricted `S.isSubsetOf` orig2]+              where _types = (t1 :: Tree Identity, t2 :: Tree Identity)+          prop_overlay_shape (t1 :: Tree Identity, t2) =+              (Just LT == runIdentity (t2 `cmpExpandedShape` t1)) ==>+              runIdentity $ (t1 `overlay` t2) `expandedShapeEq` t1+          prop_overlay_super (t1 :: Tree Identity, t2) =+              (Just LT == runIdentity (t2 `cmpExpandedShape` t1)) && no_stubs t2 ==>+              Just EQ == (runIdentity $ restrict t2 (t1 `overlay` t2) `cmpTree` t2)+          prop_expandPath (TreeWithPath t p) =+              notStub $ find (runIdentity $ expandPath t p) p+            where notStub (Just (Stub _ _)) = False+                  notStub Nothing = error "Did not exist."+                  notStub _ = True++hash :: [TF.Test]+hash = [ testProperty "decodeBase16 . encodeBase16 == id" prop_base16 ]+    where prop_base16 x = (decodeBase16 . encodeBase16) x == x++monad :: [TF.Test]+monad = [ testCase "path expansion" check_virtual+        , testCase "rename" check_rename ]+    where check_virtual = virtualTreeMonad run testTree >> return ()+              where run = do file <- readFile (floatPath "substub/substub/file")+                             file2 <- readFile (floatPath "substub/substub/file2")+                             lift $ BLC.unpack file @?= ""+                             lift $ BLC.unpack file2 @?= "foo"+          check_rename = do (_, t) <- virtualTreeMonad run testTree+                            t' <- darcsAddMissingHashes =<< expand t+                            forM_ [ (p, i) | (p, i) <- list t' ] $ \(p,i) ->+                               assertBool ("have hash: " ++ show p) $ itemHash i /= NoHash+              where run = do rename (floatPath "substub/substub/file") (floatPath "substub/file2")++----------------------------------+-- Arbitrary instances+--++instance Arbitrary BLC.ByteString where+    arbitrary = BLC.pack `fmap` arbitrary++instance Arbitrary Hash where+    arbitrary = sized hash'+        where hash' 0 = return NoHash+              hash' _ = SHA256 . BC.pack <$> sequence [ arbitrary | _ <- [1..32] :: [Int] ]++instance (Monad m) => Arbitrary (TreeItem m) where+  arbitrary = sized tree'+    where tree' 0 = oneof [ return (File emptyBlob), return (SubTree emptyTree) ]+          tree' n = oneof [ file n, subtree n ]+          file 0 = return (File emptyBlob)+          file _ = do content <- arbitrary+                      return (File $ Blob (return content) NoHash)+          subtree n = do branches <- choose (1, n)+                         let sub name = do t <- tree' ((n - 1) `div` branches)+                                           return (makeName $ show name, t)+                         sublist <- mapM sub [0..branches]+                         oneof [ tree' 0+                               , return (SubTree $ makeTree sublist)+                               , return $ (Stub $ return (makeTree sublist)) NoHash ]++instance (Monad m) => Arbitrary (Tree m) where+  arbitrary = do item <- arbitrary+                 case item of+                   File _ -> arbitrary+                   Stub _ _ -> arbitrary+                   SubTree t -> return t++data TreeWithPath = TreeWithPath (Tree Identity) AnchoredPath deriving (Show)++instance Arbitrary TreeWithPath where+  arbitrary = do t <- arbitrary+                 p <- oneof $ return (AnchoredPath []) :+                             (map (return . fst) $ list (runIdentity $ expand t))+                 return $ TreeWithPath t p++---------------------------+-- Other instances+--++instance Show (Blob m) where+    show (Blob _ h) = "Blob " ++ show h++instance Show (TreeItem m) where+    show (File f) = "File (" ++ show f ++ ")"+    show (Stub _ h) = "Stub _ " ++ show h+    show (SubTree s) = "SubTree (" ++ show s ++ ")"++instance Show (Tree m) where+    show t = "Tree " ++ show (treeHash t) ++ " { " +++             (concat . intersperse ", " $ itemstrs) ++ " }"+        where itemstrs = map show $ listImmediate t++instance Show (Int -> Int) where+    show f = "[" ++ intercalate ", " (map val [1..20]) ++ " ...]"+        where val x = show x ++ " -> " ++ show (f x)++-----------------------+-- Test utilities+--++shapeEq :: Tree m -> Tree m -> Bool+shapeEq a b = Just EQ == cmpShape a b++expandedShapeEq :: (Monad m, Functor m) => Tree m -> Tree m -> m Bool+expandedShapeEq a b = (Just EQ ==) <$> cmpExpandedShape a b++cmpcat :: [Maybe Ordering] -> Maybe Ordering+cmpcat (x:y:rest) | x == y = cmpcat (x:rest)+                  | x == Just EQ = cmpcat (y:rest)+                  | y == Just EQ = cmpcat (x:rest)+                  | otherwise = Nothing+cmpcat [x] = x+cmpcat [] = Just EQ -- empty things are equal++cmpTree :: (Monad m, Functor m) => Tree m -> Tree m -> m (Maybe Ordering)+cmpTree x y = do x' <- expand x+                 y' <- expand y+                 con <- contentsEq x' y'+                 return $ cmpcat [cmpShape x' y', con]+    where contentsEq a b = cmpcat <$> sequence (zipTrees cmp a b)+          cmp _ (Just (File a)) (Just (File b)) = do a' <- readBlob a+                                                     b' <- readBlob b+                                                     return $ Just (compare a' b')+          cmp _ _ _ = return (Just EQ) -- neutral++cmpShape :: Tree m -> Tree m -> Maybe Ordering+cmpShape t r = cmpcat $ zipTrees cmp t r+    where cmp _ (Just a) (Just b) = a `item` b+          cmp _ Nothing (Just _) = Just LT+          cmp _ (Just _) Nothing = Just GT+          cmp _ Nothing Nothing = Just EQ+          item (File _) (File _) = Just EQ+          item (SubTree s) (SubTree p) = s `cmpShape` p+          item _ _ = Nothing++cmpExpandedShape :: (Monad m) => Tree m -> Tree m -> m (Maybe Ordering)+cmpExpandedShape a b = do x <- expand a+                          y <- expand b+                          return $ x `cmpShape` y++nondarcs :: AnchoredPath -> TreeItem m -> Bool+nondarcs (AnchoredPath (x:_)) _ | x == makeName "_darcs" = False+                                     | otherwise = True+nondarcs (AnchoredPath []) _ = True++readDarcsPristine :: FilePath -> IO (Tree IO)+readDarcsPristine dir = do+  let darcs = dir </> "_darcs"+      h_inventory = darcs </> "hashed_inventory"+  repo <- doesDirectoryExist darcs+  unless repo $ fail $ "Not a darcs repository: " ++ dir+  isHashed <- doesFileExist h_inventory+  if isHashed+     then do inv <- BC.readFile h_inventory+             let thelines = BC.split '\n' inv+             case thelines of+               [] -> return emptyTree+               (pris_line:_) -> do+                          let thehash = decodeDarcsHash $ BC.drop 9 pris_line+                              thesize = decodeDarcsSize $ BC.drop 9 pris_line+                          when (thehash == NoHash) $ fail $ "Bad pristine root: " ++ show pris_line+                          readDarcsHashed (darcs </> "pristine.hashed") (thesize, thehash)+     else do have_pristine <- doesDirectoryExist $ darcs </> "pristine"+             have_current <- doesDirectoryExist $ darcs </> "current"+             case (have_pristine, have_current) of+               (True, _) -> readPlainTree $ darcs </> "pristine"+               (False, True) -> readPlainTree $ darcs </> "current"+               (_, _) -> fail "No pristine tree is available!"++extractRepoAndRun :: IO a -> IO a+extractRepoAndRun action = do+  zipFile <- toArchive . BLC.fromStrict <$> BC.readFile "harness/hstestdata.zip"+  withTempDir "_test_playground" $ \_ -> do+    extractFilesFromArchive [] zipFile+    action
harness/Darcs/Test/Misc.hs view
@@ -15,33 +15,45 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.Test.Misc ( testSuite ) where -import Darcs.Util.ByteString ( unpackPSFromUTF8, fromHex2PS, fromPS2Hex )+import Darcs.Util.ByteString+    ( unpackPSFromUTF8, fromHex2PS, fromPS2Hex+    , propHexConversion+    , prop_unlinesPS_linesPS_left_inverse+    , prop_linesPS_length+    , prop_unlinesPS_length+    , spec_betweenLinesPS+    , betweenLinesPS+    ) import Darcs.Util.Diff.Myers ( shiftBoundaries ) -import qualified Data.ByteString.Char8 as BC ( unpack, pack )-import qualified Data.ByteString as B ( concat, empty )+import Darcs.Test.Misc.CommandLine ( commandLineTestSuite )+import qualified Darcs.Test.Misc.Encoding as Encoding++import qualified Data.ByteString.Char8 as BC ( unpack, pack, last )+import qualified Data.ByteString as B ( ByteString, pack, empty, null )+import Data.Char ( ord ) import Data.Array.Base import Control.Monad.ST import Test.HUnit ( assertBool, assertEqual, assertFailure ) import Test.Framework.Providers.QuickCheck2 ( testProperty ) import Test.Framework.Providers.HUnit ( testCase ) import Test.Framework ( Test, testGroup )+import Test.QuickCheck   testSuite :: Test testSuite = testGroup ""  [ byteStringUtilsTestSuite  , lcsTestSuite+ , commandLineTestSuite+ , Encoding.testSuite  ]   -- ---------------------------------------------------------------------- -- * Darcs.Util.ByteString--- Here are a few quick tests of the shiftBoundaries function. -- ----------------------------------------------------------------------  byteStringUtilsTestSuite :: Test@@ -51,16 +63,27 @@   , testCase "Checking that hex packing and unpacking preserves 'hello world'"            (assertEqual "" (BC.unpack (fromHex2PS $ fromPS2Hex $ BC.pack "hello world"))                            "hello world")-  , testProperty "Checking that B.concat works" propConcatPS   , testProperty "Checking that hex conversion works" propHexConversion+  , testProperty "unlinesPS is left inverse of linesPS" prop_unlinesPS_linesPS_left_inverse+  , testProperty "linesPS length property" prop_linesPS_length+  , testProperty "unlinesPS length property" prop_unlinesPS_length+  , testProperty "betweenLinesPS behaves like its spec" prop_betweenLinesPS   ] -propHexConversion :: String -> Bool-propHexConversion s =-    fromHex2PS (fromPS2Hex $ BC.pack s) == BC.pack s+-- tweak the probabilities in favor of newline characters+instance Arbitrary B.ByteString where+  arbitrary = fmap B.pack $ listOf $ frequency+    [ (1, return (fromIntegral (ord '\n')))+    , (4, arbitrary)+    ] -propConcatPS :: [String] -> Bool-propConcatPS ss = concat ss == BC.unpack (B.concat $ map BC.pack ss)+-- betweenLinesPS and spec_betweenLinesPS are equivalent only+-- if certain conditions are met+prop_betweenLinesPS :: B.ByteString -> B.ByteString -> B.ByteString -> Property+prop_betweenLinesPS start end ps =+  not (B.null start) && not (B.null end) &&+  (B.null ps || BC.last ps == '\n') ==>+  betweenLinesPS start end ps == spec_betweenLinesPS start end ps  -- ---------------------------------------------------------------------- -- * LCS
+ harness/Darcs/Test/Misc/CommandLine.hs view
@@ -0,0 +1,41 @@+module Darcs.Test.Misc.CommandLine+  (+    commandLineTestSuite+  ) where++import Test.HUnit ( assertEqual, assertFailure )+import Test.Framework.Providers.HUnit ( testCase )+import Test.Framework ( Test, testGroup )++import Darcs.Util.CommandLine ( parseCmd )++formatTable :: [(Char, String)]+formatTable = [('s',"<insert subject here>"),+               ('a',"<insert author here>"),+               ('d',"date")+              ]++testParser :: (String, ([String], Bool)) -> Test+testParser (s, ok) =+  testCase ("Parse: " ++ show s) $+    case parseCmd formatTable s of+      Left e -> assertFailure $ "Parser failed with: " ++ show e+      Right res -> assertEqual ("Parsing: " ++ show s) ok res++testCases :: [(String, ([String], Bool))]+testCases = [("a b",(["a","b"], False)),+             ("a b %<",(["a","b"], True)),+             ("a b %< ",(["a","b"], True)),+             ("\"arg0 contains spaces \\\"quotes\\\"\" b",+              (["arg0 contains spaces \"quotes\"","b"],False)),+             ("a %s %<",(["a","<insert subject here>"], True)),+             ("\"%d\"", (["date"], False)),+             ("\"d %d\"", (["d date"], False)),+             ("\\\a", (["\\\a"], False)),+             ("\"\\\a\"", (["\a"], False)),+             ("\"/foo:%d\"", (["/foo:date"], False))+            ]++commandLineTestSuite :: Test+commandLineTestSuite =+  testGroup "Darcs.Util.CommandLine" $ map testParser testCases
+ harness/Darcs/Test/Misc/Encoding.hs view
@@ -0,0 +1,36 @@+module Darcs.Test.Misc.Encoding ( testSuite ) where++import qualified Data.ByteString as B+import Control.Monad+import Data.Word+import System.IO.Unsafe++import Darcs.Util.Encoding++import Test.Framework ( Test, testGroup )+import Test.Framework.Providers.QuickCheck2 ( testProperty )+import Test.QuickCheck++decodeThenEncode :: B.ByteString -> B.ByteString+decodeThenEncode = unsafePerformIO . (decode >=> encode)++testSuite :: Test+testSuite = testGroup "Darcs.Util.Encoding"+ [ testProperty "decode then encode roundtrips" propDecodeThenEncodeRoundTrip+ ]++-- could use the bytestring-arbitrary package,+-- but the shrinking isn't as effective as 'shrinkList shrink'+newtype MyByteString = MBS { _mbsBytes :: [Word8] }+ deriving Show++instance Arbitrary MyByteString where+  arbitrary = MBS <$> sized (\n -> vectorOf (100*n) arbitrary)+  shrink (MBS ws) = MBS <$> shrinkList shrink ws++toBS :: MyByteString -> B.ByteString+toBS (MBS ws) = B.pack ws++propDecodeThenEncodeRoundTrip :: MyByteString -> Bool+propDecodeThenEncodeRoundTrip mbs =+  let bstr = toBS mbs in decodeThenEncode bstr == bstr
harness/Darcs/Test/Patch.hs view
@@ -1,8 +1,4 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE CPP, ImpredicativeTypes #-}-#if __GLASGOW_HASKELL__ >= 708-{-# LANGUAGE AllowAmbiguousTypes #-}-#endif+{-# LANGUAGE AllowAmbiguousTypes  #-} --  Copyright (C) 2002-2005,2007 David Roundy -- --  This program is free software; you can redistribute it and/or modify@@ -35,19 +31,21 @@  import Darcs.Patch.Witnesses.Ordered import Darcs.Patch.Witnesses.Sealed-import Darcs.Patch.Witnesses.Eq ( MyEq, unsafeCompare )+import Darcs.Patch.Witnesses.Eq ( Eq2, unsafeCompare ) import Darcs.Patch.Witnesses.Show-import Darcs.Patch.Prim( PrimPatch, coalesce, FromPrim, PrimOf, PrimPatchBase )-import qualified Darcs.Patch.Prim.V1 as V1 ( Prim )+import Darcs.Patch.Prim( PrimPatch, coalesce, FromPrim, PrimOf ) import qualified Darcs.Patch.Prim.FileUUID as FileUUID ( Prim ) import Darcs.Patch.RepoPatch ( RepoPatch ) import Darcs.Patch.Type ( PatchType(..) ) import Darcs.Patch.V1 as V1 ( RepoPatchV1 )+import qualified Darcs.Patch.V1.Prim as V1 ( Prim )+import qualified Darcs.Patch.V2.Prim as V2 ( Prim ) import Darcs.Patch.V2.RepoPatch ( isConsistent, isForward, RepoPatchV2 )-import Darcs.Patch.Patchy ( Commute(..), Patchy )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Invert ( Invert ) import Darcs.Patch.Merge( Merge ) import Darcs.Patch.Show ( ShowPatchBasic )-import Darcs.Patch.Apply( ApplyState )+import Darcs.Patch.Apply( Apply, ApplyState )  import Darcs.Test.Patch.Arbitrary.Generic import qualified Darcs.Test.Patch.Arbitrary.PrimV1 as P1@@ -76,15 +74,16 @@ import qualified Darcs.Test.Patch.WSub as WSub  -type instance ModelOf (FL prim) = ModelOf prim+type Prim1 = V1.Prim+type Prim2 = V2.Prim -type TestGenerator thing gen = (forall t ctx . ((forall wXx wYy . thing wXx wYy -> t) -> (gen ctx -> t)))-type TestCondition thing = (forall wYy wZz . thing wYy wZz -> Bool)-type TestCheck thing t = (forall wYy wZz . thing wYy wZz -> t)+newtype TestGenerator thing gen = TestGenerator (forall t ctx . ((forall wXx wYy . thing wXx wYy -> t) -> (gen ctx -> t)))+newtype TestCondition thing = TestCondition (forall wYy wZz . thing wYy wZz -> Bool)+newtype TestCheck thing t = TestCheck (forall wYy wZz . thing wYy wZz -> t)  -- arbitraryThing :: (forall wXx wYy . thing wXx wYy -> t) -> (thing wA wB -> t) arbitraryThing :: x -> TestGenerator thing (thing x)-arbitraryThing _ f p = f p+arbitraryThing _ = TestGenerator (\f p -> f p)  -- | Run a test function on a set of data, using HUnit. The test function should --   return @Nothing@ upon success and a @Just x@ upon failure.@@ -123,7 +122,7 @@   , testCases "FL prim recommute" (PropU.recommute WSub.commute) ExU.commutablesFL   , testCases "FL prim patch and inverse commute" (PropU.patchAndInverseCommute WSub.commute) ExU.commutablesFL   , testCases "FL prim inverses commute" (PropU.commuteInverses WSub.commute) $ ExU.commutablesFL-  , testCases "fails" (PropU.commuteFails WSub.commute) ([] :: [(V1.Prim WSub.:> V1.Prim) wX wY])+  , testCases "fails" (PropU.commuteFails WSub.commute) ([] :: [(Prim2 WSub.:> Prim2) wX wY])   , testCases "read and show work on Prim" PropU.show_read ExU.primPatches   , testCases "read and show work on RepoPatchV2" PropU.show_read ExU.repov2Patches   , testCases "example flattenings work" PropU.consistentTreeFlattenings ExU.repov2PatchLoopExamples@@ -140,27 +139,16 @@   , testCases "V2 partial permutivity" (PropU.partialPermutivity WSub.commute) ExU.repov2NonduplicateTriples   ] -instance PrimPatch prim => Check (RepoPatchV2 prim) where-  checkPatch p = return $ isNothing $ isConsistent p--instance Check FileUUID.Prim where-  checkPatch _ = return True -- XXX--commuteRepoPatchV2s :: PrimPatch prim => (RepoPatchV2 prim :> RepoPatchV2 prim) wX wY -> Maybe ((RepoPatchV2 prim :> RepoPatchV2 prim) wX wY)-commuteRepoPatchV2s = commute- qc_prim :: forall prim wX wY wA model.            (PrimPatch prim, ArbitraryPrim prim, Show2 prim            , model ~ ModelOf prim, RepoModel model            , RepoState model ~ ApplyState (PrimOf prim)            , Show1 (ModelOf prim)-           , Check prim, PrimPatchBase prim, PrimOf prim ~ prim+           , Check prim, PrimOf prim ~ prim            , FromPrim prim            , MightBeEmptyHunk prim            , MightHaveDuplicate prim            , Show1 (prim wA)-           , Show1 ((prim :> prim) wA)-           , Show1 (WithState model prim wA)            , Arbitrary (Sealed ((prim :> prim) wA))            , Arbitrary (Sealed ((prim :> prim :> prim) wA))            , Arbitrary (Sealed (prim wA))@@ -195,12 +183,18 @@   ]       where arbitraryThing' = arbitraryThing (undefined :: wA) -- bind the witness for generator +consistentV2 :: RepoPatchV2 Prim2 wX wY -> TestResult+consistentV2 = fromMaybe . isConsistent++commuteRepoPatchV2s :: (RepoPatchV2 Prim2 :> RepoPatchV2 Prim2) wX wY -> Maybe ((RepoPatchV2 Prim2 :> RepoPatchV2 Prim2) wX wY)+commuteRepoPatchV2s = commute+ qc_V2P1 :: [Test] qc_V2P1 =   [ testProperty "tree flattenings are consistent... "-    (PropR.propConsistentTreeFlattenings :: Sealed (WithStartState (ModelOf V1.Prim) (Tree V1.Prim)) -> Bool)+    (PropR.propConsistentTreeFlattenings :: Sealed (WithStartState (ModelOf Prim2) (Tree Prim2)) -> Bool)   , testProperty "with quickcheck that RepoPatchV2 patches are consistent... "-    (unseal $ P1.patchFromTree $ fromMaybe . isConsistent)+    (unseal $ P1.patchFromTree $ consistentV2)   -- permutivity ----------------------------------------------------------------------------   , testConditional "permutivity"     (unseal $ P1.commuteTripleFromTree notDuplicatestriple)@@ -214,7 +208,7 @@   ]  qc_V2 :: forall prim wXx wYy . (PrimPatch prim, Show1 (ModelOf prim), RepoModel (ModelOf prim),-                                  Check (RepoPatchV2 prim), ArbitraryPrim prim, Show2 prim,+                                  ArbitraryPrim prim, Show2 prim,                                   RepoState (ModelOf prim) ~ ApplyState prim)       => prim wXx wYy -> [Test] qc_V2 _ =@@ -228,11 +222,11 @@                      -> Maybe (Tree (RepoPatchV2 prim) wX)))   ]   ++ concat-  [ merge_properties   (undefined :: RepoPatchV2 prim wX wY) "tree" mergePairFromTree-  , merge_properties   (undefined :: RepoPatchV2 prim wX wY) "twfp" mergePairFromTWFP-  , pair_properties    (undefined :: RepoPatchV2 prim wX wY) "tree" commutePairFromTree-  , pair_properties    (undefined :: RepoPatchV2 prim wX wY) "twfp" commutePairFromTWFP-  , patch_properties   (undefined :: RepoPatchV2 prim wX wY) "tree" patchFromTree+  [ merge_properties   (undefined :: RepoPatchV2 prim wX wY) "tree" (TestGenerator mergePairFromTree)+  , merge_properties   (undefined :: RepoPatchV2 prim wX wY) "twfp" (TestGenerator mergePairFromTWFP)+  , pair_properties    (undefined :: RepoPatchV2 prim wX wY) "tree" (TestGenerator commutePairFromTree)+  , pair_properties    (undefined :: RepoPatchV2 prim wX wY) "twfp" (TestGenerator commutePairFromTWFP)+  , patch_properties   (undefined :: RepoPatchV2 prim wX wY) "tree" (TestGenerator patchFromTree)   ]  properties :: forall thing gen. (Show1 gen, Arbitrary (Sealed gen)) =>@@ -241,86 +235,98 @@            -> String -> String            -> forall t. Testable t => [(String, TestCondition thing, TestCheck thing t)]            -> [Test]-properties gen prefix genname tests =+properties (TestGenerator gen) prefix genname tests =   [ cond name condition check | (name, condition, check) <- tests ]   where cond :: forall testable. Testable testable              => String -> TestCondition thing -> TestCheck thing testable -> Test-        cond t c p =+        cond t (TestCondition c) (TestCheck p) =           testConditional (prefix ++ " (" ++ genname ++ "): " ++ t) (unseal $ gen c) (unseal $ gen p)  type PropList what gen = String -> TestGenerator what gen -> [Test]  pair_properties :: forall p gen x y-                 . ( Show1 gen, Arbitrary (Sealed gen), Patchy p, MightHaveDuplicate p-                   , ShowPatchBasic p, MyEq p+                 . ( Show1 gen, Arbitrary (Sealed gen), MightHaveDuplicate p+                   , Commute p, Invert p, ShowPatchBasic p, Eq2 p                    )                 => p x y -> PropList (p :> p) gen pair_properties _ genname gen =   properties gen "commute" genname-  [ ("recommute"              , const True       , PropG.recommute commute             )-  , ("nontrivial recommute"   , nontrivialCommute, PropG.recommute commute             )-  , ("inverses commute"       , const True       , PropG.commuteInverses commute       )-  , ("nontrivial inverses"    , nontrivialCommute, PropG.commuteInverses commute       )-  , ("inverse composition"    , const True       , PropG.inverseComposition            )+  [ ("recommute"              , TestCondition (const True)     , TestCheck (PropG.recommute commute)           )+  , ("nontrivial recommute"   , TestCondition nontrivialCommute, TestCheck (PropG.recommute commute)           )+  , ("inverses commute"       , TestCondition (const True)     , TestCheck (PropG.commuteInverses commute)     )+  , ("nontrivial inverses"    , TestCondition nontrivialCommute, TestCheck (PropG.commuteInverses commute)     )+  , ("inverse composition"    , TestCondition (const True)     , TestCheck PropG.inverseComposition            )   ]  coalesce_properties :: forall p gen x y-                     . ( Show1 gen, Arbitrary (Sealed gen), Patchy p, PrimPatch p+                     . ( Show1 gen, Arbitrary (Sealed gen), PrimPatch p                        , ArbitraryPrim p, MightBeEmptyHunk p                        )                     => p x y -> PropList (p :> p :> p) gen coalesce_properties p genname gen =   properties gen "commute" genname-   (if runCoalesceTests p then [ ("coalesce commutes with commute", const True, PropG.coalesceCommute coalesce) ] else [])+   (if runCoalesceTests p then [ ("coalesce commutes with commute", TestCondition (const True), TestCheck (PropG.coalesceCommute coalesce)) ] else [])  -- The following properties do not hold for "RepoPatchV2" patches (conflictors and -- duplicates, specifically) . nonrpv2_commute_properties :: forall p gen x y-                            . (Show1 gen, Arbitrary (Sealed gen), Patchy p, ShowPatchBasic p, MyEq p)+                            . (Show1 gen, Arbitrary (Sealed gen), Commute p, Invert p, ShowPatchBasic p, Eq2 p)                            => p x y -> PropList (p :> p) gen nonrpv2_commute_properties _ genname gen =   properties gen "commute" genname-  [ ("patch & inverse commute", const True       , PropG.patchAndInverseCommute commute)-  , ("patch & inverse commute", nontrivialCommute, PropG.patchAndInverseCommute commute)+  [ ("patch & inverse commute", TestCondition (const True)     , TestCheck (PropG.patchAndInverseCommute commute))+  , ("patch & inverse commute", TestCondition nontrivialCommute, TestCheck (PropG.patchAndInverseCommute commute))   ] -patch_properties :: forall p gen x y. (Show1 gen, Arbitrary (Sealed gen), Patchy p, MyEq p)+patch_properties :: forall p gen x y. (Show1 gen, Arbitrary (Sealed gen), Invert p, Apply p, Eq2 p)                  => p x y -> PropList p gen patch_properties _ genname gen =   properties gen "patch" genname-  [ ("inverse . inverse is id"  , const True       , PropG.invertSymmetry)+  [ ("inverse . inverse is id"  , TestCondition (const True)     , TestCheck PropG.invertSymmetry)   ]  patch_repo_properties :: forall p gen x y. (Show1 gen, Arbitrary (Sealed gen),-                                            Patchy p, ShowPatchBasic p,+                                            Invert p, Apply p, ShowPatchBasic p,                                             RepoModel (ModelOf (PrimOf p)),                                             RepoState (ModelOf (PrimOf p)) ~ ApplyState p)                       => p x y -> PropList (WithState (ModelOf (PrimOf p)) p) gen patch_repo_properties _ genname gen =   properties gen "patch/repo" genname-  [ ("invert rollback"          , const True       , PropG.invertRollback)+  [ ("invert rollback"          , TestCondition (const True)     , TestCheck PropG.invertRollback)   ] -pair_repo_properties :: forall p gen x y. (Show1 gen, Arbitrary (Sealed gen), Patchy p,-                                            MightBeEmptyHunk p,-                                            RepoModel (ModelOf p),-                                            RepoState (ModelOf p) ~ ApplyState p)-                      => p x y -> PropList (WithState (ModelOf p) (p :> p)) gen+pair_repo_properties+  :: forall p gen x y.+     ( Show1 gen+     , Arbitrary (Sealed gen)+     , Commute p+     , Apply p+     , ShowPatchBasic p+     , MightBeEmptyHunk p+     , RepoModel (ModelOf p)+     , RepoState (ModelOf p) ~ ApplyState p+     )+  => p x y -> PropList (WithState (ModelOf p) (p :> p)) gen pair_repo_properties _ genname gen =-  properties gen "patch/repo" genname-  [ ("commute is effect preserving" , const True       , PropG.effectPreserving commute )-  ]+  properties+    gen+    "patch/repo"+    genname+    [ ( "commute is effect preserving"+      , TestCondition (const True)+      , TestCheck (PropG.effectPreserving commute))+    ]  merge_properties :: forall p gen x y. (Show1 gen, Arbitrary (Sealed gen)-                                      , Patchy p, MyEq p, Merge p, ShowPatchBasic p+                                      , Invert p, Eq2 p, Merge p, ShowPatchBasic p                                       , MightHaveDuplicate p, Show2 p, Check p)                  => p x y -> PropList (p :\/: p) gen merge_properties _ genname gen =   properties gen "merge" genname-  [ ("merge either way"           , const True     , PropG.mergeEitherWay      )-  , ("merge either way valid"     , const True     , Prop1.tMergeEitherWayValid)-  , ("nontrivial merge either way", nontrivialMerge, PropG.mergeEitherWay      )-  , ("merge commute"              , const True     , PropG.mergeCommute        )+  [ ("merge either way"           , TestCondition (const True)   , TestCheck PropG.mergeEitherWay      )+  , ("merge either way valid"     , TestCondition (const True)   , TestCheck Prop1.tMergeEitherWayValid)+  , ("nontrivial merge either way", TestCondition nontrivialMerge, TestCheck PropG.mergeEitherWay      )+  , ("merge commute"              , TestCondition (const True)   , TestCheck PropG.mergeCommute        )   ]  qc_V1P1 :: [Test]@@ -357,10 +363,10 @@   ] -- the following properties are disabled, because they routinely lead to     -- exponential cases, making the tests run for ever and ever; nevertheless,     -- we would expect them to hold- {- ++ merge_properties (undefined :: V1.RepoPatchV1 Prim wX wY) "tree" mergePairFromTree-    ++ merge_properties (undefined :: V1.RepoPatchV1 Prim wX wY) "twfp" mergePairFromTWFP-    ++ commute_properties (undefined :: V1.RepoPatchV1 Prim wX wY) "tree" commutePairFromTree-    ++ commute_properties (undefined :: V1.RepoPatchV1 Prim wX wY) "twfp" commutePairFromTWFP -}+ {- ++ merge_properties (undefined :: V1.RepoPatchV1 Prim1 wX wY) "tree" mergePairFromTree+    ++ merge_properties (undefined :: V1.RepoPatchV1 Prim1 wX wY) "twfp" mergePairFromTWFP+    ++ commute_properties (undefined :: V1.RepoPatchV1 Prim1 wX wY) "tree" commutePairFromTree+    ++ commute_properties (undefined :: V1.RepoPatchV1 Prim1 wX wY) "twfp" commutePairFromTWFP -}  -- tests (either QuickCheck or Unit) that should be run on any type of patch general_patchTests :: (RepoPatch p, ArbitraryPrim (PrimOf p), Show2 (PrimOf p)) => PatchType rt p -> [Test]@@ -370,16 +376,22 @@  -- | This is the big list of tests that will be run using testrunner. testSuite :: [Test]-testSuite = [ testGroup "Darcs.Patch.Prim.V1" $ qc_prim (undefined :: V1.Prim wX wY)-            , testGroup "Darcs.Patch.V1 (using Prim.V1)" $-                unit_V1P1 ++ qc_V1P1 ++ general_patchTests (PatchType :: PatchType rt (V1.RepoPatchV1 V1.Prim))-            , testGroup "Darcs.Patch.V2 (using Prim.V1)" $-                unit_V2P1 ++ qc_V2 (undefined :: V1.Prim wX wY) ++ qc_V2P1 ++-                general_patchTests (PatchType :: PatchType rt (RepoPatchV2 V1.Prim))-            -- , testGroup "Darcs.Patch.Prim.FileUUID" $ qc_prim (undefined :: FileUUID.Prim wX wY)-            , testGroup "Darcs.Patch.V2 (using Prim.FileUUID)" $-                qc_V2 (undefined :: FileUUID.Prim wX wY) ++-                general_patchTests (PatchType :: PatchType rt (RepoPatchV2 FileUUID.Prim))-            , Darcs.Test.Patch.Info.testSuite-            , Darcs.Test.Patch.Selection.testSuite-            ]+testSuite =+  [ testGroup "Darcs.Patch.Prim.V1 for V1" $ qc_prim (undefined :: Prim1 wX wY)+    -- testing both Prim1 and Prim2 here is redundant, since they differ+    -- only in their read/show behavior, which is not tested in qc_prim;+    -- we still include them because such tests might be added in the future+  , testGroup "Darcs.Patch.Prim.V1 for V2" $ qc_prim (undefined :: Prim2 wX wY)+  , testGroup "Darcs.Patch.Prim.FileUUID" $ qc_prim (undefined :: FileUUID.Prim wX wY)+  , testGroup "Darcs.Patch.V1 (using Prim.V1)" $+      unit_V1P1 ++ qc_V1P1 +++      general_patchTests (PatchType :: PatchType rt (V1.RepoPatchV1 Prim1))+  , testGroup "Darcs.Patch.V2 (using Prim.V1)" $+      unit_V2P1 ++ qc_V2 (undefined :: Prim2 wX wY) ++ qc_V2P1 +++      general_patchTests (PatchType :: PatchType rt (RepoPatchV2 Prim2))+  , testGroup "Darcs.Patch.V2 (using Prim.FileUUID)" $+      qc_V2 (undefined :: FileUUID.Prim wX wY) +++      general_patchTests (PatchType :: PatchType rt (RepoPatchV2 FileUUID.Prim))+  , Darcs.Test.Patch.Info.testSuite+  , Darcs.Test.Patch.Selection.testSuite+  ]
harness/Darcs/Test/Patch/Arbitrary/Generic.hs view
@@ -1,7 +1,5 @@-{-# OPTIONS_GHC -fno-warn-deprecations -fno-warn-orphans #-}-{-# LANGUAGE CPP, UndecidableInstances, ScopedTypeVariables, MultiParamTypeClasses,+{-# LANGUAGE UndecidableInstances, ScopedTypeVariables, MultiParamTypeClasses,              FlexibleInstances, ViewPatterns #-}- module Darcs.Test.Patch.Arbitrary.Generic        ( Tree(..), TreeWithFlattenPos(..), G2(..), ArbitraryPrim(..), NullPatch(..), RepoModel(..)        , MightBeEmptyHunk(..), MightHaveDuplicate(..)@@ -24,9 +22,9 @@ import Darcs.Patch.Witnesses.Unsafe import Darcs.Patch.Witnesses.Ordered import Darcs.Patch.Merge ( Merge(..) )-import Darcs.Patch.Patchy ( Invert(..), Commute(..) )+import Darcs.Patch.Invert ( Invert(..) )+import Darcs.Patch.Commute ( Commute(..) ) import Darcs.Patch.Prim ( PrimOf, PrimPatch, PrimPatchBase, FromPrim(..), PrimConstruct( anIdentity ) )-import Darcs.Patch.Prim.V1 () import Darcs.Patch.V2 ( RepoPatchV2 ) -- XXX this is more or less a hack --import Darcs.ColorPrinter ( errorDoc ) --import Darcs.ColorPrinter ( traceDoc )
harness/Darcs/Test/Patch/Arbitrary/PrimFileUUID.hs view
@@ -1,8 +1,9 @@--- TODO: Remove these warning disabling flags...-{-# OPTIONS_GHC -w #-}-{-# LANGUAGE CPP, MultiParamTypeClasses, OverloadedStrings #-}+{-# LANGUAGE MultiParamTypeClasses, OverloadedStrings #-} module Darcs.Test.Patch.Arbitrary.PrimFileUUID where +import Prelude ()+import Darcs.Prelude+ import qualified Darcs.Test.Patch.Arbitrary.Generic as T      ( commuteTripleFromTree, commutePairFromTree, commutePairFromTWFP      , mergePairFromTree, mergePairFromTWFP@@ -18,24 +19,20 @@ import Darcs.Patch.Witnesses.Unsafe import Darcs.Patch.Witnesses.Ordered import Darcs.Patch.Prim.FileUUID ()-import Darcs.Patch.Prim.FileUUID.Core ( Prim(..), Location, Hunk(..), UUID(..) )+import Darcs.Patch.Prim.FileUUID.Core ( Prim(..), Location(..), Hunk(..), UUID(..) ) import Darcs.Patch.RepoPatch ( RepoPatch )  import Darcs.Test.Patch.FileUUIDModel-import Darcs.Test.Util.QuickCheck ( alpha, notIn, maybeOf )+import Darcs.Test.Util.QuickCheck ( notIn, maybeOf ) -import Darcs.UI.Commands.Replace ( defaultToks ) import Darcs.Patch.Prim  import Control.Applicative ( (<$>) )-import qualified Data.ByteString.Char8 as BC-import qualified Data.ByteString as BS+import qualified Data.ByteString as B import Data.Maybe ( isJust ) import qualified Data.Map as M import Darcs.Util.Hash( Hash(..) ) -#include "impossible.h"- patchFromTree :: (RepoPatch p, PrimOf p ~ Prim) => (forall wY wZ . p wY wZ -> t) -> WithStartState FileUUIDModel (Tree Prim) wX -> t patchFromTree = T.patchFromTree @@ -59,18 +56,15 @@     runCoalesceTests _ = False     hasPrimConstruct _ = False -hunkIdentity (Hunk _ old new) | old == new = unsafeCoerceP IsEq-hunkIdentity _ = NotEq+instance MightBeEmptyHunk Prim+instance MightHaveDuplicate Prim  instance NullPatch Prim where-  nullPatch (BinaryHunk _ x) = hunkIdentity x-  nullPatch (TextHunk _ x) = hunkIdentity x+  nullPatch Identity = IsEq+  nullPatch (Hunk _ (H _ old new))+    | old == new = unsafeCoerceP IsEq   nullPatch _ = NotEq -instance Arbitrary (Sealed2 (FL (WithState FileUUIDModel Prim))) where-  arbitrary = do repo <- ourSmallRepo-                 liftM (unseal (seal2 . wesPatch)) $ arbitraryState repo- -- instance Show1 (TreeWithFlattenPos Prim) where --   showDict1 = ShowDictClass @@ -81,93 +75,83 @@ ---------------------------------------------------------------------- -- * QuickCheck generators -aHunk :: forall wX wY . BS.ByteString -> Gen (Hunk wX wY)-aHunk content- = sized $ \n ->-     do pos <- choose (0, BS.length content)-        let prefixLen = pos-            restLen   = BS.length content - prefixLen-        oldLen <- frequency-                      [ (75, choose (0, min restLen n))-                      , (25, choose (0, min 10 restLen))-                      ]-        let nonempty x = if oldLen /= 0 then x else 0-        newLen <- frequency-                      [ ( 54, choose (1,min 1 n) )-                      , ( nonempty 42, choose (1,min 1 oldLen) )-                      , ( nonempty 2, return oldLen )-                      , ( nonempty 2, return 0 )-                      ]-        new <- BS.concat <$> vectorOf newLen aLine-        let old = BS.take oldLen $ BS.drop prefixLen $ content-        return $ Hunk pos old new+aHunk :: B.ByteString -> Gen (Hunk wX wY)+aHunk content = do+  pos <- choose (0, B.length content)+  oldLen <- choose (0, B.length content - pos)+  new <- scale (`div` 8) aContent+  let old = B.take oldLen $ B.drop pos $ content+  return $ H pos old new -aTextHunk :: forall wX wY . (UUID, Object Fail) -> Gen (Prim wX wY)+aTextHunk :: (UUID, Object Fail) -> Gen (Prim wX wY) aTextHunk (uuid, (Blob text _)) =-  do hunk <- aHunk (unFail text)-     return $ TextHunk uuid hunk+  do h <- aHunk (unFail text)+     return $ Hunk uuid h+aTextHunk _ = impossible -aManifest :: forall wX wY . UUID -> Location -> Object Fail -> Gen (Prim wX wY)-aManifest uuid loc (Directory dir) =-  do newFilename <- aFilename `notIn` (M.keys dir)-     return $ Manifest uuid loc+aManifest :: UUID -> (UUID, Object Fail) -> Gen (Prim wX wY)+aManifest uuid (dirId, Directory dir) =+  do filename <- aFilename `notIn` (M.keys dir)+     return $ Manifest uuid (L dirId filename)+aManifest _ _ = impossible -aDemanifest :: forall wX wY . UUID -> Location -> Gen (Prim wX wY)+aDemanifest :: UUID -> Location -> Gen (Prim wX wY) aDemanifest uuid loc = return $ Demanifest uuid loc  -- | Generates any type of 'Prim' patch, except binary and setpref patches.-aPrim :: forall wX wY . FileUUIDModel wX -> Gen (WithEndState FileUUIDModel (Prim wX) wY)+aPrim :: FileUUIDModel wX -> Gen (WithEndState FileUUIDModel (Prim wX) wY) aPrim repo-  = do mbFile <- maybeOf repoFiles-       mbDir <- maybeOf repoDirs-       mbExisting <- maybeOf $ repoObjects repo-       mbManifested <- maybeOf manifested-       fresh <- anUUID-       filename <- aFilename-       dir  <- elements (rootDir:repoDirs)-       mbOtherDir <- maybeOf repoDirs-       let whenfile x = if isJust mbFile then x else 0-           whendir x = if isJust mbDir then x else 0-           whenexisting x = if isJust mbExisting then x else 0-           whenmanifested x = if isJust mbManifested then x else 0+  = do mbFile <- maybeOf repoFiles -- some file, not necessarily manifested+       dir <- elements repoDirs -- some directory, not necessarily manifested+       -- note, the root directory always exists and is never manifested nor demanifested+       mbDemanifested <- maybeOf notManifested -- something manifested+       mbManifested <- maybeOf manifested -- something not manifested+       fresh <- anUUID `notIn` repoIds repo -- a fresh uuid+       let whenjust m x = if isJust m then x else 0+           whenfile = whenjust mbFile+           whendemanifested = whenjust mbDemanifested+           whenmanifested = whenjust mbManifested        patch <- frequency-                  [ ( whenfile 12, aTextHunk $ fromJust mbFile )-                  , ( 2, aTextHunk (fresh, Blob (return "") NoHash) ) -- create an empty thing-                  , ( whenexisting (whendir 2), -- manifest an existing object-                      aManifest (fst $ fromJust mbExisting)-                                (fst $ fromJust mbDir, filename)-                                (snd $ fromJust mbDir))-                  , ( whenmanifested 2, uncurry aDemanifest $ fromJust mbManifested )-                    -- TODO: demanifest+                  [ ( whenfile 12, aTextHunk $ fromJust mbFile ) -- edit an existing file+                  , ( 2, aTextHunk (fresh, Blob (return "") NoHash) ) -- edit a new file+                  , ( whendemanifested 2 -- manifest an existing object+                    , aManifest (fromJust mbDemanifested) dir+                    )+                  , ( whenmanifested 2+                    , uncurry aDemanifest $ fromJust mbManifested+                    )                   ]        let repo' = unFail $ repoApply repo patch        return $ WithEndState patch repo'   where-      manifested = [ (id, (dirid, name)) | (dirid, Directory dir) <- repoDirs-                                         , (name, id) <- M.toList dir ]-      repoFiles = [ (id, Blob x y) | (id, Blob x y) <- repoObjects repo ]-      repoDirs  = [ (id, Directory x) | (id, Directory x) <- repoObjects repo ]-      rootDir   = (UUID "ROOT", root repo)+      manifested = [ (uuid, (L dirid name)) | (dirid, Directory dir) <- repoDirs+                                          , (name, uuid) <- M.toList dir ]+      notManifested = [ uuid | (uuid, _) <- nonRootObjects+                           , not (uuid `elem` map fst manifested) ]+      repoFiles = [ (uuid, Blob x y) | (uuid, Blob x y) <- repoObjects repo ]+      repoDirs  = [ (uuid, Directory x) | (uuid, Directory x) <- repoObjects repo ]+      nonRootObjects = filter notRoot $ repoObjects repo where+        notRoot (uuid, _) = uuid == rootId  ---------------------------------------------------------------------- -- *** Pairs of primitive patches  -- Try to generate commutable pairs of hunks-hunkPair :: forall wX wY . (UUID, Object Fail) -> Gen ((Prim :> Prim) wX wY)+hunkPair :: (UUID, Object Fail) -> Gen ((Prim :> Prim) wX wY) hunkPair (uuid, (Blob file _)) =-  do h1@(Hunk l1 old1 new1) <- aHunk (unFail file)+  do h1@(H off1 old1 new1) <- aHunk (unFail file)      (delta, content') <- selectChunk h1 (unFail file)-     Hunk l2' old2 new2 <- aHunk content'-     let l2 = l2'+delta-     return (TextHunk uuid (Hunk l1 old1 new1) :> TextHunk uuid (Hunk l2 old2 new2))+     H off2' old2 new2 <- aHunk content'+     let off2 = off2' + delta+     return (Hunk uuid (H off1 old1 new1) :> Hunk uuid (H off2 old2 new2))   where-     selectChunk (Hunk l old new) content = elements [prefix, suffix]-       where start = l - 1-             prefix = (0, BS.take start content)-             suffix = (start + BS.length new, BS.drop (start + BS.length old) content)-     selectChunk _ _ = impossible+     selectChunk (H off old new) content = elements [prefix, suffix]+       where prefix = (0, B.take off content)+             suffix = (off + B.length new, B.drop (off + B.length old) content)+hunkPair _ = impossible -aPrimPair :: forall wX wY . FileUUIDModel wX -> Gen (WithEndState FileUUIDModel ((Prim :> Prim) wX) wY)+aPrimPair :: FileUUIDModel wX+          -> Gen (WithEndState FileUUIDModel ((Prim :> Prim) wX) wY) aPrimPair repo   = do mbFile <- maybeOf repoFiles        frequency@@ -183,7 +167,7 @@             )           ]   where-      repoFiles = [ (id, Blob x y) | (id, Blob x y) <- repoObjects repo ]+      repoFiles = [ (uuid, Blob x y) | (uuid, Blob x y) <- repoObjects repo ]  ---------------------------------------------------------------------- -- Arbitrary instances@@ -193,6 +177,11 @@  instance ArbitraryState FileUUIDModel Prim where   arbitraryState s = seal <$> aPrim s+++instance Arbitrary (Sealed2 (FL (WithState FileUUIDModel Prim))) where+  arbitrary = do repo <- ourSmallRepo+                 liftM (unseal (seal2 . wesPatch)) $ arbitraryState repo   instance Arbitrary (Sealed2 Prim) where
harness/Darcs/Test/Patch/Arbitrary/PrimV1.hs view
@@ -1,5 +1,4 @@-{-# LANGUAGE CPP, MultiParamTypeClasses #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE MultiParamTypeClasses #-} module Darcs.Test.Patch.Arbitrary.PrimV1 where  import qualified Darcs.Test.Patch.Arbitrary.Generic as T@@ -20,39 +19,44 @@ import Darcs.Patch.Witnesses.Eq import Darcs.Patch.Witnesses.Unsafe import Darcs.Patch.Witnesses.Ordered-import Darcs.Patch.Prim.V1 ()-import Darcs.Patch.Prim.V1.Core ( FilePatchType( Hunk, TokReplace ), Prim( FP ), isIdentity )+import Darcs.Patch.Prim.V1.Core ( FilePatchType( Hunk, TokReplace ), isIdentity )+import qualified Darcs.Patch.Prim.V1.Core as Prim ( Prim( FP ) )+import qualified Darcs.Patch.V1.Prim as V1 ( Prim(..) )+import qualified Darcs.Patch.V2.Prim as V2 ( Prim(..) ) import Darcs.Patch.RepoPatch ( RepoPatch ) import Darcs.Patch.FileHunk( IsHunk( isHunk ), FileHunk(..) )  import Darcs.Test.Patch.V1Model import Darcs.Util.Path+import qualified Darcs.Util.Tree as UT ( Tree ) import Darcs.Test.Util.QuickCheck ( alpha, notIn, maybeOf )  import Darcs.UI.Commands.Replace ( defaultToks ) import Darcs.Patch.Prim+import Darcs.Patch.Apply ( ApplyState )  import qualified Data.ByteString.Char8 as BC import Data.Maybe ( isJust ) -#include "impossible.h"+type Prim1 = V1.Prim+type Prim2 = V2.Prim -patchFromTree :: (RepoPatch p, PrimOf p ~ Prim) => (forall wY wZ . p wY wZ -> t) -> WithStartState V1Model (Tree Prim) wX -> t+patchFromTree :: (RepoPatch p, PrimOf p ~ prim) => (forall wY wZ . p wY wZ -> t) -> WithStartState V1Model (Tree prim) wX -> t patchFromTree = T.patchFromTree -mergePairFromTree :: (RepoPatch p, PrimOf p ~ Prim) => (forall wY wZ . (p :\/: p) wY wZ -> t) -> WithStartState V1Model (Tree Prim) wX -> t+mergePairFromTree :: (RepoPatch p, PrimOf p ~ prim) => (forall wY wZ . (p :\/: p) wY wZ -> t) -> WithStartState V1Model (Tree prim) wX -> t mergePairFromTree = T.mergePairFromTree -mergePairFromTWFP :: (RepoPatch p, PrimOf p ~ Prim) => (forall wY wZ . (p :\/: p) wY wZ -> t) -> WithStartState V1Model (TreeWithFlattenPos Prim) wX -> t+mergePairFromTWFP :: (RepoPatch p, PrimOf p ~ prim) => (forall wY wZ . (p :\/: p) wY wZ -> t) -> WithStartState V1Model (TreeWithFlattenPos prim) wX -> t mergePairFromTWFP = T.mergePairFromTWFP -commutePairFromTWFP :: (RepoPatch p, PrimOf p ~ Prim) => (forall wY wZ . (p :> p) wY wZ -> t) -> WithStartState V1Model (TreeWithFlattenPos Prim) wX -> t+commutePairFromTWFP :: (RepoPatch p, PrimOf p ~ prim) => (forall wY wZ . (p :> p) wY wZ -> t) -> WithStartState V1Model (TreeWithFlattenPos prim) wX -> t commutePairFromTWFP = T.commutePairFromTWFP -commutePairFromTree :: (RepoPatch p, PrimOf p ~ Prim) => (forall wY wZ . (p :> p) wY wZ -> t) -> WithStartState V1Model (Tree Prim) wX -> t+commutePairFromTree :: (RepoPatch p, PrimOf p ~ prim) => (forall wY wZ . (p :> p) wY wZ -> t) -> WithStartState V1Model (Tree prim) wX -> t commutePairFromTree = T.commutePairFromTree -commuteTripleFromTree :: (RepoPatch p, PrimOf p ~ Prim) => (forall wY wZ . (p :> p :> p) wY wZ -> t) -> WithStartState V1Model (Tree Prim) wX -> t+commuteTripleFromTree :: (RepoPatch p, PrimOf p ~ prim) => (forall wY wZ . (p :> p :> p) wY wZ -> t) -> WithStartState V1Model (Tree prim) wX -> t commuteTripleFromTree = T.commuteTripleFromTree  nonEmptyHunk :: (IsHunk p) => p wX wY -> Bool@@ -69,33 +73,49 @@ nonEmptyHunksFLPair :: (IsHunk p) => (FL p :> FL p) wX wY -> Bool nonEmptyHunksFLPair (ps :> qs) = allFL nonEmptyHunk ps && allFL nonEmptyHunk qs -type instance ModelOf Prim = V1Model-instance ArbitraryPrim Prim+type instance ModelOf Prim1 = V1Model+type instance ModelOf Prim2 = V1Model+instance ArbitraryPrim Prim1+instance ArbitraryPrim Prim2 -instance NullPatch Prim where-  nullPatch (FP _ fp) = nullPatch fp-  nullPatch p | IsEq <- isIdentity p = IsEq+instance NullPatch Prim2 where+  nullPatch (V2.Prim (Prim.FP _ fp)) = nullPatch fp+  nullPatch p | IsEq <- isIdentity (V2.unPrim p) = IsEq   nullPatch _ = NotEq +instance NullPatch Prim1 where+  nullPatch (V1.Prim (Prim.FP _ fp)) = nullPatch fp+  nullPatch p | IsEq <- isIdentity (V1.unPrim p) = IsEq+  nullPatch _ = NotEq+ instance NullPatch FilePatchType where   nullPatch (Hunk _ [] []) = unsafeCoerceP IsEq -- is this safe?   nullPatch _ = NotEq -instance MightBeEmptyHunk Prim where-  isEmptyHunk (FP _ (Hunk _ [] [])) = True+instance MightBeEmptyHunk Prim1 where+  isEmptyHunk (V1.Prim (Prim.FP _ (Hunk _ [] []))) = True   isEmptyHunk _ = False -instance MightHaveDuplicate Prim+instance MightBeEmptyHunk Prim2 where+  isEmptyHunk (V2.Prim (Prim.FP _ (Hunk _ [] []))) = True+  isEmptyHunk _ = False -instance Arbitrary (Sealed2 (FL (WithState V1Model Prim))) where+instance MightHaveDuplicate Prim1+instance MightHaveDuplicate Prim2++instance Arbitrary (Sealed2 (FL (WithState V1Model Prim1))) where   arbitrary = do repo <- ourSmallRepo                  liftM (unseal (seal2 . wesPatch)) $ arbitraryState repo +instance Arbitrary (Sealed2 (FL (WithState V1Model Prim2))) where+  arbitrary = do repo <- ourSmallRepo+                 liftM (unseal (seal2 . wesPatch)) $ arbitraryState repo+ -- instance Show1 (TreeWithFlattenPos Prim) where --   showDict1 = ShowDictClass  -- WithState and propFail are handy for debugging arbitrary code-propFail :: Int -> Tree Prim wX -> Bool+propFail :: Int -> Tree prim wX -> Bool propFail n xs = sizeTree xs < n  ----------------------------------------------------------------------@@ -153,21 +173,21 @@ ---------------------------------------------------------------------- -- ** Prim generators -aHunkP :: forall wX wY . (AnchoredPath,File) -> Gen (Prim wX wY)+aHunkP :: forall prim wX wY . PrimPatch prim => (AnchoredPath,File) -> Gen (prim wX wY) aHunkP (path,file)   = do Hunk pos old new <- aHunk content        return $ hunk (ap2fp path) pos old new   where       content = fileContent file -aTokReplaceP :: forall wX wY . (AnchoredPath,File) -> Gen (Prim wX wY)+aTokReplaceP :: forall prim wX wY . PrimPatch prim => (AnchoredPath,File) -> Gen (prim wX wY) aTokReplaceP (path,file)   = do TokReplace tokchars old new <- aTokReplace content        return $ tokreplace (ap2fp path) tokchars old new   where       content = fileContent file -anAddFileP :: forall wX wY . (AnchoredPath,Dir) -> Gen (Prim wX wY)+anAddFileP :: forall prim wX wY . PrimPatch prim => (AnchoredPath,Dir) -> Gen (prim wX wY) anAddFileP (path,dir)   = do newFilename <- aFilename `notIn` existing        let newPath = path `appendPath` newFilename@@ -175,11 +195,11 @@   where       existing = map fst $ filterFiles $ dirContent dir -aRmFileP :: forall wX wY . AnchoredPath   -- ^ Path of an empty file-                          -> Prim wX wY+aRmFileP :: forall prim wX wY . PrimPatch prim => AnchoredPath   -- ^ Path of an empty file+                          -> prim wX wY aRmFileP path = rmfile (ap2fp path) -anAddDirP :: forall wX wY . (AnchoredPath,Dir) -> Gen (Prim wX wY)+anAddDirP :: forall prim wX wY . PrimPatch prim => (AnchoredPath,Dir) -> Gen (prim wX wY) anAddDirP (path,dir)   = do newDirname <- aDirname `notIn` existing        let newPath = path `appendPath` newDirname@@ -187,11 +207,11 @@   where       existing = map fst $ filterDirs $ dirContent dir -aRmDirP :: forall wX wY . AnchoredPath    -- ^ Path of an empty directory-                        -> Prim wX wY+aRmDirP :: forall prim wX wY . PrimPatch prim => AnchoredPath    -- ^ Path of an empty directory+                        -> prim wX wY aRmDirP path = rmdir (ap2fp path) -aMoveP :: forall wX wY . Gen Name -> AnchoredPath -> (AnchoredPath,Dir) -> Gen (Prim wX wY)+aMoveP :: forall prim wX wY . PrimPatch prim => Gen Name -> AnchoredPath -> (AnchoredPath,Dir) -> Gen (prim wX wY) aMoveP nameGen oldPath (dirPath,dir)   = do newName <- nameGen `notIn` existing        let newPath = dirPath `appendPath` newName@@ -199,8 +219,9 @@   where       existing = map fst $ dirContent dir --- | Generates any type of 'Prim' patch, except binary and setpref patches.-aPrim :: forall wX wY . V1Model wX -> Gen (WithEndState V1Model (Prim wX) wY)+-- | Generates any type of 'prim' patch, except binary and setpref patches.+aPrim :: forall prim wX wY . (PrimPatch prim, ApplyState prim ~ RepoState V1Model)+      => V1Model wX -> Gen (WithEndState V1Model (prim wX) wY) aPrim repo   = do mbFile <- maybeOf repoFiles        mbEmptyFile <- maybeOf $ filter (isEmpty . snd) repoFiles@@ -266,7 +287,7 @@ -- *** Pairs of primitive patches  -- Try to generate commutable pairs of hunks-hunkPairP :: forall wX wY . (AnchoredPath,File) -> Gen ((Prim :> Prim) wX wY)+hunkPairP :: forall prim wX wY . PrimPatch prim => (AnchoredPath,File) -> Gen ((prim :> prim) wX wY) hunkPairP (path,file)   = do h1@(Hunk l1 old1 new1) <- aHunk content        (delta, content') <- selectChunk h1 content@@ -284,7 +305,7 @@             suffix = (start + length new, drop (start + length old) content_)       selectChunk _ _ = impossible -aPrimPair :: forall wX wY . V1Model wX -> Gen (WithEndState V1Model ((Prim :> Prim) wX) wY)+aPrimPair :: forall prim wX wY . (PrimPatch prim, ArbitraryState V1Model prim, ApplyState prim ~ RepoState V1Model) => V1Model wX -> Gen (WithEndState V1Model ((prim :> prim) wX) wY) aPrimPair repo   = do mbFile <- maybeOf repoFiles        frequency@@ -337,66 +358,143 @@ ourSmallRepo :: Gen (V1Model wX) ourSmallRepo = aSmallRepo -instance ArbitraryState V1Model Prim where+instance ArbitraryState V1Model Prim1 where   arbitraryState s = seal <$> aPrim s +instance ArbitraryState V1Model Prim2 where+  arbitraryState s = seal <$> aPrim s -instance Arbitrary (Sealed2 Prim) where++instance Arbitrary (Sealed (Prim1 wA)) where+  arbitrary = makeSGen ourSmallRepo++instance Arbitrary (Sealed (Prim2 wA)) where+  arbitrary = makeSGen ourSmallRepo++instance Arbitrary (Sealed2 Prim1) where   arbitrary = makeS2Gen ourSmallRepo -instance Arbitrary (Sealed2 (Prim :> Prim)) where+instance Arbitrary (Sealed2 Prim2) where+  arbitrary = makeS2Gen ourSmallRepo++arbitrarySeal2 :: (PrimPatch prim, ApplyState prim ~ UT.Tree,+                   ArbitraryState V1Model prim)+               => Gen (Sealed2 (prim :> prim))+arbitrarySeal2 = do+  repo <- ourSmallRepo+  WithEndState pp _ <- aPrimPair repo+  return $ seal2 pp++arbitrarySeal :: (PrimPatch prim, ApplyState prim ~ UT.Tree,+                  ArbitraryState V1Model prim)+              => Gen (Sealed ((:>) prim prim wX))+arbitrarySeal = do+  repo <- ourSmallRepo+  WithEndState pp _ <- aPrimPair repo+  return $ seal pp++instance Arbitrary (Sealed2 (Prim1 :> Prim1)) where+  arbitrary = arbitrarySeal2++instance Arbitrary (Sealed2 (Prim2 :> Prim2)) where+  arbitrary = arbitrarySeal2++instance Arbitrary (Sealed ((Prim1 :> Prim1) wA)) where+  arbitrary = arbitrarySeal++instance Arbitrary (Sealed ((Prim2 :> Prim2) wA)) where+  arbitrary = arbitrarySeal++instance Arbitrary (Sealed2 (Prim1 :> Prim1 :> Prim1)) where+  arbitrary = makeS2Gen ourSmallRepo++instance Arbitrary (Sealed ((Prim1 :> Prim1 :> Prim1) a)) where+  arbitrary = makeSGen ourSmallRepo++instance Arbitrary (Sealed2 (FL Prim1)) where+  arbitrary = makeS2Gen ourSmallRepo++instance Arbitrary (Sealed ((FL Prim1) wA)) where+  arbitrary = makeSGen ourSmallRepo++instance Arbitrary (Sealed2 (FL Prim1 :> FL Prim1)) where+  arbitrary = makeS2Gen ourSmallRepo++instance Arbitrary (Sealed ((FL Prim1 :> FL Prim1) wA)) where+  arbitrary = makeSGen ourSmallRepo++instance Arbitrary (Sealed2 (WithState V1Model Prim1)) where+  arbitrary = makeWS2Gen ourSmallRepo++instance Arbitrary (Sealed (WithState V1Model Prim1 wA)) where+  arbitrary = makeWSGen ourSmallRepo++instance Arbitrary (Sealed (WithState V1Model (FL Prim1) wA)) where+  arbitrary = makeWSGen ourSmallRepo++instance Arbitrary (Sealed2 (WithState V1Model (Prim1 :> Prim1))) where   arbitrary = do repo <- ourSmallRepo-                 WithEndState pp _ <- aPrimPair repo-                 return $ seal2 pp+                 WithEndState pp repo' <- aPrimPair repo+                 return $ seal2 $ WithState repo pp repo' -instance Arbitrary (Sealed ((Prim :> Prim) wA)) where+instance Arbitrary (Sealed (WithState V1Model (Prim1 :> Prim1) a)) where   arbitrary = do repo <- ourSmallRepo-                 WithEndState pp _ <- aPrimPair repo-                 return $ seal pp+                 WithEndState pp repo' <- aPrimPair repo+                 return $ seal $ WithState repo pp repo' -instance Arbitrary (Sealed2 (Prim :> Prim :> Prim)) where++instance Arbitrary (Sealed2 (WithState V1Model (FL Prim1))) where+  arbitrary = makeWS2Gen ourSmallRepo++instance Arbitrary (Sealed2 (WithState V1Model (FL Prim1 :> FL Prim1))) where+  arbitrary = makeWS2Gen ourSmallRepo++instance Arbitrary (Sealed (WithState V1Model (FL Prim1 :> FL Prim1) a)) where+  arbitrary = makeWSGen ourSmallRepo++instance Arbitrary (Sealed2 (Prim2 :> Prim2 :> Prim2)) where   arbitrary = makeS2Gen ourSmallRepo -instance Arbitrary (Sealed ((Prim :> Prim :> Prim) a)) where+instance Arbitrary (Sealed ((Prim2 :> Prim2 :> Prim2) a)) where   arbitrary = makeSGen ourSmallRepo -instance Arbitrary (Sealed2 (FL Prim)) where+instance Arbitrary (Sealed2 (FL Prim2)) where   arbitrary = makeS2Gen ourSmallRepo -instance Arbitrary (Sealed ((FL Prim) wA)) where+instance Arbitrary (Sealed ((FL Prim2) wA)) where   arbitrary = makeSGen ourSmallRepo -instance Arbitrary (Sealed2 (FL Prim :> FL Prim)) where+instance Arbitrary (Sealed2 (FL Prim2 :> FL Prim2)) where   arbitrary = makeS2Gen ourSmallRepo -instance Arbitrary (Sealed ((FL Prim :> FL Prim) wA)) where+instance Arbitrary (Sealed ((FL Prim2 :> FL Prim2) wA)) where   arbitrary = makeSGen ourSmallRepo -instance Arbitrary (Sealed2 (WithState V1Model Prim)) where+instance Arbitrary (Sealed2 (WithState V1Model Prim2)) where   arbitrary = makeWS2Gen ourSmallRepo -instance Arbitrary (Sealed (WithState V1Model Prim wA)) where+instance Arbitrary (Sealed (WithState V1Model Prim2 wA)) where   arbitrary = makeWSGen ourSmallRepo -instance Arbitrary (Sealed (WithState V1Model (FL Prim) wA)) where+instance Arbitrary (Sealed (WithState V1Model (FL Prim2) wA)) where   arbitrary = makeWSGen ourSmallRepo -instance Arbitrary (Sealed2 (WithState V1Model (Prim :> Prim))) where+instance Arbitrary (Sealed2 (WithState V1Model (Prim2 :> Prim2))) where   arbitrary = do repo <- ourSmallRepo                  WithEndState pp repo' <- aPrimPair repo                  return $ seal2 $ WithState repo pp repo' -instance Arbitrary (Sealed (WithState V1Model (Prim :> Prim) a)) where+instance Arbitrary (Sealed (WithState V1Model (Prim2 :> Prim2) a)) where   arbitrary = do repo <- ourSmallRepo                  WithEndState pp repo' <- aPrimPair repo                  return $ seal $ WithState repo pp repo'  -instance Arbitrary (Sealed2 (WithState V1Model (FL Prim))) where+instance Arbitrary (Sealed2 (WithState V1Model (FL Prim2))) where   arbitrary = makeWS2Gen ourSmallRepo -instance Arbitrary (Sealed2 (WithState V1Model (FL Prim :> FL Prim))) where+instance Arbitrary (Sealed2 (WithState V1Model (FL Prim2 :> FL Prim2))) where   arbitrary = makeWS2Gen ourSmallRepo -instance Arbitrary (Sealed (WithState V1Model (FL Prim :> FL Prim) a)) where+instance Arbitrary (Sealed (WithState V1Model (FL Prim2 :> FL Prim2) a)) where   arbitrary = makeWSGen ourSmallRepo
harness/Darcs/Test/Patch/Arbitrary/RepoPatchV1.hs view
@@ -15,20 +15,16 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE CPP, FlexibleInstances, TypeSynonymInstances #-}-+{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}  module Darcs.Test.Patch.Arbitrary.RepoPatchV1 () where  import Prelude () import Darcs.Prelude -import System.IO.Unsafe ( unsafePerformIO ) import Test.QuickCheck import Control.Monad ( liftM, liftM2, liftM3, liftM4, replicateM ) -import Darcs.Patch.Info ( PatchInfo, patchinfo ) import qualified Data.ByteString as B ( ByteString ) import qualified Data.ByteString.Char8 as BC ( pack ) @@ -36,8 +32,8 @@                      hunk, tokreplace, binary,                      changepref, invert, merge ) import Darcs.Patch.V1 ()-import qualified Darcs.Patch.V1.Core as V1 ( RepoPatchV1(..) )-import Darcs.Patch.Prim.V1 ()+import Darcs.Patch.V1.Core ( RepoPatchV1(..) )+import qualified Darcs.Patch.V1.Prim as V1 ( Prim(..) ) import Darcs.Patch.Prim.V1.Core ( Prim(..) ) import Darcs.Patch.Witnesses.Ordered import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed), unseal, mapSeal, Sealed2(..) )@@ -49,9 +45,10 @@ import Darcs.Test.Patch.Properties.Check( checkAPatch ) import Darcs.Test.Patch.Arbitrary.Generic ( MightHaveDuplicate ) -#include "impossible.h"+type Patch = RepoPatchV1 V1.Prim -type Patch = V1.RepoPatchV1 Prim+pp :: Prim wX wY -> Patch wX wY+pp = PP . V1.Prim  class ArbitraryP p where     arbitraryP :: Gen (Sealed (p wX))@@ -112,7 +109,7 @@ instance ArbitraryP Prim where     arbitraryP = onepatchgen -instance MightHaveDuplicate (V1.RepoPatchV1 prim)+instance MightHaveDuplicate (RepoPatchV1 prim)  hunkgen :: Gen (Sealed (Prim wX)) hunkgen = do@@ -165,25 +162,18 @@ onepatchgen = oneof [simplepatchgen, mapSeal (invert . unsafeCoerceP) `fmap` simplepatchgen]  norecursgen :: Int -> Gen (Sealed (FL Patch wX))-norecursgen 0 = mapSeal (\p -> V1.PP p :>: NilFL) `fmap` onepatchgen-norecursgen n = oneof [mapSeal (\p -> V1.PP p :>: NilFL) `fmap` onepatchgen,flatcompgen n]+norecursgen 0 = mapSeal (\p -> pp p :>: NilFL) `fmap` onepatchgen+norecursgen n = oneof [mapSeal (\p -> pp p :>: NilFL) `fmap` onepatchgen,flatcompgen n]  arbpatch :: Int -> Gen (Sealed (FL Patch wX))-arbpatch 0 = mapSeal (\p -> V1.PP p :>: NilFL) `fmap` onepatchgen-arbpatch n = frequency [(3,mapSeal (\p -> V1.PP p :>: NilFL) `fmap` onepatchgen),+arbpatch 0 = mapSeal (\p -> pp p :>: NilFL) `fmap` onepatchgen+arbpatch n = frequency [(3,mapSeal (\p -> pp p :>: NilFL) `fmap` onepatchgen),                         (2,flatcompgen n),                         (0,rawMergeGen n),                         (0,mergegen n),-                        (1,mapSeal (\p -> V1.PP p :>: NilFL) `fmap` onepatchgen)+                        (1,mapSeal (\p -> pp p :>: NilFL) `fmap` onepatchgen)                        ] --- | Generate an arbitrary list of at least one element-unempty :: Arbitrary a => Gen [a]-unempty = do-  a <- arbitrary-  as <- arbitrary-  return (a:as)- rawMergeGen :: Int -> Gen (Sealed (FL Patch wX)) rawMergeGen n =   do Sealed p1 <- arbpatch len                      Sealed p2 <- arbpatch len@@ -208,16 +198,6 @@      else mergegen n   where len = if n < 15 then n`div`3 else 3 -arbpi :: Gen PatchInfo-arbpi = do n <- unempty-           a <- unempty-           l <- unempty-           d <- unempty-           return $ unsafePerformIO $ patchinfo n d a l--instance Arbitrary PatchInfo where-    arbitrary = arbpi- instance Arbitrary B.ByteString where     arbitrary = liftM BC.pack arbitrary @@ -225,7 +205,7 @@ flatlistgen 0 = return $ Sealed NilFL flatlistgen n = do Sealed x <- onepatchgen                    Sealed xs <- flatlistgen (n-1)-                   return (Sealed (V1.PP x :>: xs))+                   return (Sealed (pp x :>: xs))  flatcompgen :: Int -> Gen (Sealed (FL Patch wX)) flatcompgen n = do
harness/Darcs/Test/Patch/Arbitrary/RepoPatchV2.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE UndecidableInstances #-} module Darcs.Test.Patch.Arbitrary.RepoPatchV2 where import Darcs.Test.Patch.Arbitrary.Generic@@ -7,7 +6,7 @@  import Darcs.Patch.Witnesses.Ordered import Darcs.Patch.Merge ( Merge(..) )-import Darcs.Patch.Patchy ( Patchy, Commute(..) )+import Darcs.Patch.Commute ( Commute(..) ) import Darcs.Patch.Prim ( PrimPatch, anIdentity ) import Darcs.Patch.V2 ( RepoPatchV2 ) import Darcs.Patch.V2.RepoPatch ( isDuplicate )@@ -22,7 +21,7 @@ nontrivialRepoPatchV2s :: PrimPatch prim => (RepoPatchV2 prim :> RepoPatchV2 prim) wX wY -> Bool nontrivialRepoPatchV2s = nontrivialCommute -nontrivialCommute :: (Patchy p, MyEq p) => (p :> p) wX wY -> Bool+nontrivialCommute :: (Commute p, Eq2 p) => (p :> p) wX wY -> Bool nontrivialCommute (x :> y) = case commute (x :> y) of                               Just (y' :> x') -> not (y' `unsafeCompare` y) ||                                                  not (x' `unsafeCompare` x)@@ -31,7 +30,7 @@ nontrivialMergerepoPatchV2s :: PrimPatch prim => (RepoPatchV2 prim :\/: RepoPatchV2 prim) wX wY -> Bool nontrivialMergerepoPatchV2s = nontrivialMerge -nontrivialMerge :: (Patchy p, MyEq p, Merge p) => (p :\/: p) wX wY -> Bool+nontrivialMerge :: (Eq2 p, Merge p) => (p :\/: p) wX wY -> Bool nontrivialMerge (x :\/: y) = case merge (x :\/: y) of                               y' :/\: x' -> not (y' `unsafeCompare` y) ||                                             not (x' `unsafeCompare` x)
harness/Darcs/Test/Patch/Check.hs view
@@ -15,7 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-} module Darcs.Test.Patch.Check ( PatchCheck(), doCheck, fileExists, dirExists,                                 removeFile, removeDir, createFile, createDir,                                 insertLine, deleteLine, isValid, doVerboseCheck,@@ -23,6 +22,9 @@                                 checkMove, modifyFile, FileContents(..)                               ) where +import Prelude ()+import Darcs.Prelude+ import System.IO.Unsafe ( unsafePerformIO ) import qualified Data.ByteString as B (ByteString) import Data.List ( isPrefixOf, inits )@@ -32,8 +34,6 @@ import Data.Map ( Map ) import qualified Data.Map as M ( mapKeys, delete, insert, empty, lookup, null ) import System.FilePath ( joinPath, splitDirectories )--#include "impossible.h"  -- | File contents are represented by a map from line numbers to line contents. --   If for a certain line number, the line contents are Nothing, that means
harness/Darcs/Test/Patch/Examples/Set1.hs view
@@ -15,9 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# OPTIONS_GHC -fno-warn-orphans -fno-warn-deprecations #-}-{-# LANGUAGE CPP #-}- module Darcs.Test.Patch.Examples.Set1        ( knownCommutes, knownCantCommutes, knownMerges        , knownMergeEquivs, knownCanons, mergePairs2@@ -25,6 +22,8 @@        , primitiveTestPatches, testPatches, testPatchesNamed        , primitiveCommutePairs ) where +import Prelude ()+import Darcs.Prelude import System.IO.Unsafe ( unsafePerformIO ) import qualified Data.ByteString.Char8 as BC ( pack ) import qualified Data.ByteString as B ( empty )@@ -34,16 +33,14 @@      , readPatch, fromPrim      , adddir, addfile, hunk, binary, rmdir, rmfile, tokreplace ) import Darcs.Patch.Prim ( PrimOf, FromPrim )-import Darcs.Patch.Prim.V1 ( Prim ) import qualified Darcs.Patch.V1 as V1 ( RepoPatchV1 )+import qualified Darcs.Patch.V1.Prim as V1 ( Prim(..) ) import Darcs.Test.Patch.Properties.Check( checkAPatch ) import Darcs.Patch.Witnesses.Ordered import Darcs.Patch.Witnesses.Sealed ( unsafeUnseal ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP, unsafeCoercePEnd ) -#include "impossible.h"--type Patch = V1.RepoPatchV1 Prim+type Patch = V1.RepoPatchV1 V1.Prim  -- The unit tester function is really just a glorified map for functions that -- return lists, in which the lists get concatenated (where map would end up@@ -86,7 +83,7 @@      (quickhunk 1 "abcde" "cde" :>: NilFL, quickhunk 1 "ab" "" :>: NilFL),      (quickhunk 1 "abcde" "acde" :>: NilFL, quickhunk 2 "b" "" :>: NilFL)] -quickhunk :: (FromPrim p, PrimOf p ~ Prim) => Int -> String -> String -> p wX wY+quickhunk :: (FromPrim p, PrimOf p ~ V1.Prim) => Int -> String -> String -> p wX wY quickhunk l o n = fromPrim $ hunk "test" l (map (\c -> BC.pack [c]) o)                                              (map (\c -> BC.pack [c]) n) 
harness/Darcs/Test/Patch/Examples/Set2Unwitnessed.hs view
@@ -15,10 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# OPTIONS_GHC -fno-warn-deprecations -fno-warn-orphans #-}-{-# LANGUAGE CPP #-}-- module Darcs.Test.Patch.Examples.Set2Unwitnessed        ( primPermutables, primPatches        , commutables, commutablesFL@@ -30,11 +26,9 @@ import qualified Data.ByteString.Char8 as BC ( pack ) import Darcs.Patch.Witnesses.Sealed import Darcs.Patch ( invert, hunk )-import Darcs.Patch.Patchy ( Invert(..) )-import Darcs.Patch.Prim ( PrimPatch )-import Darcs.Patch.Prim.V1 ( Prim )+import Darcs.Patch.Invert ( Invert(..) )+import Darcs.Patch.Prim ( PrimPatch, fromPrim ) import Darcs.Patch.V2 ( RepoPatchV2 )-import Darcs.Patch.V2.RepoPatch ( prim2repopatchV2 ) -- import Darcs.Test.Patch.Test () -- for instance Eq Patch -- import Darcs.Test.Patch.Examples.Set2Unwitnessed import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )@@ -45,14 +39,14 @@ import Darcs.Util.Printer.Color () -- for instance Show Doc import Darcs.Test.Patch.WSub + import qualified Darcs.Patch.Witnesses.Ordered as W ( (:>), (:\/:) ) import qualified Data.ByteString as B ( ByteString ) import Darcs.Test.Patch.V1Model ( V1Model, Content                                 , makeRepo, makeFile) import Darcs.Test.Patch.WithState ( WithStartState(..) )-import Darcs.Patch.Prim.V1.Core ( Prim(FP), FilePatchType(Hunk) )-import Darcs.Util.Path ( FileName, fp2fn, makeName )-import Darcs.Patch.Prim ( PrimPatchBase(..), FromPrim )+import Darcs.Util.Path ( makeName )+import Darcs.Patch.Prim ( PrimPatchBase(..), FromPrim, PrimConstruct(..) ) import Darcs.Patch.Merge ( Merge ) import Darcs.Test.Patch.Arbitrary.Generic     ( Tree(..)@@ -63,209 +57,210 @@     )  -- import Debug.Trace--- #include "impossible.h" +type Patch = RepoPatchV2 Prim2+ makeSimpleRepo :: String -> Content -> V1Model wX makeSimpleRepo filename content = makeRepo [(makeName filename, makeFile content)]  -w_tripleExamples :: (FromPrim p, Merge p, Invert p, PrimPatchBase p, PrimOf p ~ Prim) => [Sealed2 (p W.:> p W.:> p)]+w_tripleExamples :: (FromPrim p, Merge p, Invert p, PrimPatchBase p, PrimConstruct (PrimOf p)) => [Sealed2 (p W.:> p W.:> p)] w_tripleExamples = [commuteTripleFromTree seal2 $                    WithStartState (makeSimpleRepo "file" [])                    (ParTree-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "g"]))-                     (SeqTree (FP (fp2fn "./file") (Hunk 2 [] [BC.pack "j"]))-                      (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "s"])) NilTree)))-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "e"])) NilTree))+                    (SeqTree (hunk "file" 1 [] [BC.pack "g"])+                     (SeqTree (hunk "file" 2 [] [BC.pack "j"])+                      (SeqTree (hunk "file" 1 [] [BC.pack "s"]) NilTree)))+                    (SeqTree (hunk "file" 1 [] [BC.pack "e"]) NilTree))                   ,commuteTripleFromTree seal2 $                    WithStartState (makeSimpleRepo "file" [BC.pack "j"])                    (ParTree-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "s"]))+                    (SeqTree (hunk "file" 1 [] [BC.pack "s"])                      (ParTree-                      (SeqTree (FP (fp2fn "./file") (Hunk 2 [BC.pack "j"] [])) NilTree)-                      (SeqTree (FP (fp2fn "./file") (Hunk 2 [BC.pack "j"] [])) NilTree)))-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "j"] [])) NilTree))+                      (SeqTree (hunk "file" 2 [BC.pack "j"] []) NilTree)+                      (SeqTree (hunk "file" 2 [BC.pack "j"] []) NilTree)))+                    (SeqTree (hunk "file" 1 [BC.pack "j"] []) NilTree))                   ]  -w_mergeExamples :: (FromPrim p, Merge p, Invert p, PrimPatchBase p, PrimOf p ~ Prim) => [Sealed2 (p W.:\/: p)]+w_mergeExamples :: (FromPrim p, Merge p, Invert p, PrimPatchBase p, PrimConstruct (PrimOf p)) => [Sealed2 (p W.:\/: p)] w_mergeExamples = map (unseal2 (mergePairFromCommutePair seal2)) w_commuteExamples -w_commuteExamples :: (FromPrim p, Merge p, PrimPatchBase p, PrimOf p ~ Prim) => [Sealed2 (p W.:> p)]+w_commuteExamples :: (FromPrim p, Merge p, PrimPatchBase p, PrimConstruct (PrimOf p)) => [Sealed2 (p W.:> p)] w_commuteExamples = [                    commutePairFromTWFP seal2 $                    WithStartState (makeSimpleRepo "file" [])                    (TWFP 3                     (ParTree-                     (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "h"])) NilTree)-                     (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "b"]))-                       (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "f"]))-                         (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "v"]))-                           (SeqTree (FP (fp2fn "./file") (Hunk 2 [BC.pack "f"] [])) NilTree)))))),+                     (SeqTree (hunk "file" 1 [] [BC.pack "h"]) NilTree)+                     (SeqTree (hunk "file" 1 [] [BC.pack "b"])+                       (SeqTree (hunk "file" 1 [] [BC.pack "f"])+                         (SeqTree (hunk "file" 1 [] [BC.pack "v"])+                           (SeqTree (hunk "file" 2 [BC.pack "f"] []) NilTree)))))),                    commutePairFromTWFP seal2 $                    WithStartState                    (makeSimpleRepo "file" [BC.pack "f",BC.pack "s",BC.pack "d"])                    (TWFP 3                     (ParTree-                     (SeqTree (FP (fp2fn "./file") (Hunk 3 [BC.pack "d"] [])) NilTree)+                     (SeqTree (hunk "file" 3 [BC.pack "d"] []) NilTree)                      (ParTree-                      (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "f"] [])) NilTree)-                      (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "f"] []))-                        (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "s",BC.pack "d"] []))-                          (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "v"])) NilTree)))))),+                      (SeqTree (hunk "file" 1 [BC.pack "f"] []) NilTree)+                      (SeqTree (hunk "file" 1 [BC.pack "f"] [])+                        (SeqTree (hunk "file" 1 [BC.pack "s",BC.pack "d"] [])+                          (SeqTree (hunk "file" 1 [] [BC.pack "v"]) NilTree)))))), {-                   commutePairFromTWFP seal2 $                    WithStartState                    (makeSimpleRepo "file" [BC.pack "f",BC.pack "u",                                             BC.pack "s",BC.pack "d"])                    (TWFP 5                     (ParTree-                     (SeqTree (FP (fp2fn "./file") (Hunk 5 [] [BC.pack "x"]))-                      (SeqTree (FP (fp2fn "./file") (Hunk 4 [BC.pack "d"] [])) NilTree))+                     (SeqTree (hunk "file" 5 [] [BC.pack "x"])+                      (SeqTree (hunk "file" 4 [BC.pack "d"] []) NilTree))                      (ParTree-                      (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "f",BC.pack "u"] [])) NilTree)-                      (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "f"] []))-                       (SeqTree (FP(fp2fn "./file") (Hunk 1 [BC.pack "u",BC.pack "s",BC.pack "d"] []))-                        (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "a"]))-                         (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "a"] [])) NilTree))))))),-}+                      (SeqTree (hunk "file" 1 [BC.pack "f",BC.pack "u"] []) NilTree)+                      (SeqTree (hunk "file" 1 [BC.pack "f"] [])+                       (SeqTree (hunk "file" 1 [BC.pack "u",BC.pack "s",BC.pack "d"] [])+                        (SeqTree (hunk "file" 1 [] [BC.pack "a"])+                         (SeqTree (hunk "file" 1 [BC.pack "a"] []) NilTree))))))),-}                    commutePairFromTree seal2 $                    WithStartState (makeSimpleRepo "file" [BC.pack "n",BC.pack "t",BC.pack "h"])                    (ParTree-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "n",BC.pack "t",BC.pack "h"] []))+                    (SeqTree (hunk "file" 1 [BC.pack "n",BC.pack "t",BC.pack "h"] [])                      NilTree)-                    (SeqTree (FP (fp2fn "./file") (Hunk 3 [BC.pack "h"] []))-                     (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "n"] []))-                      (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "t"] [])) NilTree)))),+                    (SeqTree (hunk "file" 3 [BC.pack "h"] [])+                     (SeqTree (hunk "file" 1 [BC.pack "n"] [])+                      (SeqTree (hunk "file" 1 [BC.pack "t"] []) NilTree)))),                   commutePairFromTree seal2 $                   WithStartState (makeSimpleRepo "file" [])                   (ParTree-                   (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "n"])) NilTree)-                   (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "i"]))-                                (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "i"])) NilTree))),+                   (SeqTree (hunk "file" 1 [] [BC.pack "n"]) NilTree)+                   (SeqTree (hunk "file" 1 [] [BC.pack "i"])+                                (SeqTree (hunk "file" 1 [] [BC.pack "i"]) NilTree))),                   commutePairFromTree seal2 $                   WithStartState (makeSimpleRepo "file" [])                   (ParTree-                   (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "c"]))+                   (SeqTree (hunk "file" 1 [] [BC.pack "c"])                      (ParTree-                       (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "c"] [BC.pack "r"])) NilTree)-                       (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "h"]))-                        (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "d"])) NilTree))))-                   (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "f"])) NilTree)),+                       (SeqTree (hunk "file" 1 [BC.pack "c"] [BC.pack "r"]) NilTree)+                       (SeqTree (hunk "file" 1 [] [BC.pack "h"])+                        (SeqTree (hunk "file" 1 [] [BC.pack "d"]) NilTree))))+                   (SeqTree (hunk "file" 1 [] [BC.pack "f"]) NilTree)),                   commutePairFromTWFP seal2 $                   WithStartState (makeSimpleRepo "file" [])                   (TWFP 1                   (ParTree                    (ParTree-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "t"])) NilTree)-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "t"])) NilTree))-                   (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "f"])) NilTree))),+                    (SeqTree (hunk "file" 1 [] [BC.pack "t"]) NilTree)+                    (SeqTree (hunk "file" 1 [] [BC.pack "t"]) NilTree))+                   (SeqTree (hunk "file" 1 [] [BC.pack "f"]) NilTree))),                    commutePairFromTWFP seal2 $                    WithStartState (makeSimpleRepo "file" [BC.pack "f",BC.pack " r",                                                             BC.pack "c",BC.pack "v"])                    (TWFP 4                     (ParTree-                     (SeqTree (FP (fp2fn "./file") (Hunk 3 [BC.pack "c",BC.pack "v"] []))+                     (SeqTree (hunk "file" 3 [BC.pack "c",BC.pack "v"] [])                         (ParTree-                         (SeqTree (FP (fp2fn "./file") (Hunk 2 [BC.pack "r"] []))-                          (SeqTree (FP (fp2fn "fi le") (Hunk 1 [BC.pack "f"] [])) NilTree))-                         (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "f",BC.pack "r"] []))-                          (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "y"])) NilTree))))-                     (SeqTree (FP (fp2fn "./file") (Hunk 4 [BC.pack "v"] [])) NilTree))),+                         (SeqTree (hunk "file" 2 [BC.pack "r"] [])+                          (SeqTree (hunk "fi le" 1 [BC.pack "f"] []) NilTree))+                         (SeqTree (hunk "file" 1 [BC.pack "f",BC.pack "r"] [])+                          (SeqTree (hunk "file" 1 [] [BC.pack "y"]) NilTree))))+                     (SeqTree (hunk "file" 4 [BC.pack "v"] []) NilTree))),                    commutePairFromTree seal2 $                    WithStartState (makeSimpleRepo "file" [])                    (ParTree-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "z"])) NilTree)+                    (SeqTree (hunk "file" 1 [] [BC.pack "z"]) NilTree)                     (ParTree-                     (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "f"])) NilTree)+                     (SeqTree (hunk "file" 1 [] [BC.pack "f"]) NilTree)                      (ParTree-                      (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "r"])) NilTree)-                      (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "d"])) NilTree))))+                      (SeqTree (hunk "file" 1 [] [BC.pack "r"]) NilTree)+                      (SeqTree (hunk "file" 1 [] [BC.pack "d"]) NilTree))))                  , commutePairFromTree seal2 $                    WithStartState (makeSimpleRepo "file" [BC.pack "t",BC.pack "r",BC.pack "h"])                    (ParTree                     (ParTree-                     (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "t",BC.pack "r",BC.pack "h"] []))+                     (SeqTree (hunk "file" 1 [BC.pack "t",BC.pack "r",BC.pack "h"] [])                               NilTree)-                     (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "o"])) NilTree))-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "t"] []))-                     (SeqTree (FP (fp2fn "./file") (Hunk 2 [BC.pack "h"] [])) NilTree)))+                     (SeqTree (hunk "file" 1 [] [BC.pack "o"]) NilTree))+                    (SeqTree (hunk "file" 1 [BC.pack "t"] [])+                     (SeqTree (hunk "file" 2 [BC.pack "h"] []) NilTree)))                  , commutePairFromTWFP seal2 $                    WithStartState (makeSimpleRepo "file" []) $                    TWFP 2                    (ParTree-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "h"])) NilTree)-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "y"]))-                     (SeqTree (FP (fp2fn "./file") (Hunk 2 [] [BC.pack "m"]))-                      (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "v"])) NilTree))))+                    (SeqTree (hunk "file" 1 [] [BC.pack "h"]) NilTree)+                    (SeqTree (hunk "file" 1 [] [BC.pack "y"])+                     (SeqTree (hunk "file" 2 [] [BC.pack "m"])+                      (SeqTree (hunk "file" 1 [] [BC.pack "v"]) NilTree))))                  , commutePairFromTree seal2 $                  WithStartState (makeSimpleRepo "file" [])                  (ParTree-                  (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "p"]))-                   (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "p"] []))-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "c"])) NilTree)))-                  (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "z"])) NilTree))+                  (SeqTree (hunk "file" 1 [] [BC.pack "p"])+                   (SeqTree (hunk "file" 1 [BC.pack "p"] [])+                    (SeqTree (hunk "file" 1 [] [BC.pack "c"]) NilTree)))+                  (SeqTree (hunk "file" 1 [] [BC.pack "z"]) NilTree))                  , commutePairFromTree seal2 $                  WithStartState (makeSimpleRepo "file" [])                  (ParTree-                  (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "j" ]))-                   (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "j"] [])) NilTree))-                  (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "v"])) NilTree))+                  (SeqTree (hunk "file" 1 [] [BC.pack "j" ])+                   (SeqTree (hunk "file" 1 [BC.pack "j"] []) NilTree))+                  (SeqTree (hunk "file" 1 [] [BC.pack "v"]) NilTree))                  , commutePairFromTree seal2 $                  WithStartState (makeSimpleRepo "file" [])                  (ParTree-                  (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "v"])) NilTree)-                  (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "j" ]))-                   (SeqTree (FP (fp2fn "./file") (Hunk 1 [BC.pack "j"] [])) NilTree)))+                  (SeqTree (hunk "file" 1 [] [BC.pack "v"]) NilTree)+                  (SeqTree (hunk "file" 1 [] [BC.pack "j" ])+                   (SeqTree (hunk "file" 1 [BC.pack "j"] []) NilTree)))                  , commutePairFromTree seal2 $                  WithStartState (makeSimpleRepo "file" [BC.pack "x",BC.pack "c"])                  (ParTree-                  (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "h"]))+                  (SeqTree (hunk "file" 1 [] [BC.pack "h"])                    (ParTree-                    (SeqTree (FP (fp2fn "./file") (Hunk 3 [BC.pack "c"] [])) NilTree)-                    (SeqTree (FP (fp2fn "./file") (Hunk 2 [BC.pack "x"] []))-                     (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "j"])) NilTree))))-                  (SeqTree (FP (fp2fn "./file") (Hunk 1 [] [BC.pack "l"])) NilTree))+                    (SeqTree (hunk "file" 3 [BC.pack "c"] []) NilTree)+                    (SeqTree (hunk "file" 2 [BC.pack "x"] [])+                     (SeqTree (hunk "file" 1 [] [BC.pack "j"]) NilTree))))+                  (SeqTree (hunk "file" 1 [] [BC.pack "l"]) NilTree))                  , commutePairFromTree seal2 $                  WithStartState (makeSimpleRepo "file" [])                  (ParTree-                  (SeqTree (FP (fp2fn "./file") (Hunk 1 [] (packStringLetters "s"))) NilTree)-                  (SeqTree (FP (fp2fn "./file") (Hunk 1 [] (packStringLetters "k")))-                   (SeqTree (FP (fp2fn "./file") (Hunk 1 (packStringLetters "k") []))-                    (SeqTree (FP (fp2fn "./file") (Hunk 1 [] (packStringLetters "m")))-                     (SeqTree (FP (fp2fn "./file") (Hunk 1 (packStringLetters "m") [])) NilTree)))))+                  (SeqTree (hunk "file" 1 [] (packStringLetters "s")) NilTree)+                  (SeqTree (hunk "file" 1 [] (packStringLetters "k"))+                   (SeqTree (hunk "file" 1 (packStringLetters "k") [])+                    (SeqTree (hunk "file" 1 [] (packStringLetters "m"))+                     (SeqTree (hunk "file" 1 (packStringLetters "m") []) NilTree)))))                  ]  packStringLetters :: String -> [B.ByteString] packStringLetters = map (BC.pack . (:[])) -w_repov2PatchLoopExamples :: [Sealed (WithStartState V1Model (Tree Prim))]+w_repov2PatchLoopExamples :: [Sealed (WithStartState V1Model (Tree Prim2))] w_repov2PatchLoopExamples =-    [Sealed (WithStartState (makeSimpleRepo fx_name [])+    [Sealed (WithStartState (makeSimpleRepo fx [])      $ canonizeTree      (ParTree-      (SeqTree (FP fx (Hunk 1 [] (packStringLetters "pkotufogbvdabnmbzajvolwviqebieonxvcvuvigkfgybmqhzuaaurjspd")))+      (SeqTree (hunk fx 1 [] (packStringLetters "pkotufogbvdabnmbzajvolwviqebieonxvcvuvigkfgybmqhzuaaurjspd"))        (ParTree-        (SeqTree (FP fx (Hunk 47 (packStringLetters "qhzu") (packStringLetters "zafybdcokyjskcgnvhkbzpysaafnjjhcstgrczplxsfwagmh")))+        (SeqTree (hunk fx 47 (packStringLetters "qhzu") (packStringLetters "zafybdcokyjskcgnvhkbzpysaafnjjhcstgrczplxsfwagmh"))          (ParTree           (ParTree            NilTree            (ParTree             (ParTree              (ParTree-              (SeqTree (FP fx (Hunk 15 (packStringLetters "mbzajvolwviqebieonxvcvuvigkfgyb") (packStringLetters "vujnxnhvybvpouyciaabszfmgssezlwwjgnethvrpnfrkubphzvdgymjjoacppqps")))+              (SeqTree (hunk fx 15 (packStringLetters "mbzajvolwviqebieonxvcvuvigkfgyb") (packStringLetters "vujnxnhvybvpouyciaabszfmgssezlwwjgnethvrpnfrkubphzvdgymjjoacppqps"))                (ParTree                 NilTree                 (ParTree-                 (SeqTree (FP fx (Hunk 40 (packStringLetters "ssezlwwjgnethvrpnfrkubphzvdgymjjoacppqpsmzafybdcokyjskcgnvhkbz") (packStringLetters "wnesidpccwoiqiichxaaejdsyrhrusqljlcoro")))+                 (SeqTree (hunk fx 40 (packStringLetters "ssezlwwjgnethvrpnfrkubphzvdgymjjoacppqpsmzafybdcokyjskcgnvhkbz") (packStringLetters "wnesidpccwoiqiichxaaejdsyrhrusqljlcoro"))                   (ParTree                    (ParTree-                    (SeqTree (FP fx (Hunk 12 (packStringLetters "abnvujnxnhvybvpouyciaabszfmgwnesidpccwoiqii") (packStringLetters "czfdhqkipdstfjycqaxwnbxrihrufdeyneqiiiafwzlmg"))) NilTree)+                    (SeqTree (hunk fx 12 (packStringLetters "abnvujnxnhvybvpouyciaabszfmgwnesidpccwoiqii") (packStringLetters "czfdhqkipdstfjycqaxwnbxrihrufdeyneqiiiafwzlmg")) NilTree)                     NilTree)                    NilTree))-                 (SeqTree (FP fx (Hunk 25 [] (packStringLetters "dihgmsotezucqdgxczvcivijootyvhlwymbiueufnvpwpeukmskqllalfe"))) NilTree))))-              (SeqTree (FP fx (Hunk 56 (packStringLetters "yjskcgnvhkbzpysaafnjjhcstgrczplxsfwagmhaaurjsp") (packStringLetters "xldhrutyhcyaqeezwujiguawfyawjjqlirxshjddvq"))) NilTree))-             (SeqTree (FP fx (Hunk 20 [] (packStringLetters "ooygwiyogqrqnytixqtmvdxx")))-              (SeqTree (FP fx (Hunk 26 (packStringLetters "yogqrqnytixqtmvdxxvolwviqebieonxvcvuvigkfgybmzafybdcokyjskcgnvhkbz") (packStringLetters "akhsmlbkdxnvfoikmiatfbpzdrsyykkpoxvvddeaspzxe")))-               (SeqTree (FP fx (Hunk 39 [] (packStringLetters "ji")))+                 (SeqTree (hunk fx 25 [] (packStringLetters "dihgmsotezucqdgxczvcivijootyvhlwymbiueufnvpwpeukmskqllalfe")) NilTree))))+              (SeqTree (hunk fx 56 (packStringLetters "yjskcgnvhkbzpysaafnjjhcstgrczplxsfwagmhaaurjsp") (packStringLetters "xldhrutyhcyaqeezwujiguawfyawjjqlirxshjddvq")) NilTree))+             (SeqTree (hunk fx 20 [] (packStringLetters "ooygwiyogqrqnytixqtmvdxx"))+              (SeqTree (hunk fx 26 (packStringLetters "yogqrqnytixqtmvdxxvolwviqebieonxvcvuvigkfgybmzafybdcokyjskcgnvhkbz") (packStringLetters "akhsmlbkdxnvfoikmiatfbpzdrsyykkpoxvvddeaspzxe"))+               (SeqTree (hunk fx 39 [] (packStringLetters "ji"))                 (ParTree                  NilTree                  (ParTree@@ -273,14 +268,14 @@                   (ParTree                    (ParTree                     NilTree-                    (SeqTree (FP fx (Hunk 26 (packStringLetters "akhsmlbkdxnvfjioikmiatfbpzdrsyykkpoxvvddeaspzxepysaafnjjhcstgrczplxs") (packStringLetters "onjbhddskcj")))-                     (SeqTree (FP fx (Hunk 39 [] (packStringLetters "fyscunxxxjjtyqpfxeznhtwvlphmp"))) NilTree)))+                    (SeqTree (hunk fx 26 (packStringLetters "akhsmlbkdxnvfjioikmiatfbpzdrsyykkpoxvvddeaspzxepysaafnjjhcstgrczplxs") (packStringLetters "onjbhddskcj"))+                     (SeqTree (hunk fx 39 [] (packStringLetters "fyscunxxxjjtyqpfxeznhtwvlphmp")) NilTree)))                    (ParTree                     NilTree-                    (SeqTree (FP fx (Hunk 44 [] (packStringLetters "xcchzwmzoezxkmkhcmesplnjpqriypshgiqklgdnbmmkldnydiy")))+                    (SeqTree (hunk fx 44 [] (packStringLetters "xcchzwmzoezxkmkhcmesplnjpqriypshgiqklgdnbmmkldnydiy"))                      (ParTree                       NilTree-                      (SeqTree (FP fx (Hunk 64 (packStringLetters "plnjpqriypshgiqklgdnbmmkldnydiymiatfbpzdrsyykkpoxvvddeaspzxepysaafn") (packStringLetters "anjlzfdqbjqbcplvqvkhwjtkigp"))) NilTree)))))))))))+                      (SeqTree (hunk fx 64 (packStringLetters "plnjpqriypshgiqklgdnbmmkldnydiymiatfbpzdrsyykkpoxvvddeaspzxepysaafn") (packStringLetters "anjlzfdqbjqbcplvqvkhwjtkigp")) NilTree)))))))))))             (ParTree              NilTree              NilTree)))@@ -288,46 +283,42 @@         NilTree))       (ParTree        NilTree-       (SeqTree (FP fx (Hunk 1 [] (packStringLetters "ti")))-        (SeqTree (FP fx (Hunk 1 (packStringLetters "t") (packStringLetters "ybcop")))-         (SeqTree (FP fx (Hunk 2 [] (packStringLetters "dvlhgwqlpaeweerqrhnjtfolczbqbzoccnvdsyqiefqitrqneralf")))-          (SeqTree (FP fx (Hunk 15 [] (packStringLetters "yairbjphwtnaerccdlfewujvjvmjakbc")))-           (SeqTree (FP fx (Hunk 51 [] (packStringLetters "xayvfuwaiiogginufnhsrmktpmlbvxiakjwllddkiyofyfw")))+       (SeqTree (hunk fx 1 [] (packStringLetters "ti"))+        (SeqTree (hunk fx 1 (packStringLetters "t") (packStringLetters "ybcop"))+         (SeqTree (hunk fx 2 [] (packStringLetters "dvlhgwqlpaeweerqrhnjtfolczbqbzoccnvdsyqiefqitrqneralf"))+          (SeqTree (hunk fx 15 [] (packStringLetters "yairbjphwtnaerccdlfewujvjvmjakbc"))+           (SeqTree (hunk fx 51 [] (packStringLetters "xayvfuwaiiogginufnhsrmktpmlbvxiakjwllddkiyofyfw"))             (ParTree              NilTree              NilTree)))))))))]   where-      fx_name :: String-      fx_name = "F"--      fx :: FileName-      fx = fp2fn "./F"-+      fx :: String+      fx = "F" -mergeExamples :: [Sealed2 (RepoPatchV2 Prim :\/: RepoPatchV2 Prim)]+mergeExamples :: [Sealed2 (Patch :\/: Patch)] mergeExamples = map (mapSeal2 fromW) w_mergeExamples -repov2PatchLoopExamples :: [Sealed (WithStartState V1Model (Tree Prim))]+repov2PatchLoopExamples :: [Sealed (WithStartState V1Model (Tree Prim2))] repov2PatchLoopExamples = w_repov2PatchLoopExamples -commuteExamples :: [Sealed2 (RepoPatchV2 Prim :> RepoPatchV2 Prim)]+commuteExamples :: [Sealed2 (Patch :> Patch)] commuteExamples = map (mapSeal2 fromW) w_commuteExamples -tripleExamples :: [Sealed2 (RepoPatchV2 Prim :> RepoPatchV2 Prim :> RepoPatchV2 Prim)]+tripleExamples :: [Sealed2 (Patch :> Patch :> Patch)] tripleExamples = map (mapSeal2 fromW) w_tripleExamples -notDuplicatestriple :: (RepoPatchV2 Prim :> RepoPatchV2 Prim :> RepoPatchV2 Prim) wX wY -> Bool+notDuplicatestriple :: (Patch :> Patch :> Patch) wX wY -> Bool notDuplicatestriple = W.notDuplicatestriple . toW  quickhunk :: PrimPatch prim => Int -> String -> String -> prim wX wY quickhunk l o n = hunk "test" l (map (\c -> BC.pack [c]) o)                                 (map (\c -> BC.pack [c]) n) -primPermutables :: [(Prim :> Prim :> Prim) wX wY]+primPermutables :: [(Prim2 :> Prim2 :> Prim2) wX wY] primPermutables =     [quickhunk 0 "e" "bo" :> quickhunk 3 "" "x" :> quickhunk 2 "f" "qljo"] -mergeables :: [(Prim :\/: Prim) wX wY]+mergeables :: [(Prim2 :\/: Prim2) wX wY] mergeables = [quickhunk 1 "a" "b" :\/: quickhunk 1 "a" "c",               quickhunk 1 "a" "b" :\/: quickhunk 3 "z" "c",               quickhunk 0 "" "a" :\/: quickhunk 1 "" "b",@@ -336,7 +327,7 @@               quickhunk 0 "" "a" :\/: quickhunk 1 "b" ""              ] -mergeablesFL :: [(FL Prim :\/: FL Prim) wX wY]+mergeablesFL :: [(FL Prim2 :\/: FL Prim2) wX wY] mergeablesFL = map (\ (x:\/:y) -> (x :>: NilFL) :\/: (y :>: NilFL)) mergeables ++            [] --    [(quickhunk 1 "a" "b" :>: quickhunk 3 "z" "c" :>: NilFL)               --  :\/: (quickhunk 1 "a" "z" :>: NilFL),@@ -346,50 +337,50 @@ mergeable2commutable :: Invert p => (p :\/: p) wX wY -> (p :> p) wX wY mergeable2commutable (x :\/: y) = unsafeCoerceP (invert x) :> y -commutablesFL :: [(FL Prim :> FL Prim) wX wY]+commutablesFL :: [(FL Prim2 :> FL Prim2) wX wY] commutablesFL = map mergeable2commutable mergeablesFL-commutables :: [(Prim :> Prim) wX wY]+commutables :: [(Prim2 :> Prim2) wX wY] commutables = map mergeable2commutable mergeables -primPatches :: [Prim wX wY]+primPatches :: [Prim2 wX wY] primPatches = concatMap mergeable2patches mergeables     where mergeable2patches (x:\/:y) = [x,y] -repov2Patches :: [RepoPatchV2 Prim wX wY]+repov2Patches :: [Patch wX wY] repov2Patches = concatMap commutable2patches repov2Commutables     where commutable2patches (x:>y) = [x,y] -repov2Triples :: [(RepoPatchV2 Prim :> RepoPatchV2 Prim :> RepoPatchV2 Prim) wX wY]+repov2Triples :: [(Patch :> Patch :> Patch) wX wY] repov2Triples = [ob' :> oa2 :> a2'',                  oa' :> oa2 :> a2'']                ++ map unsafeUnseal2 tripleExamples                ++ map unsafeUnseal2 (concatMap getTriples repov2FLs)-    where oa = prim2repopatchV2 $ quickhunk 1 "o" "aa"+    where oa = fromPrim $ quickhunk 1 "o" "aa"           oa2 = oa-          a2 = prim2repopatchV2 $ quickhunk 2 "a34" "2xx"-          ob = prim2repopatchV2 $ quickhunk 1 "o" "bb"+          a2 = fromPrim $ quickhunk 2 "a34" "2xx"+          ob = fromPrim $ quickhunk 1 "o" "bb"           ob' :/\: oa' = merge (oa :\/: ob)           a2' :/\: _ = merge (ob' :\/: a2)           a2'' :/\: _ = merge (oa2 :\/: a2') -repov2NonduplicateTriples :: [(RepoPatchV2 Prim :> RepoPatchV2 Prim :> RepoPatchV2 Prim) wX wY]+repov2NonduplicateTriples :: [(Patch :> Patch :> Patch) wX wY] repov2NonduplicateTriples = filter (notDuplicatestriple) repov2Triples -repov2FLs :: [FL (RepoPatchV2 Prim) wX wY]+repov2FLs :: [FL (Patch) wX wY] repov2FLs = [oa :>: invert oa :>: oa :>: invert oa :>: ps +>+ oa :>: invert oa :>: NilFL]-    where oa = prim2repopatchV2 $ quickhunk 1 "o" "a"+    where oa = fromPrim $ quickhunk 1 "o" "a"           ps :/\: _ = merge (oa :>: invert oa :>: NilFL :\/: oa :>: invert oa :>: NilFL) -repov2Commutables :: [(RepoPatchV2 Prim :> RepoPatchV2 Prim) wX wY]+repov2Commutables :: [(Patch :> Patch) wX wY] repov2Commutables = map unsafeUnseal2 commuteExamples++                      map mergeable2commutable repov2Mergeables++                      [invert oa :> ob'] ++ map unsafeUnseal2 (concatMap getPairs repov2FLs)-    where oa = prim2repopatchV2 $ quickhunk 1 "o" "a"-          ob = prim2repopatchV2 $ quickhunk 1 "o" "b"+    where oa = fromPrim $ quickhunk 1 "o" "a"+          ob = fromPrim $ quickhunk 1 "o" "b"           _ :/\: ob' = mergeFL (ob :\/: oa :>: invert oa :>: NilFL) -repov2Mergeables :: [(RepoPatchV2 Prim :\/: RepoPatchV2 Prim) wX wY]-repov2Mergeables = map (\ (x :\/: y) -> prim2repopatchV2 x :\/: prim2repopatchV2 y) mergeables+repov2Mergeables :: [(Patch :\/: Patch) wX wY]+repov2Mergeables = map (\ (x :\/: y) -> fromPrim x :\/: fromPrim y) mergeables                         ++ repov2IglooMergeables                         ++ repov2QuickcheckMergeables                         ++ map unsafeUnseal2 mergeExamples@@ -410,16 +401,16 @@                             (ob'' :\/: og''),                             (ob'' :\/: oc''),                             (oc' :\/: od'')]-    where oa = prim2repopatchV2 $ quickhunk 1 "o" "aa"-          a2 = prim2repopatchV2 $ quickhunk 2 "a34" "2xx"-          og = prim2repopatchV2 $ quickhunk 3 "4" "g"-          ob = prim2repopatchV2 $ quickhunk 1 "o" "bb"-          b2 = prim2repopatchV2 $ quickhunk 2 "b" "2"-          oc = prim2repopatchV2 $ quickhunk 1 "o" "cc"-          od = prim2repopatchV2 $ quickhunk 7 "x" "d"-          oe = prim2repopatchV2 $ quickhunk 7 "x" "e"-          pf = prim2repopatchV2 $ quickhunk 7 "x" "f"-          od'' = prim2repopatchV2 $ quickhunk 8 "x" "d"+    where oa = fromPrim $ quickhunk 1 "o" "aa"+          a2 = fromPrim $ quickhunk 2 "a34" "2xx"+          og = fromPrim $ quickhunk 3 "4" "g"+          ob = fromPrim $ quickhunk 1 "o" "bb"+          b2 = fromPrim $ quickhunk 2 "b" "2"+          oc = fromPrim $ quickhunk 1 "o" "cc"+          od = fromPrim $ quickhunk 7 "x" "d"+          oe = fromPrim $ quickhunk 7 "x" "e"+          pf = fromPrim $ quickhunk 7 "x" "f"+          od'' = fromPrim $ quickhunk 8 "x" "d"           ob' :>: b2' :>: NilFL :/\: _ = mergeFL (oa :\/: ob :>: b2 :>: NilFL)           a2' :/\: _ = merge (ob' :\/: a2)           ob'' :/\: _ = merge (a2 :\/: ob')@@ -431,12 +422,12 @@           oc''' :/\: _ = merge (ob' :\/: oc')           oe' :/\: _ = merge (od :\/: oe)           of' :/\: _ = merge (od :\/: pf)-          pair2m :: Sealed2 (RepoPatchV2 Prim :> RepoPatchV2 Prim)-                 -> Maybe ((RepoPatchV2 Prim :\/: RepoPatchV2 Prim) wX wY)+          pair2m :: Sealed2 (Patch :> Patch)+                 -> Maybe ((Patch :\/: Patch) wX wY)           pair2m (Sealed2 (xx :> y)) = do y' :> _ <- commute (xx :> y)                                           return $ unsafeCoerceP (xx :\/: y') -repov2IglooMergeables :: [(RepoPatchV2 Prim :\/: RepoPatchV2 Prim) wX wY]+repov2IglooMergeables :: [(Patch :\/: Patch) wX wY] repov2IglooMergeables = [(a :\/: b),                     (b :\/: c),                     (a :\/: c),@@ -447,17 +438,17 @@                     (z' :\/: y'),                     (x' :\/: z'),                     (a :\/: a)]-    where a = prim2repopatchV2 $ quickhunk 1 "1" "A"-          b = prim2repopatchV2 $ quickhunk 2 "2" "B"-          c = prim2repopatchV2 $ quickhunk 3 "3" "C"-          x = prim2repopatchV2 $ quickhunk 1 "1BC" "xbc"-          y = prim2repopatchV2 $ quickhunk 1 "A2C" "ayc"-          z = prim2repopatchV2 $ quickhunk 1 "AB3" "abz"+    where a = fromPrim $ quickhunk 1 "1" "A"+          b = fromPrim $ quickhunk 2 "2" "B"+          c = fromPrim $ quickhunk 3 "3" "C"+          x = fromPrim $ quickhunk 1 "1BC" "xbc"+          y = fromPrim $ quickhunk 1 "A2C" "ayc"+          z = fromPrim $ quickhunk 1 "AB3" "abz"           x' :/\: _ = merge (a :\/: x)           y' :/\: _ = merge (b :\/: y)           z' :/\: _ = merge (c :\/: z) -repov2QuickcheckMergeables :: [(RepoPatchV2 Prim :\/: RepoPatchV2 Prim) wX wY]+repov2QuickcheckMergeables :: [(Patch :\/: Patch) wX wY] repov2QuickcheckMergeables = [-- invert k1 :\/: n1                              --, invert k2 :\/: n2                                hb :\/: k@@ -467,25 +458,25 @@                              , k' :\/: k'                              , k3 :\/: k3                              ] ++ catMaybes (map pair2m pairs)-    where hb = prim2repopatchV2 $ quickhunk 0 "" "hb"-          k = prim2repopatchV2 $ quickhunk 0 "" "k"-          n = prim2repopatchV2 $ quickhunk 0 "" "n"-          b = prim2repopatchV2 $ quickhunk 1 "b" ""-          d = prim2repopatchV2 $ quickhunk 2 "" "d"+    where hb = fromPrim $ quickhunk 0 "" "hb"+          k = fromPrim $ quickhunk 0 "" "k"+          n = fromPrim $ quickhunk 0 "" "n"+          b = fromPrim $ quickhunk 1 "b" ""+          d = fromPrim $ quickhunk 2 "" "d"           d':/\:_ = merge (b :\/: d)           --k1 :>: n1 :>: NilFL :/\: _ = mergeFL (hb :\/: k :>: n :>: NilFL)           --k2 :>: n2 :>: NilFL :/\: _ =           --    merge (hb :>: b :>: NilFL :\/: k :>: n :>: NilFL)           k' :>: n' :>: NilFL :/\: _ :>: b' :>: _ = merge (hb :>: b :>: d' :>: NilFL :\/: k :>: n :>: NilFL)           pairs = getPairs (hb :>: b :>: d' :>: k' :>: n' :>: NilFL)-          pair2m :: Sealed2 (RepoPatchV2 Prim :> RepoPatchV2 Prim)-                 -> Maybe ((RepoPatchV2 Prim :\/: RepoPatchV2 Prim) wX wY)+          pair2m :: Sealed2 (Patch :> Patch)+                 -> Maybe ((Patch :\/: Patch) wX wY)           pair2m (Sealed2 (xx :> y)) = do y' :> _ <- commute (xx :> y)                                           return $ unsafeCoerceP (xx :\/: y') -          i = prim2repopatchV2 $ quickhunk 0 "" "i"-          x = prim2repopatchV2 $ quickhunk 0 "" "x"-          xi = prim2repopatchV2 $ quickhunk 0 "xi" ""+          i = fromPrim $ quickhunk 0 "" "i"+          x = fromPrim $ quickhunk 0 "" "x"+          xi = fromPrim $ quickhunk 0 "xi" ""           d3 :/\: _ = merge (xi :\/: d)           _ :/\: k3 = mergeFL (k :\/: i :>: x :>: xi :>: d3 :>: NilFL) 
harness/Darcs/Test/Patch/FileUUIDModel.hs view
@@ -1,6 +1,4 @@-{-# OPTIONS_GHC -fno-warn-name-shadowing -fno-warn-unused-binds -fno-warn-unused-imports -fno-warn-orphans #-}-{-# LANGUAGE CPP, OverloadedStrings, MultiParamTypeClasses, StandaloneDeriving #-}-+{-# LANGUAGE OverloadedStrings, MultiParamTypeClasses, StandaloneDeriving #-}  -- | Repository model module Darcs.Test.Patch.FileUUIDModel@@ -10,8 +8,8 @@   , emptyFile   , emptyDir   , nullRepo-  , isEmpty-  , root, repoObjects+  , root, rootId+  , repoObjects, repoIds   , aFilename, aDirname   , aLine, aContent   , aFile, aDir@@ -20,41 +18,34 @@   ) where  +import Prelude ()+import Darcs.Prelude+ import Darcs.Test.Util.QuickCheck ( alpha, uniques, bSized ) import Darcs.Test.Patch.RepoModel -import Darcs.Patch.Apply( Apply(..), applyToState )-import Darcs.Patch.ApplyMonad( ApplyMonad(..) )-import Darcs.Patch.Prim.FileUUID.Core( UUID(..), Hunk(..), Prim(..), Object(..) )+import Darcs.Patch.Apply( applyToState )+import Darcs.Patch.Prim.FileUUID.Core( UUID(..), Object(..) ) import Darcs.Patch.Prim.FileUUID.Apply( ObjectMap(..) ) import Darcs.Patch.Witnesses.Sealed ( Sealed, seal ) import Darcs.Patch.Witnesses.Show -import Darcs.Util.Path-import Darcs.Util.Tree( Tree, TreeItem )-import qualified Darcs.Util.Tree as T+import Darcs.Util.Path ( Name, unsafeMakeName ) import Darcs.Util.Hash( Hash(..) )-import Darcs.Util.Tree.Hashed ( darcsUpdateHashes )  import Control.Applicative ( (<$>) )-import Control.Arrow ( second )-import qualified Data.ByteString as BS+import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC-import qualified Data.ByteString.Lazy as BL-import qualified Data.ByteString.Lazy.Char8 as BLC-import Data.List ( intercalate, sort ) import qualified Data.Map as M import Test.QuickCheck   ( Arbitrary(..)   , Gen, choose, vectorOf, frequency, oneof )--#include "impossible.h"-+-- import Text.Show.Pretty ( ppShow )  ---------------------------------------------------------------------- -- * Model definition -newtype FileUUIDModel wX = FileUUIDModel { repoMap :: ObjectMap Fail }+newtype FileUUIDModel wX = FileUUIDModel { _repoMap :: ObjectMap Fail }  ---------------------------------------- -- Instances@@ -65,8 +56,8 @@  deriving instance Eq (Object Fail) -instance Show (FileUUIDModel x) where-  show = showModel+instance Show (FileUUIDModel wX) where+  show repo = "FileUUIDModel " ++ show (repoObjects repo)  instance Show1 FileUUIDModel where   showDict1 = ShowDictClass@@ -75,16 +66,18 @@ -- * Constructors  objectMap :: (Monad m) => M.Map UUID (Object m) -> ObjectMap m-objectMap map = ObjectMap { getObject = get, putObject = put, listObjects = list }-  where list = return $ M.keys map-        put k o = return $ objectMap (M.insert k o map)-        get k = return $ M.lookup k map+objectMap m = ObjectMap { getObject = get, putObject = put, listObjects = list }+  where list = return $ M.keys m+        put k o = return $ objectMap (M.insert k o m)+        get k = return $ M.lookup k m +{- emptyRepo :: FileUUIDModel wX-emptyRepo = FileUUIDModel (objectMap M.empty)+emptyRepo = FileUUIDModel (objectMap $ M.singleton rootId emptyDir)+-}  emptyFile :: (Monad m) => Object m-emptyFile = Blob (return BS.empty) NoHash+emptyFile = Blob (return B.empty) NoHash  emptyDir :: Object m emptyDir = Directory M.empty@@ -93,22 +86,32 @@ -- * Queries  nullRepo :: FileUUIDModel wX -> Bool-nullRepo = null . repoObjects+nullRepo repo = repoIds repo == [rootId] +rootId :: UUID+rootId = UUID "ROOT"++-- | The root directory of a repository.+root :: FileUUIDModel wX -> (UUID, Object Fail)+root (FileUUIDModel repo) = (rootId, fromJust $ unFail $ getObject repo rootId)++repoObjects :: FileUUIDModel wX -> [(UUID, Object Fail)]+repoObjects (FileUUIDModel repo) =+    [(uuid, obj uuid) | uuid <- unFail $ listObjects repo]+  where+    obj uuid = fromJust $ unFail $ getObject repo uuid++repoIds :: FileUUIDModel wX -> [UUID]+repoIds = map fst . repoObjects+ -- | @isEmpty file@ <=> file content is empty --   @isEmpty dir@  <=> dir has no child isEmpty :: Object Fail -> Bool isEmpty (Directory d) = M.null d-isEmpty (Blob f _) = BS.null $ unFail f---- | The root directory of a repository.-root :: FileUUIDModel wX -> Object Fail-root (FileUUIDModel repo) = fromJust $ unFail $ getObject repo (UUID "ROOT")+isEmpty (Blob f _) = B.null $ unFail f -repoObjects :: FileUUIDModel wX -> [(UUID, Object Fail)]-repoObjects (FileUUIDModel repo) = [ (id, obj id) |-                               id <- unFail $ listObjects repo, not $ isEmpty $ obj id ]-  where obj id = fromJust $ unFail $ getObject repo id+nonEmptyRepoObjects :: FileUUIDModel wX -> [(UUID, Object Fail)]+nonEmptyRepoObjects = filter (not . isEmpty . snd) . repoObjects  ---------------------------------------------------------------------- -- * Comparing repositories@@ -125,29 +128,28 @@   -- | Files are distinguish by ending their names with ".txt".-aFilename :: Gen BS.ByteString-aFilename = do len <- choose (1,maxLength)-               name <- vectorOf len alpha-               return $ BC.pack $ name ++ ".txt"-  where-      maxLength = 3+aFilename :: Gen Name+aFilename = do+  len <- choose (1,3)+  name <- vectorOf len alpha+  return $ unsafeMakeName . BC.pack $ name ++ ".txt" -aDirname :: Gen BS.ByteString-aDirname = do len <- choose (1,maxLength)-              BC.pack <$> vectorOf len alpha-  where-      maxLength = 3+aDirname :: Gen Name+aDirname = do+  len <- choose (1,3)+  name <- vectorOf len alpha+  return $ unsafeMakeName . BC.pack $ name -aWord :: Gen BS.ByteString+aWord :: Gen B.ByteString aWord = do c <- alpha            return $ BC.pack[c] -aLine :: Gen BS.ByteString+aLine :: Gen B.ByteString aLine = do wordsNo <- choose (1,2)            ws <- vectorOf wordsNo aWord            return $ BC.unwords ws -aContent :: Gen BS.ByteString+aContent :: Gen B.ByteString aContent = bSized 0 0.5 80 $ \k ->              do n <- choose (0,k)                 BC.intercalate "\n" <$> vectorOf n aLine@@ -161,7 +163,6 @@   do dirsplit <- choose (1, length dirids)      filesplit <- choose (1, length fileids)      let ids = take filesplit fileids-         rem = drop filesplit fileids      files <- vectorOf filesplit aFile      names <- vectorOf filesplit aFilename      dirnames <- vectorOf dirsplit aDirname@@ -175,28 +176,29 @@           dirsplit <- choose (1, length dirs)           filesplit <- choose (1, length files)           dir <- aDir (head tomake : take dirsplit dirs) (take filesplit files)-          rem <- subdirs (tail tomake) (drop dirsplit dirs) (drop filesplit files)-          return $ dir ++ rem+          remaining <- subdirs (tail tomake) (drop dirsplit dirs) (drop filesplit files)+          return $ dir ++ remaining   anUUID :: Gen UUID-anUUID = UUID . BC.pack <$> vectorOf 32 (oneof $ map return "0123456789")+anUUID = UUID . BC.pack <$> vectorOf 4 (oneof $ map return "0123456789")  -- | @aRepo filesNo dirsNo@ produces repositories with *at most*  -- @filesNo@ files and @dirsNo@ directories.  -- The structure of the repository is aleatory.-aRepo :: Int                -- ^ Maximum number of files-        -> Int              -- ^ Maximum number of directories-        -> Gen (FileUUIDModel wX)-aRepo maxFiles maxDirs-  = do let minFiles = if maxDirs == 0 && maxFiles > 0 then 1 else 0-       filesNo <- choose (minFiles,maxFiles)-       let minDirs = if filesNo == 0 && maxDirs > 0 then 1 else 0-       dirsNo <- choose (minDirs,maxDirs)-       dirids <- (UUID "ROOT":) <$> uniques dirsNo anUUID-       fileids <- uniques filesNo anUUID-       objectmap <- aDir dirids fileids-       return $ FileUUIDModel $ objectMap $ M.fromList objectmap+aRepo :: Int                    -- ^ Maximum number of files+      -> Int                    -- ^ Maximum number of directories+      -> Gen (FileUUIDModel wX)+aRepo maxFiles maxDirs = do+  ids <- uniques (maxFiles+maxDirs) anUUID+  let minFiles = if maxDirs == 0 && maxFiles > 0 then 1 else 0+  filesNo <- choose (minFiles,maxFiles)+  let minDirs = if filesNo == 0 && maxDirs > 0 then 1 else 0+  dirsNo <- choose (minDirs,maxDirs)+  let (dirids, ids') = splitAt dirsNo ids+      fileids = take filesNo ids'+  objectmap <- aDir (rootId : dirids) fileids+  return $ FileUUIDModel $ objectMap $ M.fromList objectmap  -- | Generate small repositories. -- Small repositories help generating (potentially) conflicting patches.@@ -206,9 +208,8 @@                   dirsNo <- frequency [(3, return 1), (1, return 0)]                   aRepo filesNo dirsNo   repoApply (FileUUIDModel state) patch = FileUUIDModel <$> applyToState patch state-  showModel model = "FileUUIDModel{\n" ++ unlines (map entry $ repoObjects model) ++ "}"-    where entry (id, obj) = show id ++ " -> " ++ show obj-  eqModel r1 r2 = repoObjects r1 == repoObjects r2+  showModel = show -- ppShow+  eqModel r1 r2 = nonEmptyRepoObjects r1 == nonEmptyRepoObjects r2  instance Arbitrary (Sealed FileUUIDModel) where   arbitrary = seal <$> aSmallRepo
harness/Darcs/Test/Patch/Info.hs view
@@ -20,30 +20,36 @@ module Darcs.Test.Patch.Info ( testSuite ) where  import Prelude hiding ( pi )-import Data.ByteString ( ByteString )-import qualified Data.ByteString as B ( split, pack )+import qualified Data.ByteString as B ( ByteString, pack ) import qualified Data.ByteString.Char8 as BC ( unpack )-import Data.List ( sort )+import Data.List ( sort , isPrefixOf ) import Data.Maybe ( isNothing ) import Data.Text as T ( find, any ) import Data.Text.Encoding ( decodeUtf8With ) import Data.Text.Encoding.Error ( lenientDecode )-import System.IO.Unsafe ( unsafePerformIO ) import Test.QuickCheck ( Arbitrary(arbitrary), oneof, listOf, choose, shrink-                       , Gen )+                       , Gen, suchThat, scale ) import Test.Framework.Providers.QuickCheck2 ( testProperty ) import Test.Framework (Test, testGroup)-import Data.List ( isPrefixOf )+-- import Text.Show.Pretty ( ppShow ) -import Darcs.Patch.Info ( PatchInfo(..), patchinfo,-                          piLog, piAuthor, piName )-import Darcs.Util.ByteString ( decodeLocale, packStringToUTF8, unpackPSFromUTF8 )+import Darcs.Patch.Info+    ( PatchInfo(..), rawPatchInfo, showPatchInfo, readPatchInfo+    , piLog, piAuthor, piName, validDate, validLog, validAuthor+    , validDatePS, validLogPS, validAuthorPS+    )+import Darcs.Patch.ReadMonads ( parseStrictly )+import Darcs.Patch.Show ( ShowPatchFor(..) )+import Darcs.Util.ByteString+    ( decodeLocale, packStringToUTF8, unpackPSFromUTF8, linesPS )+import Darcs.Util.Printer ( renderPS )  testSuite :: Test testSuite = testGroup "Darcs.Patch.Info"   [ metadataDecodingTest   , metadataEncodingTest   , packUnpackTest+  , parseUnparseTest   ]  -- | A newtype wrapping String so we can make our own random generator for it.@@ -58,6 +64,9 @@ --   only UTF-8-encoded PatchInfo's. newtype UTF8PatchInfo = UTF8PatchInfo PatchInfo deriving (Eq, Ord) +-- Note that this instance only creates valid unicode strings. It does not+-- generate lone surrogates, for instance, as these would fail the+-- packUnpackTest below. instance Arbitrary UnicodeString where     -- 0x10ffff is the highest Unicode code point ; 0xd800 - 0xdfff are     -- surrogates. '\xfffd' is excluded because it is used as a marker@@ -67,80 +76,82 @@                                                    ,choose ('\xfffe', '\x10ffff')])  instance Show UTF8PatchInfo where-     showsPrec _ = withUTF8PatchInfo rawPatchInfoShow+    show = withUTF8PatchInfo rawPatchInfoShow instance Show UTF8OrNotPatchInfo where-     showsPrec _ = withUTF8OrNotPatchInfo rawPatchInfoShow+    show = withUTF8OrNotPatchInfo rawPatchInfoShow  -- | Shows a PatchInfo, outputting every byte and clearly marking what is what-rawPatchInfoShow :: PatchInfo -> String -> String-rawPatchInfoShow pi = ("PatchInfo: \n"++)-                    . ("date: "++) . shows (_piDate pi) . ('\n':)-                    . ("author: "++) . shows (_piAuthor pi) . ('\n':)-                    . ("name: "++) . shows (_piName pi) . ('\n':)-                    . ("log: "++) . shows (_piLog pi) . ('\n':)+rawPatchInfoShow :: PatchInfo -> String+rawPatchInfoShow = {- ppShow -} show  instance Arbitrary UTF8PatchInfo where-    arbitrary = UTF8PatchInfo `fmap` arbitraryUTF8Patch+    arbitrary = UTF8PatchInfo `fmap` arbitraryUTF8PatchInfo     shrink upi = flip withUTF8PatchInfo upi $ \pi -> do         sn <- shrink (piName pi)         sa <- shrink (piAuthor pi)         sl <- shrink (filter (not . isPrefixOf "Ignore-this:") (piLog pi))-        return (UTF8PatchInfo-                   (unsafePerformIO $ patchinfo sn-                                          (BC.unpack (_piDate pi)) sa sl))+        i <- shrink (isInverted pi)+        return (UTF8PatchInfo (rawPatchInfo sn (BC.unpack (_piDate pi)) sa sl i))  instance Arbitrary UTF8OrNotPatchInfo where-    arbitrary = UTF8OrNotPatchInfo `fmap` oneof ([arbitraryUTF8Patch,-                                                  arbitraryUnencodedPatch])+    arbitrary = UTF8OrNotPatchInfo `fmap` oneof ([arbitraryUTF8PatchInfo,+                                                  arbitraryUnencodedPatchInfo]) --- | Generate arbitrary patch metadata that uses the metadata creation function---   'patchinfo' from Darcs.Patch.Info.-arbitraryUTF8Patch :: Gen PatchInfo-arbitraryUTF8Patch =-    do n <- asString `fmap` arbitrary-       d <- arbitrary-       a <- asString `fmap` arbitrary-       l <- (lines . asString) `fmap` arbitrary-       return $ unsafePerformIO $ patchinfo n d a l+-- | Generate arbitrary patch metadata.+-- Note : We must NOT use 'patchinfo' from Darcs.Patch.Info+-- with unsafePerformIO here because this breaks  the parse/unparse test+-- (the added junk will be different on each call).+arbitraryUTF8PatchInfo :: Gen PatchInfo+arbitraryUTF8PatchInfo = do+    d <- arbitrary `suchThat` validDate+    n <- (asString `fmap` arbitrary) `suchThat` validLog+    a <- (asString `fmap` arbitrary) `suchThat` validAuthor+    l <- lines `fmap` scale (* 2) arbitrary+    i <- return False+    return $ rawPatchInfo d n a l i  -- | Generate arbitrary patch metadata that has totally arbitrary byte strings --   as its name, date, author and log.-arbitraryUnencodedPatch :: Gen PatchInfo-arbitraryUnencodedPatch = do-    n <- arbitraryByteString-    d <- arbitraryByteString-    a <- arbitraryByteString-    -- split 10 is the ByteString equivalent of 'lines'-    l <- B.split 10 `fmap` arbitraryByteString-    i <- arbitrary+arbitraryUnencodedPatchInfo :: Gen PatchInfo+arbitraryUnencodedPatchInfo = do+    d <- arbitraryByteString `suchThat` validDatePS+    n <- arbitraryByteString `suchThat` validLogPS+    a <- arbitraryByteString `suchThat` validAuthorPS+    l <- linesPS `fmap` scale (* 2) arbitraryByteString+    i <- return False     return (PatchInfo d n a l i) -arbitraryByteString :: Gen ByteString-arbitraryByteString = (B.pack . map fromIntegral)-                          `fmap` listOf (choose (0, 255) :: Gen Int)+arbitraryByteString :: Gen B.ByteString+arbitraryByteString = B.pack <$> listOf arbitrary  -- | Test that anything produced by the 'patchinfo' function is valid UTF-8 metadataEncodingTest :: Test-metadataEncodingTest = testProperty "Testing patch metadata encoding" $-    withUTF8PatchInfo $-       \patchInfo -> encodingOK (_piAuthor patchInfo)-                     && encodingOK (_piName patchInfo)-                     && all encodingOK (_piLog patchInfo)-  where encodingOK = isNothing . T.find (=='\xfffd') . decodeUtf8With lenientDecode+metadataEncodingTest =+    testProperty "Testing patch metadata encoding" propMetadataEncoding +propMetadataEncoding :: UTF8PatchInfo -> Bool+propMetadataEncoding (UTF8PatchInfo patchInfo) =+    encodingOK (_piAuthor patchInfo)+    && encodingOK (_piName patchInfo)+    && all encodingOK (_piLog patchInfo)+  where+    encodingOK = isNothing . T.find (=='\xfffd') . decodeUtf8With lenientDecode+ -- | Test that metadata in patches are decoded as UTF-8 or locale depending on -- whether they're valid UTF-8. metadataDecodingTest :: Test-metadataDecodingTest = testProperty "Testing patch metadata decoding" $-    withUTF8OrNotPatchInfo $-        \patchInfo -> utf8OrLocale (_piAuthor patchInfo) == piAuthor patchInfo-                      && utf8OrLocale (_piName patchInfo) == piName patchInfo-                      && map utf8OrLocale (_piLog patchInfo) `superset` piLog patchInfo-  where utf8OrLocale bs = if isValidUTF8 bs-                            then unpackPSFromUTF8 bs-                            else decodeLocale bs+metadataDecodingTest = testProperty "Testing patch metadata decoding" propMetadataDecoding -isValidUTF8 :: ByteString -> Bool+propMetadataDecoding :: UTF8OrNotPatchInfo -> Bool+propMetadataDecoding (UTF8OrNotPatchInfo patchInfo) =+    utf8OrLocale (_piAuthor patchInfo) == piAuthor patchInfo+    && utf8OrLocale (_piName patchInfo) == piName patchInfo+    && map utf8OrLocale (_piLog patchInfo) `superset` piLog patchInfo+  where+    utf8OrLocale bs =+      if isValidUTF8 bs then unpackPSFromUTF8 bs else decodeLocale bs++isValidUTF8 :: B.ByteString -> Bool isValidUTF8 = not . T.any (=='\xfffd') . decodeUtf8With lenientDecode  packUnpackTest :: Test@@ -161,3 +172,18 @@ withUTF8OrNotPatchInfo :: (PatchInfo -> a) -> UTF8OrNotPatchInfo -> a withUTF8OrNotPatchInfo f mpi = case mpi of                                  UTF8OrNotPatchInfo pinf -> f pinf++parseUnparseTest :: Test+parseUnparseTest = testProperty "parse . show == id" propParseUnparse++parsePatchInfo :: B.ByteString -> Maybe PatchInfo+parsePatchInfo = fmap fst . parseStrictly readPatchInfo++unparsePatchInfo :: PatchInfo -> B.ByteString+unparsePatchInfo = renderPS . showPatchInfo ForStorage++instance Arbitrary PatchInfo where+    arbitrary = arbitraryUnencodedPatchInfo++propParseUnparse :: PatchInfo -> Bool+propParseUnparse pi = Just pi == parsePatchInfo (unparsePatchInfo pi)
harness/Darcs/Test/Patch/Properties/Check.hs view
@@ -1,7 +1,10 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE StandaloneDeriving, GeneralizedNewtypeDeriving #-} module Darcs.Test.Patch.Properties.Check ( Check(..), checkAPatch ) where +import Prelude ()+import Darcs.Prelude import Control.Monad ( liftM )+import Data.Maybe ( isNothing )  import Darcs.Test.Patch.Check ( PatchCheck,                                 checkMove, removeDir, createDir,@@ -16,17 +19,20 @@ import Darcs.Util.Path ( fn2fp ) import qualified Data.Map as M ( mapMaybe ) -import Darcs.Patch ( invert,-                     effect )+import Darcs.Patch ( invert, effect, PrimPatch ) import Darcs.Patch.Invert ( Invert )-import Darcs.Patch.V1 ()-import qualified Darcs.Patch.V1.Core as V1 ( RepoPatchV1(..) )+import Darcs.Patch.V1 ( )+import Darcs.Patch.V1.Core ( RepoPatchV1(..) )+import Darcs.Patch.V2.RepoPatch ( RepoPatchV2, isConsistent )+import qualified Darcs.Patch.V1.Prim as V1 ( Prim(..) )+import qualified Darcs.Patch.V2.Prim as V2 ( Prim(..) ) import Darcs.Patch.V1.Core ( isMerger )-import Darcs.Patch.Prim.V1 ()+import qualified Darcs.Patch.Prim.FileUUID as FileUUID ( Prim ) import Darcs.Patch.Prim.V1.Core ( Prim(..), DirPatchType(..), FilePatchType(..) ) import Darcs.Patch.Witnesses.Ordered -#include "impossible.h"+type Prim1 = V1.Prim+type Prim2 = V2.Prim  class Check p where    checkPatch :: p wX wY -> PatchCheck Bool@@ -35,16 +41,27 @@    checkPatch NilFL = isValid    checkPatch (p :>: ps) = checkPatch p >> checkPatch ps +instance Check p => Check (p:>p) where+   checkPatch (p1 :> p2) = checkPatch p1 >> checkPatch p2+ checkAPatch :: (Invert p, Check p) => p wX wY -> Bool checkAPatch p = doCheck $ do _ <- checkPatch p                              checkPatch $ invert p -instance Check (V1.RepoPatchV1 Prim) where-   checkPatch p | isMerger p = do-     checkPatch $ effect p-   checkPatch (V1.Merger _ _ _ _) = impossible-   checkPatch (V1.Regrem _ _ _ _) = impossible-   checkPatch (V1.PP p) = checkPatch p+instance PrimPatch prim => Check (RepoPatchV2 prim) where+  checkPatch p = return $ isNothing $ isConsistent p++instance Check (RepoPatchV1 Prim1) where+   checkPatch p | isMerger p = checkPatch $ effect p+   checkPatch (Merger _ _ _ _) = impossible+   checkPatch (Regrem _ _ _ _) = impossible+   checkPatch (PP p) = checkPatch p++deriving instance Check Prim1+deriving instance Check Prim2++instance Check FileUUID.Prim where+  checkPatch _ = return True -- XXX  instance Check Prim where 
harness/Darcs/Test/Patch/Properties/Generic.hs view
@@ -15,10 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -fno-warn-deprecations -fno-warn-orphans #-}-- module Darcs.Test.Patch.Properties.Generic     ( invertSymmetry, inverseComposition, invertRollback,       recommute, commuteInverses, effectPreserving,@@ -37,21 +33,22 @@ import Darcs.Test.Patch.Arbitrary.Generic ( Tree, flattenOne, MightBeEmptyHunk(..), MightHaveDuplicate(..) )  import Control.Monad ( msum )+ import Darcs.Patch.Witnesses.Show ( Show2(..), show2 )-import Darcs.Patch.Patchy ( Patchy, showPatch, commute, invert ) import Darcs.Patch.Read ( ReadPatch )-import Darcs.Patch.Show ( ShowPatchBasic )+import Darcs.Patch.Show+    ( ShowPatchBasic, displayPatch, showPatch, ShowPatchFor(ForStorage) ) import Darcs.Patch.Prim.Class ( PrimPatch, PrimOf, FromPrim ) import Darcs.Patch ()-import Darcs.Patch.Apply ( ApplyState )-import Darcs.Patch.Commute ( commuteFLorComplain )+import Darcs.Patch.Apply ( Apply, ApplyState )+import Darcs.Patch.Commute ( commute, commuteFL ) import Darcs.Patch.Merge ( Merge(merge) ) import Darcs.Patch.Read ( readPatch )-import Darcs.Patch.Invert ( invertFL )-import Darcs.Patch.Witnesses.Eq ( MyEq(..), EqCheck(..) )+import Darcs.Patch.Invert ( Invert, invert, invertFL )+import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) ) import Darcs.Patch.Witnesses.Ordered ( FL(..), (:>)(..), (:\/:)(..), (:/\:)(..), lengthFL, eqFL, reverseRL ) import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed), seal2, Sealed2 )-import Darcs.Util.Printer ( Doc, renderPS, redText, greenText, ($$), text, RenderMode(..) )+import Darcs.Util.Printer ( Doc, renderPS, redText, greenText, ($$), text ) --import Darcs.ColorPrinter ( traceDoc )  propIsMergeable :: forall model p wX . (FromPrim p, Merge p, RepoModel model)@@ -64,19 +61,19 @@                        _ -> Nothing  -- | invert symmetry   inv(inv(p)) = p-invertSymmetry :: (Patchy p, MyEq p) => p wA wB -> TestResult+invertSymmetry :: (Invert p, Eq2 p) => p wA wB -> TestResult invertSymmetry p = case invert (invert p) =\/= p of                         IsEq  -> succeeded                         NotEq -> failed $ redText "p /= inv(inv(p))" -inverseComposition :: (Patchy p, MyEq p) => (p :> p) wX wY -> TestResult+inverseComposition :: (Invert p, Eq2 p) => (p :> p) wX wY -> TestResult inverseComposition (a :> b) =     case eqFL (reverseRL (invertFL (a:>:b:>:NilFL))) (invert b:>:invert a:>:NilFL) of       IsEq -> succeeded       NotEq -> failed $ redText "inv(a :>: b :>: NilFL) /= inv(b) :>: inv(a) :>: NilFL"  -- | invert rollback   if b = A(a) then a = A'(b)-invertRollback :: (ApplyState p ~ RepoState model, Patchy p, ShowPatchBasic p, RepoModel model)+invertRollback :: (Invert p, Apply p, ApplyState p ~ RepoState model, ShowPatchBasic p, RepoModel model)                 => WithState model p wA wB -> TestResult invertRollback (WithState a x b)   = case maybeFail $ repoApply b (invert x) of@@ -86,10 +83,10 @@                        else failed $ redText "a1: " $$ text (showModel a1)                                   $$ redText " ---- is not equals to a:" $$ text (showModel a)                                   $$ redText "where a was" $$ text (showModel b)-                                  $$ redText "with (invert x) on top:" $$ showPatch (invert x)+                                  $$ redText "with (invert x) on top:" $$ displayPatch (invert x)  -- | recommute   AB ↔ B′A′ if and only if B′A′ ↔ AB-recommute :: (Patchy p, ShowPatchBasic p, MyEq p, MightHaveDuplicate p)+recommute :: (ShowPatchBasic p, Eq2 p, MightHaveDuplicate p)           => (forall wX wY . ((p :> p) wX wY -> Maybe ((p :> p) wX wY)))           -> (p :> p) wA wB -> TestResult recommute c (x :> y) =@@ -103,99 +100,150 @@       | hasDuplicate y' || hasDuplicate x' -> rejected       | otherwise ->        case c (y' :> x') of-         Nothing -> failed (redText "failed" $$ showPatch y' $$ redText ":>" $$ showPatch x')+         Nothing -> failed (redText "failed, where x" $$ displayPatch x $$+                              redText ":> y" $$ displayPatch y $$+                              redText "y'" $$ displayPatch y' $$+                              redText ":> x'" $$ displayPatch x')          Just (x'' :> y'') ->              case y'' =/\= y of-             NotEq -> failed (redText "y'' =/\\= y failed, where x" $$ showPatch x $$-                              redText ":> y" $$ showPatch y $$-                              redText "y'" $$ showPatch y' $$-                              redText ":> x'" $$ showPatch x' $$-                              redText "x''" $$ showPatch x'' $$-                              redText ":> y''" $$ showPatch y'')+             NotEq -> failed (redText "y'' =/\\= y failed, where x" $$ displayPatch x $$+                              redText ":> y" $$ displayPatch y $$+                              redText "y'" $$ displayPatch y' $$+                              redText ":> x'" $$ displayPatch x' $$+                              redText "x''" $$ displayPatch x'' $$+                              redText ":> y''" $$ displayPatch y'')              IsEq -> case x'' =/\= x of-                     NotEq -> failed (redText "x'' /= x" $$ showPatch x'' $$ redText ":>" $$ showPatch y'')+                     NotEq -> failed (+                              redText "x'' /= x, where x" $$ displayPatch x $$+                              redText ":> y" $$ displayPatch y $$+                              redText "y'" $$ displayPatch y' $$+                              redText ":> x'" $$ displayPatch x' $$+                              redText "x''" $$ displayPatch x'' $$+                              redText ":> y''" $$ displayPatch y'')                      IsEq -> succeeded  -- | commuteInverses   AB ↔ B′A′ if and only if B⁻¹A⁻¹ ↔ A′⁻¹B′⁻¹-commuteInverses :: (Patchy p, ShowPatchBasic p, MyEq p) => (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))-                 -> (p :> p) wA wB -> TestResult+commuteInverses :: (Invert p, ShowPatchBasic p, Eq2 p)+                => (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))+                -> (p :> p) wA wB -> TestResult commuteInverses c (x :> y) =     case c (x :> y) of     Nothing -> rejected     Just (y' :> x') ->         case c (invert y :> invert x) of         Nothing -> failed $ redText "second commute failed" $$-                            redText "x" $$ showPatch x $$ redText "y" $$ showPatch y $$-                            redText "y'" $$ showPatch y' $$ redText "x'" $$ showPatch x'+                            redText "x" $$ displayPatch x $$ redText "y" $$ displayPatch y $$+                            redText "y'" $$ displayPatch y' $$ redText "x'" $$ displayPatch x'         Just (ix' :> iy') ->             case invert ix' =/\= x' of             NotEq -> failed $ redText "invert ix' /= x'" $$-                              redText "x" $$ showPatch x $$-                              redText "y" $$ showPatch y $$-                              redText "y'" $$ showPatch y' $$-                              redText "x'" $$ showPatch x' $$-                              redText "ix'" $$ showPatch ix' $$-                              redText "iy'" $$ showPatch iy' $$-                              redText "invert ix'" $$ showPatch (invert ix') $$-                              redText "invert iy'" $$ showPatch (invert iy')+                              redText "x" $$ displayPatch x $$+                              redText "y" $$ displayPatch y $$+                              redText "y'" $$ displayPatch y' $$+                              redText "x'" $$ displayPatch x' $$+                              redText "ix'" $$ displayPatch ix' $$+                              redText "iy'" $$ displayPatch iy' $$+                              redText "invert ix'" $$ displayPatch (invert ix') $$+                              redText "invert iy'" $$ displayPatch (invert iy')             IsEq -> case y' =\/= invert iy' of-                    NotEq -> failed $ redText "y' /= invert iy'" $$ showPatch iy' $$ showPatch y'+                    NotEq -> failed $ redText "y' /= invert iy'" $$ displayPatch iy' $$ displayPatch y'                     IsEq -> succeeded  -- | effect preserving  AB <--> B'A' then effect(AB) = effect(B'A')-effectPreserving :: (Patchy p, MightBeEmptyHunk p, RepoModel model, ApplyState p ~ RepoState model) =>-                        (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))-                     -> WithState model (p :> p) wA wB -> TestResult-effectPreserving _ (WithState _ (x :> _) _) | isEmptyHunk x = rejected-effectPreserving c (WithState r (x :> y) r')-  = case c (x :> y) of-    Nothing         -> rejected+effectPreserving+  :: ( Apply p+     , MightBeEmptyHunk p+     , RepoModel model+     , ApplyState p ~ RepoState model+     , ShowPatchBasic p+     )+  => (forall wX wY. (p :> p) wX wY -> Maybe ((p :> p) wX wY))+  -> WithState model (p :> p) wA wB+  -> TestResult+effectPreserving _ (WithState _ (x :> _) _)+  | isEmptyHunk x = rejected+effectPreserving c (WithState r (x :> y) r') =+  case c (x :> y) of+    Nothing -> rejected     Just (y' :> x') ->       case maybeFail $ repoApply r y' of-      Nothing  -> failed $ redText "y' is not applicable to r."-      Just r_y' ->-        case maybeFail $ repoApply r_y' x' of-        Nothing     -> failed $ redText "x' is not applicable to r_y'."-        Just r_y'x' -> if r_y'x' `eqModel` r'-                          then succeeded-                          else failed $ redText "r_y'x' is not equal to r'."+        Nothing ->+          failed+          $  redText "##x" $$ displayPatch x+          $$ redText "##y" $$ displayPatch y+          $$ redText "##y'" $$ displayPatch y'+          $$ redText "##x'" $$ displayPatch x'+          $$ redText "##y' is not applicable to r"+          $$ displayModel r+        Just r_y' ->+          case maybeFail $ repoApply r_y' x' of+            Nothing ->+              failed+              $  redText "##x" $$ displayPatch x+              $$ redText "##y" $$ displayPatch y+              $$ redText "##y'" $$ displayPatch y'+              $$ redText "##x'" $$ displayPatch x'+              $$ redText "##x' is not applicable to r_y'"+              $$ displayModel r_y'+            Just r_y'x' ->+              if r_y'x' `eqModel` r'+                then succeeded+                else+                  failed+                  $  redText "##x" $$ displayPatch x+                  $$ redText "##y" $$ displayPatch y+                  $$ redText "##y'" $$ displayPatch y'+                  $$ redText "##x'" $$ displayPatch x'+                  $$ redText "##r_y'x'"+                  $$ displayModel r_y'x'+                  $$ redText "##is not equal to r'"+                  $$ displayModel r'+  where+    displayModel = text . showModel  -- | patchAndInverseCommute   If AB ↔ B′A′ then A⁻¹B′ ↔ BA′⁻¹-patchAndInverseCommute :: (Patchy p, ShowPatchBasic p, MyEq p) =>-                             (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))-                          -> (p :> p) wA wB -> TestResult+patchAndInverseCommute+  :: (Invert p, ShowPatchBasic p, Eq2 p)+  => (forall wX wY. (p :> p) wX wY -> Maybe ((p :> p) wX wY))+  -> (p :> p) wA wB+  -> TestResult patchAndInverseCommute c (x :> y) =   case c (x :> y) of-  Nothing -> rejected-  Just (y' :> x') ->-     case c (invert x :> y') of-       Nothing -> failed (redText ""-                          $$ redText "-------- original commute (x :> y):"-                          $$ showPatch x $$ redText ":>" $$ showPatch y-                          $$ redText "-------- result (y' :> x'):"-                          $$ showPatch y' $$ redText ":>" $$ showPatch x'-                          $$ redText "-------- bad commute (invert x :> y'):"-                          $$ showPatch (invert x) $$ redText ":>" $$ showPatch y')-       Just (y'' :> ix') ->-           case y'' =\/= y of-           NotEq -> failed (redText "y'' /= y" $$-                            redText "x" $$ showPatch x $$-                            redText "y" $$ showPatch y $$-                            redText "x'" $$ showPatch x' $$-                            redText "y'" $$ showPatch y' $$-                            redText "y''" $$ showPatch y'' $$-                            redText ":> x'" $$ showPatch x')-           IsEq -> case x' =\/= invert ix' of-                   NotEq -> failed (redText "x' /= invert ix'" $$-                                    redText "y''" $$ showPatch y'' $$-                                    redText ":> x'" $$ showPatch x' $$-                                    redText "invert x" $$ showPatch (invert x) $$-                                    redText ":> y" $$ showPatch y $$-                                    redText "y'" $$ showPatch y' $$-                                    redText "ix'" $$ showPatch ix')-                   IsEq -> succeeded+    Nothing -> rejected+    Just (y' :> x') ->+      case c (invert x :> y') of+        Nothing ->+          failed $+          redText "-------- original (x :> y)" $$+          displayPatch x $$ redText ":>" $$ displayPatch y $$+          redText "-------- result (y' :> x')" $$+          displayPatch y' $$ redText ":>" $$ displayPatch x' $$+          redText "-------- failed commute (invert x :> y')" $$+          displayPatch (invert x) $$ redText ":>" $$ displayPatch y'+        Just (y'' :> ix') ->+          case y'' =\/= y of+            NotEq ->+              failed $ redText "y'' /= y" $$+              redText "x" $$ displayPatch x $$+              redText "y" $$ displayPatch y $$+              redText "y'" $$ displayPatch y' $$+              redText "x'" $$ displayPatch x' $$+              redText "y''" $$ displayPatch y'' $$+              redText "ix'" $$ displayPatch ix'+            IsEq ->+              case x' =\/= invert ix' of+                NotEq ->+                  failed $ redText "x' /= invert ix'" $$+                  redText "x" $$ displayPatch x $$+                  redText "y" $$ displayPatch y $$+                  redText "y'" $$ displayPatch y' $$+                  redText "x'" $$ displayPatch x' $$+                  redText "invert x" $$ displayPatch (invert x) $$+                  redText "y'" $$ displayPatch y' $$+                  redText "invert ix'" $$ displayPatch (invert ix')+                IsEq -> succeeded -permutivity :: (Patchy p, ShowPatchBasic p, MyEq p) => (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))+permutivity :: (ShowPatchBasic p, Eq2 p) => (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))             -> (p :> p :> p) wA wB -> TestResult permutivity c (x:>y:>z) =   case c (x :> y) of@@ -212,8 +260,8 @@           Just (z4 :> x4) ->             --traceDoc (greenText "third commuted" $$             --          greenText "about to commute" $$-            --          greenText "y1" $$ showPatch y1 $$-            --          greenText "z4" $$ showPatch z4) $+            --          greenText "y1" $$ displayPatch y1 $$+            --          greenText "z4" $$ displayPatch z4) $             case c (y1 :> z4) of             Nothing -> failed $ redText "permutivity2"             Just (z3_ :> y4)@@ -221,68 +269,77 @@                      --traceDoc (greenText "passed z3") $ error "foobar test" $                      case c (y4 :> x4) of                      Nothing -> failed $ redText "permutivity5: input was" $$-                                         redText "x" $$ showPatch x $$-                                         redText "y" $$ showPatch y $$-                                         redText "z" $$ showPatch z $$-                                         redText "z3" $$ showPatch z3 $$+                                         redText "x" $$ displayPatch x $$+                                         redText "y" $$ displayPatch y $$+                                         redText "z" $$ displayPatch z $$+                                         redText "z3" $$ displayPatch z3 $$                                          redText "failed commute of" $$-                                         redText "y4" $$ showPatch y4 $$-                                         redText "x4" $$ showPatch x4 $$+                                         redText "y4" $$ displayPatch y4 $$+                                         redText "x4" $$ displayPatch x4 $$                                          redText "whereas commute of x and y give" $$-                                         redText "y1" $$ showPatch y1 $$-                                         redText "x1" $$ showPatch x1+                                         redText "y1" $$ displayPatch y1 $$+                                         redText "x1" $$ displayPatch x1                      Just (x3_ :> y2_)                           | NotEq <- x3_ =\/= x3 -> failed $ redText "permutivity6"                           | NotEq <- y2_ =/\= y2 -> failed $ redText "permutivity7"                           | otherwise -> succeeded                 | otherwise ->                     failed $ redText "permutivity failed" $$-                             redText "z3" $$ showPatch z3 $$-                             redText "z3_" $$ showPatch z3_+                             redText "z3" $$ displayPatch z3 $$+                             redText "z3_" $$ displayPatch z3_ -partialPermutivity :: (Patchy p, ShowPatchBasic p) => (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))-                    -> (p :> p :> p) wA wB -> TestResult-partialPermutivity c (xx:>yy:>zz) = pp (xx:>yy:>zz) <&&> pp (invert zz:>invert yy:>invert xx)-    where pp (x:>y:>z) =-            case c (y :> z) of+partialPermutivity+  :: (Invert p, ShowPatchBasic p)+  => (forall wX wY. (p :> p) wX wY -> Maybe ((p :> p) wX wY))+  -> (p :> p :> p) wA wB+  -> TestResult+partialPermutivity c (xx :> yy :> zz) =+  pp (xx :> yy :> zz) <&&> pp (invert zz :> invert yy :> invert xx)+  where+    pp (x :> y :> z) =+      case c (y :> z) of+        Nothing -> rejected+        Just (z1 :> y1) ->+          case c (x :> z1) of             Nothing -> rejected-            Just (z1 :> y1) ->-              case c (x :> z1) of-              Nothing -> rejected-              Just (_ :> x1) ->-                case c (x :> y) of-                  Just _ -> rejected -- this is covered by full permutivity test above-                  Nothing ->-                      case c (x1 :> y1) of-                      Nothing -> succeeded-                      Just _ -> failed $ greenText "partialPermutivity error" $$-                                         greenText "x" $$ showPatch x $$-                                         greenText "y" $$ showPatch y $$-                                         greenText "z" $$ showPatch z+            Just (_ :> x1) ->+              case c (x :> y) of+                Just _ -> rejected -- this is covered by full permutivity test above+                Nothing ->+                  case c (x1 :> y1) of+                    Nothing -> succeeded+                    Just _ ->+                      failed $+                      greenText "partialPermutivity error" $$ greenText "x" $$+                      displayPatch x $$+                      greenText "y" $$+                      displayPatch y $$+                      greenText "z" $$+                      displayPatch z -mergeArgumentsConsistent :: (Patchy p, ShowPatchBasic p) =>+mergeArgumentsConsistent :: (ShowPatchBasic p) =>                               (forall wX wY . p wX wY -> Maybe Doc)                            -> (p :\/: p) wA wB -> TestResult mergeArgumentsConsistent isConsistent (x :\/: y) =   fromMaybe $-    msum [(\z -> redText "mergeArgumentsConsistent x" $$ showPatch x $$ z) `fmap` isConsistent x,-          (\z -> redText "mergeArgumentsConsistent y" $$ showPatch y $$ z) `fmap` isConsistent y]+    msum [(\z -> redText "mergeArgumentsConsistent x" $$ displayPatch x $$ z) `fmap` isConsistent x,+          (\z -> redText "mergeArgumentsConsistent y" $$ displayPatch y $$ z) `fmap` isConsistent y] -mergeConsistent :: (Patchy p, ShowPatchBasic p, Merge p) =>+mergeConsistent :: (ShowPatchBasic p, Merge p) =>                            (forall wX wY . p wX wY -> Maybe Doc)                         -> (p :\/: p) wA wB -> TestResult mergeConsistent isConsistent (x :\/: y) =     case merge (x :\/: y) of     y' :/\: x' ->       fromMaybe $-        msum [(\z -> redText "mergeConsistent x" $$ showPatch x $$ z) `fmap` isConsistent x,-              (\z -> redText "mergeConsistent y" $$ showPatch y $$ z) `fmap` isConsistent y,-              (\z -> redText "mergeConsistent x'" $$ showPatch x' $$ z $$-                     redText "where x' comes from x" $$ showPatch x $$-                     redText "and y" $$ showPatch y) `fmap` isConsistent x',-              (\z -> redText "mergeConsistent y'" $$ showPatch y' $$ z) `fmap` isConsistent y']+        msum [(\z -> redText "mergeConsistent x" $$ displayPatch x $$ z) `fmap` isConsistent x,+              (\z -> redText "mergeConsistent y" $$ displayPatch y $$ z) `fmap` isConsistent y,+              (\z -> redText "mergeConsistent x'" $$ displayPatch x' $$ z $$+                     redText "where x' comes from x" $$ displayPatch x $$+                     redText "and y" $$ displayPatch y) `fmap` isConsistent x',+              (\z -> redText "mergeConsistent y'" $$ displayPatch y' $$ z) `fmap` isConsistent y'] -mergeEitherWay :: (Patchy p, MyEq p, Merge p) => (p :\/: p) wX wY -> TestResult+mergeEitherWay :: (Eq2 p, Merge p) => (p :\/: p) wX wY -> TestResult mergeEitherWay (x :\/: y) =     case merge (x :\/: y) of     y' :/\: x' -> case merge (y :\/: x) of@@ -290,7 +347,7 @@                                  IsEq <- y'' =\/= y' -> succeeded                                | otherwise -> failed $ redText "mergeEitherWay bug" -mergeCommute :: (Patchy p, MyEq p, ShowPatchBasic p, Merge p, MightHaveDuplicate p)+mergeCommute :: (Eq2 p, ShowPatchBasic p, Merge p, MightHaveDuplicate p)              => (p :\/: p) wX wY -> TestResult mergeCommute (x :\/: y) =     case merge (x :\/: y) of@@ -303,36 +360,36 @@      | otherwise ->         case commute (x :> y') of         Nothing -> failed $ redText "mergeCommute 1" $$-                            redText "x" $$ showPatch x $$-                            redText "y" $$ showPatch y $$-                            redText "x'" $$ showPatch x' $$-                            redText "y'" $$ showPatch y'+                            redText "x" $$ displayPatch x $$+                            redText "y" $$ displayPatch y $$+                            redText "x'" $$ displayPatch x' $$+                            redText "y'" $$ displayPatch y'         Just (y_ :> x'_)             | IsEq <- y_ =\/= y,               IsEq <- x'_ =\/= x' ->                       case commute (y :> x') of                       Nothing -> failed $ redText "mergeCommute 2 failed" $$-                                          redText "x" $$ showPatch x $$-                                          redText "y" $$ showPatch y $$-                                          redText "x'" $$ showPatch x' $$-                                          redText "y'" $$ showPatch y'+                                          redText "x" $$ displayPatch x $$+                                          redText "y" $$ displayPatch y $$+                                          redText "x'" $$ displayPatch x' $$+                                          redText "y'" $$ displayPatch y'                       Just (x_ :> y'_)                            | IsEq <- x_ =\/= x,                              IsEq <- y'_ =\/= y' -> succeeded                            | otherwise -> failed $ redText "mergeCommute 3" $$-                                                   redText "x" $$ showPatch x $$-                                                   redText "y" $$ showPatch y $$-                                                   redText "x'" $$ showPatch x' $$-                                                   redText "y'" $$ showPatch y' $$-                                                   redText "x_" $$ showPatch x_ $$-                                                   redText "y'_" $$ showPatch y'_+                                                   redText "x" $$ displayPatch x $$+                                                   redText "y" $$ displayPatch y $$+                                                   redText "x'" $$ displayPatch x' $$+                                                   redText "y'" $$ displayPatch y' $$+                                                   redText "x_" $$ displayPatch x_ $$+                                                   redText "y'_" $$ displayPatch y'_             | otherwise -> failed $ redText "mergeCommute 4" $$-                                    redText "x" $$ showPatch x $$-                                    redText "y" $$ showPatch y $$-                                    redText "x'" $$ showPatch x' $$-                                    redText "y'" $$ showPatch y' $$-                                    redText "x'_" $$ showPatch x'_ $$-                                    redText "y_" $$ showPatch y_+                                    redText "x" $$ displayPatch x $$+                                    redText "y" $$ displayPatch y $$+                                    redText "x'" $$ displayPatch x' $$+                                    redText "y'" $$ displayPatch y' $$+                                    redText "x'_" $$ displayPatch x'_ $$+                                    redText "y_" $$ displayPatch y_   -- | coalesce effect preserving@@ -345,9 +402,24 @@        Nothing -> rejected        Just x  -> case maybeFail $ repoApply r x of                        Nothing  -> failed $ redText "x is not applicable to r."+                                        $$ text (showModel r)+                                        $$ displayPatch x+                                        $$ redText "a:>b"+                                        $$ displayPatch a $$ displayPatch b+                                        $$ redText "r'="+                                        $$ text (showModel r')                        Just r_x -> if r_x `eqModel` r'                                       then succeeded-                                      else failed $ redText "r_x /= r'"+                                      else failed $ redText "r_x /= r', r="+                                        $$ text (showModel r)+                                        $$ redText "a:>b="+                                        $$ displayPatch a $$ displayPatch b+                                        $$ redText "x="+                                        $$ displayPatch x+                                        $$ redText "r'="+                                        $$ text (showModel r')+                                        $$ redText "r_x="+                                        $$ text (showModel r_x)  coalesceCommute           :: (PrimPatch prim, MightBeEmptyHunk prim)@@ -358,29 +430,59 @@     case j (b :> c) of     Nothing -> rejected     Just x  ->-       case commuteFLorComplain (a :> b :>: c :>: NilFL) of-        Right (b' :>: c' :>: NilFL :> a') ->-           case commute (a:>:NilFL :> x) of-             Just (x' :> a'':>:NilFL) ->-                 case a'' =/\= a' of-                 NotEq -> failed $ greenText "coalesceCommute 3"-                 IsEq -> case j (b' :> c') of-                         Nothing -> failed $ greenText "coalesceCommute 4"-                         Just x'' -> case x' =\/= x'' of-                                     NotEq -> failed $ greenText "coalesceCommute 5"-                                     IsEq -> succeeded-             _ -> failed $ greenText "coalesceCommute 1"+      case commuteFL (a :> b :>: c :>: NilFL) of+        Just (b' :>: c' :>: NilFL :> a') ->+          case commuteFL (a :> x) of+            Just (x' :> a'') ->+              case a'' =/\= a' of+                NotEq ->+                  failed $ greenText "a'' =/\\= a' failed"+                    $$ display1+                    $$ display2+                IsEq ->+                  case j (b' :> c') of+                    Nothing ->+                      failed $ greenText "coalesce (b':>c') failed"+                        $$ display1+                        $$ display2+                    Just x'' ->+                      case x' =\/= x'' of+                        NotEq ->+                          failed $ greenText "x' =\\/= x'' failed"+                            $$ display1+                            $$ display2+                            $$ display3+                        IsEq -> succeeded+                      where+                        display3 = redText "## coalesce (b':>c') => x''"+                                   $$ displayPatch x''+              where+                display2 =+                     redText "## commute (a:>x) => x'" $$ displayPatch x'+                  $$ redText "## :> a''" $$ displayPatch a''+            _ -> failed $ greenText "commute a x failed" $$ display1+          where+            display1 =+                 redText "## a" $$ displayPatch a+              $$ redText "## b" $$ displayPatch b+              $$ redText "## c" $$ displayPatch c+              $$ redText "## coalesce (b:>c) => x" $$ displayPatch x+              $$ redText "## commute (a:>b:>c) => a'" $$ displayPatch a'+              $$ redText "## b'" $$ displayPatch b'+              $$ redText "## c'" $$ displayPatch c'         _ -> rejected -show_read :: (Show2 p, MyEq p, ReadPatch p, ShowPatchBasic p, Patchy p) => p wA wB -> TestResult-show_read p = let ps = renderPS Standard (showPatch p)+-- note: we would normally use displayPatch in the failure message+-- but that would be very misleading here+show_read :: (Show2 p, Eq2 p, ReadPatch p, ShowPatchBasic p) => p wA wB -> TestResult+show_read p = let ps = renderPS (showPatch ForStorage p)               in case readPatch ps of-                 Nothing -> failed (redText "unable to read " $$ showPatch p)+                 Nothing -> failed (redText "unable to read " $$ showPatch ForStorage p)                  Just (Sealed p'  ) | IsEq <- p' =\/= p -> succeeded                                     | otherwise -> failed $ redText "trouble reading patch p" $$-                                                            showPatch p $$+                                                            showPatch ForStorage p $$                                                             redText "reads as p'" $$-                                                            showPatch p' $$+                                                            showPatch ForStorage p' $$                                                             redText "aka" $$                                                             greenText (show2 p) $$                                                             redText "and" $$
harness/Darcs/Test/Patch/Properties/GenericUnwitnessed.hs view
@@ -14,84 +14,82 @@ import Darcs.Test.Patch.WSub import Darcs.Test.Util.TestResult -import Darcs.Patch.Prim.V1 ( Prim )-import Darcs.Patch.Patchy ( showPatch )+import Darcs.Patch.Invert ( Invert ) import Darcs.Patch.Read ( ReadPatch )-import Darcs.Patch.Show ( ShowPatchBasic )+import Darcs.Patch.Show ( ShowPatchBasic, displayPatch ) import Darcs.Patch.Witnesses.Show import Darcs.Patch.Witnesses.Eq import Darcs.Patch.Witnesses.Sealed( Sealed ) import Darcs.Patch.Merge ( Merge )-import Darcs.Patch ( Patchy ) import Darcs.Util.Printer ( Doc, redText, ($$) ) import qualified Darcs.Util.Tree as T ( Tree )  -permutivity :: (Patchy wp, ShowPatchBasic wp, MyEq wp, WSub wp p)+permutivity :: (ShowPatchBasic wp, Eq2 wp, WSub wp p)             => (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))             -> (p :> p :> p) wA wB -> TestResult permutivity f = W.permutivity (fmap toW . f . fromW) . toW -partialPermutivity :: (Patchy wp, ShowPatchBasic wp, MyEq wp, WSub wp p)+partialPermutivity :: (Invert wp, ShowPatchBasic wp, Eq2 wp, WSub wp p)                     => (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))                     -> (p :> p :> p) wA wB -> TestResult partialPermutivity f = W.partialPermutivity (fmap toW . f . fromW) . toW -mergeEitherWay :: (Patchy wp, ShowPatchBasic wp, MyEq wp, Merge wp, WSub wp p) => (p :\/: p) wX wY -> TestResult+mergeEitherWay :: (ShowPatchBasic wp, Eq2 wp, Merge wp, WSub wp p) => (p :\/: p) wX wY -> TestResult mergeEitherWay = W.mergeEitherWay . toW -commuteInverses :: (Patchy wp, ShowPatchBasic wp, MyEq wp, WSub wp p)+commuteInverses :: (Invert wp, ShowPatchBasic wp, Eq2 wp, WSub wp p)                  => (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))                  -> (p :> p) wA wB -> TestResult commuteInverses f = W.commuteInverses (fmap toW . f . fromW) . toW -recommute :: (Patchy wp, ShowPatchBasic wp, MightHaveDuplicate wp, MyEq wp, WSub wp p)+recommute :: (ShowPatchBasic wp, MightHaveDuplicate wp, Eq2 wp, WSub wp p)           => (forall wX wY . ((p :> p) wX wY -> Maybe ((p :> p) wX wY)))           -> (p :> p) wA wB -> TestResult recommute f = W.recommute (fmap toW . f . fromW) . toW -mergeCommute :: (Patchy wp, MightHaveDuplicate wp, ShowPatchBasic wp, MyEq wp, Merge wp, WSub wp p)+mergeCommute :: (MightHaveDuplicate wp, ShowPatchBasic wp, Eq2 wp, Merge wp, WSub wp p)              => (p :\/: p) wX wY -> TestResult mergeCommute = W.mergeCommute . toW -mergeConsistent :: (Patchy wp, Merge wp, ShowPatchBasic wp, WSub wp p) =>+mergeConsistent :: (Merge wp, ShowPatchBasic wp, WSub wp p) =>                            (forall wX wY . p wX wY -> Maybe Doc)                         -> (p :\/: p) wA wB -> TestResult mergeConsistent f = W.mergeConsistent (f . fromW) . toW -mergeArgumentsConsistent :: (Patchy wp, ShowPatchBasic wp, WSub wp p) =>+mergeArgumentsConsistent :: (ShowPatchBasic wp, WSub wp p) =>                               (forall wX wY . p wX wY -> Maybe Doc)                            -> (p :\/: p) wA wB -> TestResult mergeArgumentsConsistent f = W.mergeArgumentsConsistent (f . fromW) . toW -show_read :: (Patchy p, ShowPatchBasic p, ReadPatch p, MyEq p, Show2 p) => p wX wY -> TestResult+show_read :: (ShowPatchBasic p, ReadPatch p, Eq2 p, Show2 p) => p wX wY -> TestResult show_read = W.show_read -patchAndInverseCommute :: (Patchy wp, ShowPatchBasic wp, MyEq wp, WSub wp p) =>+patchAndInverseCommute :: (Invert wp, ShowPatchBasic wp, Eq2 wp, WSub wp p) =>                              (forall wX wY . (p :> p) wX wY -> Maybe ((p :> p) wX wY))                           -> (p :> p) wA wB -> TestResult patchAndInverseCommute f = W.patchAndInverseCommute (fmap toW . f . fromW) . toW  -coalesceCommute :: MightBeEmptyHunk Prim-                => (forall wX wY . (Prim :> Prim) wX wY -> Maybe (FL Prim wX wY))-                -> (Prim :> Prim :> Prim) wA wB -> TestResult+coalesceCommute :: MightBeEmptyHunk Prim2+                => (forall wX wY . (Prim2 :> Prim2) wX wY -> Maybe (FL Prim2 wX wY))+                -> (Prim2 :> Prim2 :> Prim2) wA wB -> TestResult coalesceCommute f = W.coalesceCommute (fmap toW . f . fromW) . toW  consistentTreeFlattenings :: (RepoState model ~ T.Tree, RepoModel model)-                          => Sealed (WithStartState model (Tree Prim)) -> TestResult+                          => Sealed (WithStartState model (Tree Prim2)) -> TestResult consistentTreeFlattenings = (\x -> if W.propConsistentTreeFlattenings x                                       then succeeded                                       else failed $ redText "oops") -commuteFails :: (MyEq p, Patchy p, ShowPatchBasic p)+commuteFails :: (Eq2 p, ShowPatchBasic p)              => ((p :> p) wX wY -> Maybe ((p :> p) wX wY))              -> (p :> p) wX wY              -> TestResult commuteFails c (x :> y) = case c (x :> y) of                             Nothing -> succeeded                             Just (y' :> x') ->-                              failed $ redText "x" $$ showPatch x $$-                                       redText ":> y" $$ showPatch y $$-                                       redText "y'" $$ showPatch y' $$-                                       redText ":> x'" $$ showPatch x'+                              failed $ redText "x" $$ displayPatch x $$+                                       redText ":> y" $$ displayPatch y $$+                                       redText "y'" $$ displayPatch y' $$+                                       redText ":> x'" $$ displayPatch x'
harness/Darcs/Test/Patch/Properties/RepoPatchV2.hs view
@@ -1,19 +1,25 @@-{-# LANGUAGE CPP #-} module Darcs.Test.Patch.Properties.RepoPatchV2        ( propConsistentTreeFlattenings ) where +import Prelude ()+import Darcs.Prelude+ import Darcs.Test.Patch.Arbitrary.Generic ( Tree, flattenTree, G2(..), mapTree ) import Darcs.Test.Patch.WithState import Darcs.Test.Patch.RepoModel ( RepoModel, repoApply, showModel, eqModel, RepoState                                   , Fail, maybeFail ) import qualified Darcs.Util.Tree as T ( Tree ) -import Darcs.Patch.Witnesses.Sealed( Sealed(..) )-import Darcs.Patch.V2.RepoPatch( prim2repopatchV2 )-import Darcs.Patch.Prim.V1 ( Prim )+import Darcs.Patch.Prim ( fromPrim )+import Darcs.Patch.Witnesses.Sealed ( Sealed(..) )+import qualified Darcs.Patch.V2.Prim as V2 ( Prim )+import Darcs.Patch.V2 ( RepoPatchV2 ) -#include "impossible.h"+type Prim2 = V2.Prim +fromPrim2 :: Prim2 wX wY -> RepoPatchV2 Prim2 wX wY+fromPrim2 = fromPrim+ assertEqualFst :: (RepoModel a, Show b, Show c) => (Fail (a x), b) -> (Fail (a x), c) -> Bool assertEqualFst (x,bx) (y,by)     | Just x' <- maybeFail x, Just y' <- maybeFail y, x' `eqModel` y' = True@@ -26,10 +32,11 @@                   | otherwise = "Nothing"  propConsistentTreeFlattenings :: (RepoState model ~ T.Tree, RepoModel model)-                              => Sealed (WithStartState model (Tree Prim)) -> Bool+                              => Sealed (WithStartState model (Tree Prim2))+                              -> Bool propConsistentTreeFlattenings (Sealed (WithStartState start t))   = fromJust $-    do Sealed (G2 flat) <- return $ flattenTree $ mapTree prim2repopatchV2 t+    do Sealed (G2 flat) <- return $ flattenTree $ mapTree fromPrim2 t        rms <- return $ map (start `repoApply`) flat        return $ and $ zipWith assertEqualFst (zip rms flat) (tail $ zip rms flat) 
harness/Darcs/Test/Patch/Properties/V1Set1.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE CPP #-}-{-# OPTIONS_GHC -fno-warn-orphans #-} module Darcs.Test.Patch.Properties.V1Set1        ( checkMerge, checkMergeEquiv, checkMergeSwap, checkCanon        , checkCommute, checkCantCommute@@ -7,16 +5,17 @@        , tMergeEitherWayValid, tTestCheck ) where  import Darcs.Patch-     ( Patchy, commute, invert, merge, effect+     ( commute, invert, merge, effect      , readPatch, showPatch      , fromPrim, canonize, sortCoalesceFL )-import Darcs.Patch.Prim.V1 ( Prim )+import Darcs.Patch.Invert ( Invert ) import Darcs.Patch.Merge ( Merge ) import Darcs.Patch.Read ( ReadPatch )-import Darcs.Patch.Show ( ShowPatchBasic )+import Darcs.Patch.Show ( ShowPatchBasic, ShowPatchFor(..) ) import qualified Darcs.Patch.V1 as V1 ( RepoPatchV1 )+import qualified Darcs.Patch.V1.Prim as V1 ( Prim(..) ) import Darcs.Test.Patch.Properties.Check ( checkAPatch, Check )-import Darcs.Util.Printer ( renderPS, RenderMode(..) )+import Darcs.Util.Printer ( renderPS ) import Darcs.Patch.Witnesses.Eq import Darcs.Patch.Witnesses.Ordered import Darcs.Patch.Witnesses.Show@@ -27,14 +26,14 @@ import Darcs.Util.Printer ( text )  -type Patch = V1.RepoPatchV1 Prim+type Patch = V1.RepoPatchV1 V1.Prim  -quickmerge :: (Patchy p, Merge p) => (p :\/: p ) wX wY -> p wY wZ+quickmerge :: (Merge p) => (p :\/: p ) wX wY -> p wY wZ quickmerge (p1:\/:p2) = case merge (p1:\/:p2) of                         _ :/\: p1' -> unsafeCoercePEnd p1' -instance MyEq p => Eq ((p :/\: p) wX wY) where+instance Eq2 p => Eq ((p :/\: p) wX wY) where    (x :/\: y) == (x' :/\: y') = isIsEq (x =\/= x') && isIsEq (y =\/= y')  -- ----------------------------------------------------------------------------@@ -130,15 +129,15 @@ -- A few "test" properties, doing things with input patches and giving a OK/not -- OK type of answer. -tShowRead :: (Show2 p, Patchy p, ReadPatch p, ShowPatchBasic p)+tShowRead :: (Show2 p, ReadPatch p, ShowPatchBasic p)           => (forall wX wY wW wZ . p wX wY -> p wW wZ -> Bool) -> forall wX wY . p wX wY -> TestResult tShowRead eq p =-    case readPatch $ renderPS Standard $ showPatch p of+    case readPatch $ renderPS $ showPatch ForStorage p of     Just (Sealed p') -> if p' `eq` p then succeeded                         else failed $ text $ "Failed to read shown:  "++(show2 p)++"\n"     Nothing -> failed $ text $ "Failed to read at all:  "++(show2 p)++"\n" -tMergeEitherWayValid :: forall wX wY p . (Check p, Show2 p, Merge p, Patchy p) => (p :\/: p) wX wY -> TestResult+tMergeEitherWayValid :: forall wX wY p . (Check p, Show2 p, Merge p, Invert p) => (p :\/: p) wX wY -> TestResult tMergeEitherWayValid (p1 :\/: p2) =   case p2 :>: quickmerge (p1:\/: p2) :>: NilFL of   combo2 ->
harness/Darcs/Test/Patch/Properties/V1Set2.hs view
@@ -15,9 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}-- module Darcs.Test.Patch.Properties.V1Set2     ( propCommuteInverse, propPatchAndInverseIsIdentity     , propSimpleSmartMergeGoodEnough, propCommuteEquivalency@@ -36,7 +33,9 @@     , propUnravelOrderIndependent, propResolveConflictsValid     ) where -import Prelude hiding ( pi )+import Prelude ()+import Darcs.Prelude+ import Test.QuickCheck import Test.Framework.Providers.QuickCheck2 ( testProperty ) import Test.Framework ( Test )@@ -46,24 +45,29 @@  import Darcs.Patch ( invert, commute, merge,                      readPatch, resolveConflicts,-                     fromPrim, showPatch )+                     fromPrim, showPatch, ShowPatchFor(..) ) import Darcs.Patch.Commute ( Commute ) import Darcs.Patch.Invert ( Invert ) import qualified Darcs.Patch.V1 as V1 ( RepoPatchV1 )+import qualified Darcs.Patch.V1.Prim as V1 ( Prim(..) ) import Darcs.Patch.V1.Commute ( unravel, merger )-import Darcs.Patch.Prim.V1 ()-import Darcs.Patch.Prim.V1.Core ( Prim(..) )-import Darcs.Patch.Prim.V1.Commute ( WrappedCommuteFunction(..), Perhaps(..),-                                     subcommutes )-import Darcs.Util.Printer ( renderPS, RenderMode(..) )+import Darcs.Patch.Prim.V1 ( Prim )+import Darcs.Patch.Prim.V1.Commute+    ( Perhaps(..)+    , toPerhaps+    , speedyCommute+    , cleverCommute+    , commuteFiledir+    , commuteFilepatches+    )+import Darcs.Util.Printer ( renderPS ) import Darcs.Patch.Witnesses.Eq import Darcs.Patch.Witnesses.Ordered import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed), unsafeUnseal, unseal, mapSeal, Sealed2(..) ) import Darcs.Patch.Witnesses.Unsafe -#include "impossible.h"--type Patch = V1.RepoPatchV1 Prim+type Prim1 = V1.Prim+type Patch = V1.RepoPatchV1 Prim1   -- | Groups a set of tests by giving them the same prefix in their description.@@ -84,7 +88,7 @@ propCommuteTwice :: Sealed2 (FL Patch :> FL Patch) -> Property propCommuteTwice (Sealed2 (p1:>p2)) =     (doesCommute p1 p2) ==> (Just (p1:>p2) == (commute (p1:>p2) >>= commute))-doesCommute :: (MyEq p, Invert p, Commute p, Check p) => p wX wY -> p wY wZ -> Bool+doesCommute :: (Eq2 p, Invert p, Commute p, Check p) => p wX wY -> p wY wZ -> Bool doesCommute p1 p2 =     commute (p1:>p2) /= Nothing && checkAPatch (p1:>:p2:>:NilFL) propCommuteEquivalency :: Sealed2 (FL Patch :> FL Patch) -> Property@@ -208,9 +212,9 @@     and $ map (\l -> (\ml -> checkAPatch (p+>+ml)) `unseal` mergeList l)             $ resolveConflicts p -mergeList :: [Sealed (FL Prim wX)] -> Sealed (FL Patch wX)+mergeList :: [Sealed (FL Prim1 wX)] -> Sealed (FL Patch wX) mergeList patches = mapFL_FL fromPrim `mapSeal` doml NilFL patches-    where doml :: FL Prim wX wY -> [Sealed (FL Prim wX)] -> Sealed (FL Prim wX)+    where doml :: FL Prim1 wX wY -> [Sealed (FL Prim1 wX)] -> Sealed (FL Prim1 wX)           doml mp (Sealed p:ps) =               case commute (invert p :> mp) of               Just (mp' :> _) -> doml (p +>+ mp') ps@@ -218,7 +222,7 @@           doml mp [] = Sealed mp  propReadShow :: FL Patch wX wY -> Bool-propReadShow p = case readPatch $ renderPS Standard $ showPatch p of+propReadShow p = case readPatch $ renderPS $ showPatch ForStorage p of                    Just (Sealed p') -> isIsEq (p' =\/= p)                    Nothing -> False @@ -234,8 +238,29 @@                                Nothing -> False                                Just (_ :> p1'') -> isIsEq (p1'' =/\= p1) -type CommuteProperty = Sealed2 (Prim :> Prim) -> Property+type CommuteProperty = Sealed2 (Prim1 :> Prim1) -> Property +type CommuteFunction =+    forall wX wY . (Prim1 :> Prim1) wX wY -> Perhaps ((Prim1 :> Prim1) wX wY)++newtype WrappedCommuteFunction = WrappedCommuteFunction+    { runWrappedCommuteFunction :: CommuteFunction }++wrapCommuteFunction :: (forall wX wY . (Prim :> Prim) wX wY -> Perhaps ((Prim :> Prim) wX wY)) -> WrappedCommuteFunction+wrapCommuteFunction f = WrappedCommuteFunction $+  \(p :> q) -> do+    q' :> p' <- f (V1.unPrim p :> V1.unPrim q)+    return (V1.Prim q' :> V1.Prim p')++subcommutes :: [(String, WrappedCommuteFunction)]+subcommutes =+    [("speedyCommute", wrapCommuteFunction speedyCommute),+     ("commuteFiledir", wrapCommuteFunction (cleverCommute commuteFiledir)),+     ("commuteFilepatches", wrapCommuteFunction (cleverCommute commuteFilepatches)),+     ("commutex", wrapCommuteFunction (toPerhaps . commute))+    ]++ subcommutesInverse :: [(String, CommuteProperty)] subcommutesInverse = zip names (map prop_subcommute cs)     where (names, cs) = unzip subcommutes@@ -297,19 +322,19 @@                  Failed -> True                  _ -> False -doesFail :: WrappedCommuteFunction -> Prim wX wY -> Prim wY wZ -> Bool+doesFail :: WrappedCommuteFunction -> Prim1 wX wY -> Prim1 wY wZ -> Bool doesFail c p1 p2 =     fails (runWrappedCommuteFunction c (p1 :> p2)) && checkAPatch (p1 :>: p2 :>: NilFL)         where fails Failed = True               fails _ = False -does :: WrappedCommuteFunction -> Prim wX wY -> Prim wY wZ -> Bool+does :: WrappedCommuteFunction -> Prim1 wX wY -> Prim1 wY wZ -> Bool does c p1 p2 =     succeeds (runWrappedCommuteFunction c (p1 :> p2)) && checkAPatch (p1 :>: p2 :>: NilFL)         where succeeds (Succeeded _) = True               succeeds _ = False -nontrivial :: WrappedCommuteFunction -> Prim wX wY -> Prim wY wZ -> Bool+nontrivial :: WrappedCommuteFunction -> Prim1 wX wY -> Prim1 wY wZ -> Bool nontrivial c p1 p2 =     succeeds (runWrappedCommuteFunction c (p1 :> p2)) && checkAPatch (p1 :>: p2 :>: NilFL)         where succeeds (Succeeded (p2' :> p1' )) = not (p1' `unsafeCompare` p1 && p2' `unsafeCompare` p2)
harness/Darcs/Test/Patch/RepoModel.hs view
@@ -1,5 +1,6 @@ module Darcs.Test.Patch.RepoModel where import Darcs.Patch.Apply ( Apply, ApplyState )+import Darcs.Patch.Witnesses.Ordered ( FL ) import Test.QuickCheck ( Gen )  type Fail = Either String@@ -21,3 +22,4 @@  type family ModelOf (patch :: * -> * -> *) :: * -> * +type instance ModelOf (FL prim) = ModelOf prim
harness/Darcs/Test/Patch/Selection.hs view
@@ -8,8 +8,8 @@ import Darcs.Patch.Witnesses.Ordered ( FL(..), (:>)(..)  ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP ) -import Darcs.Patch.Prim.V1 ( Prim ) import Darcs.Patch.V2 ( RepoPatchV2 )+import qualified Darcs.Patch.V2.Prim as V2 import Darcs.Patch.RepoType ( RepoType(..), RebaseType(..) )  import Darcs.UI.SelectChanges@@ -26,7 +26,7 @@  -- A test module for interactive patch selection. -type Patch = RepoPatchV2 Prim+type Patch = RepoPatchV2 V2.Prim  testSuite :: Test testSuite = testGroup "Darcs.Patch.Selection" $
harness/Darcs/Test/Patch/V1Model.hs view
@@ -1,6 +1,3 @@-{-# LANGUAGE CPP #-}-- -- | Repository model module Darcs.Test.Patch.V1Model   ( V1Model, repoTree@@ -44,14 +41,12 @@ import qualified Data.ByteString.Char8 as BC import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy.Char8 as BLC-import Data.List ( intercalate ) import qualified Data.Map as M import Test.QuickCheck   ( Arbitrary(..)   , Gen, choose, vectorOf, frequency ) -#include "impossible.h"-+-- import Text.Show.Pretty ( ppShow )  ---------------------------------------------------------------------- -- * Model definition@@ -76,17 +71,18 @@ ---------------------------------------- -- Instances +data FlatItem = Dir FilePath | File FilePath [String]+  deriving Show++flattenTree :: Tree Fail -> [FlatItem]+flattenTree = map flattenEntry . T.list where+  flattenEntry (fn, T.SubTree _) = Dir (BC.unpack (flatten fn))+  flattenEntry (fn, T.File blob) = File (BC.unpack (flatten fn))+    (map BLC.unpack $ BLC.lines $ unFail $ T.readBlob blob)+  flattenEntry (_, _) = impossible+ instance Show (V1Model wX) where-  show repo = "V1Model{ "-            ++ intercalate " " (map showEntry $ list repo)-            ++ " }"-    where-        showPath = show . flatten-        showContent content = "[" ++ intercalate " " (map show content) ++ "]"-        showEntry (path,item)-          | isDir item  = showPath path-          | isFile item = showPath path ++ showContent (fileContent item)-        showEntry _ = impossible+  show repo = "V1Model " ++ show (flattenTree (repoTree repo))  instance Show1 V1Model where   showDict1 = ShowDictClass@@ -276,7 +272,7 @@ -- Small repositories help generating (potentially) conflicting patches. instance RepoModel V1Model where   type RepoState V1Model = Tree-  showModel m = show m+  showModel m = show {- ppShow -} m   aSmallRepo = do filesNo <- frequency [(3, return 1), (1, return 2)]                   dirsNo <- frequency [(3, return 1), (1, return 0)]                   aRepo filesNo dirsNo
harness/Darcs/Test/Patch/WSub.hs view
@@ -30,11 +30,14 @@ import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP, unsafeCoercePStart, unsafeCoercePEnd )  import Darcs.Patch.Merge ( Merge )-import Darcs.Patch.Prim.V1 ( Prim ) import Darcs.Patch.V2 ( RepoPatchV2 )-import Darcs.Patch.Patchy ( Commute, Invert(..) )+import qualified Darcs.Patch.V2.Prim as V2+import Darcs.Patch.Commute ( Commute )+import Darcs.Patch.Invert ( Invert(..) ) +type Prim2 = V2.Prim + infixr 5 :>: infixr 5 +>+ infixr 1 :>@@ -85,7 +88,7 @@    fromW = id    toW = id -instance WSub Prim Prim where+instance WSub Prim2 Prim2 where    fromW = id    toW = id @@ -107,7 +110,7 @@ instance (WSub wp p, Show2 wp) => Show2 (FL p) where    showDict2 = ShowDictClass -instance (WSub wp p, Commute wp, MyEq wp) => MyEq (FL p) where+instance (WSub wp p, Commute wp, Eq2 wp) => Eq2 (FL p) where    unsafeCompare x y = unsafeCompare (toW x) (toW y)  instance (WSub wp p, Commute wp, Invert wp) => Invert (FL p) where@@ -126,12 +129,12 @@ commute :: (WSub wp p, Commute wp) => (p :> p) wX wY -> Maybe ((p :> p) wX wY) commute = fmap fromW . W.commute . toW -getPairs :: FL (RepoPatchV2 Prim) wX wY -> [Sealed2 (RepoPatchV2 Prim :> RepoPatchV2 Prim)]+getPairs :: FL (RepoPatchV2 Prim2) wX wY -> [Sealed2 (RepoPatchV2 Prim2 :> RepoPatchV2 Prim2)] getPairs = map (mapSeal2 fromW) . W.getPairs . toW -getTriples :: FL (RepoPatchV2 Prim) wX wY -> [Sealed2 (RepoPatchV2 Prim :> RepoPatchV2 Prim :> RepoPatchV2 Prim)]+getTriples :: FL (RepoPatchV2 Prim2) wX wY -> [Sealed2 (RepoPatchV2 Prim2 :> RepoPatchV2 Prim2 :> RepoPatchV2 Prim2)] getTriples = map (mapSeal2 fromW) . W.getTriples . toW -coalesce :: (Prim :> Prim) wX wY -> Maybe (FL Prim wX wY)+coalesce :: (Prim2 :> Prim2) wX wY -> Maybe (FL Prim2 wX wY) coalesce = fmap fromW . W.coalesce . toW 
harness/Darcs/Test/Patch/WithState.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, MultiParamTypeClasses, ScopedTypeVariables, UndecidableInstances #-}+{-# LANGUAGE MultiParamTypeClasses, ScopedTypeVariables, UndecidableInstances #-}   module Darcs.Test.Patch.WithState
+ harness/Darcs/Test/Repository/Inventory.hs view
@@ -0,0 +1,159 @@+module Darcs.Test.Repository.Inventory where++import Darcs.Repository.Inventory+    ( Inventory(..)+    , HeadInventory+    , ValidHash(..)+    , InventoryHash+    , PatchHash+    , PristineHash+    , getValidHash+    , mkValidHash+    , parseInventory+    , showInventory+    , skipPristineHash+    , peekPristineHash+    , pokePristineHash+    , prop_inventoryParseShow+    , prop_peekPokePristineHash+    , prop_skipPokePristineHash+    )+import Darcs.Patch.Info ( rawPatchInfo )+import Darcs.Util.Printer ( renderPS )++import Darcs.Test.Patch.Info ()++import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC+import Test.Framework ( Test, testGroup )+import Test.Framework.Providers.HUnit ( testCase )+import Test.Framework.Providers.QuickCheck2 ( testProperty )+import Test.HUnit ( Assertion, (@=?) )+import Test.QuickCheck++testSuite :: Test+testSuite = testGroup "Darcs.Repository.Inventory"+ [ testProperty "parse/show roundtrips" prop_inventoryParseShow+ , testProperty "peek gets back what we poked" prop_peekPokePristineHash+ , testProperty "skip/poke roundtrips" prop_skipPokePristineHash+ , testCase "example1" (testInventory rawHeadInv1 headInv1)+ , testCase "example2" (testInventory rawHeadInv2 headInv2)+ ]++instance Arbitrary B.ByteString where+  arbitrary = B.pack <$> arbitrary++instance Arbitrary Inventory where+  arbitrary = uncurry Inventory <$> arbitrary++instance Arbitrary InventoryHash where+  arbitrary = arbitraryHash+instance Arbitrary PatchHash where+  arbitrary = arbitraryHash+instance Arbitrary PristineHash where+  arbitrary = arbitraryHash++arbitraryHash :: ValidHash h => Gen h+arbitraryHash = mkValidHash <$> do+  n <- elements [64, 75] -- see D.R.Cache.okayHash+  vectorOf n $ elements $ '-' : (['0'..'9'] ++ ['a'..'f'])++testInventory :: B.ByteString -> HeadInventory -> Assertion+testInventory raw (vhash,inv) = do+  let hash = getValidHash vhash+  hash @=? peekPristineHash raw+  let rest = skipPristineHash raw+  Just inv @=? parseInventory rest+  rest @=? renderPS (showInventory inv)+  raw @=? renderPS (pokePristineHash hash rest)++headInv1 :: HeadInventory+headInv1 =+  ( mkValidHash "57fb9c1abbed1c0b880e2fffebe32a2163762b87e67e9bf4dcd3168e5abcad83"+  , Inventory+      { inventoryParent = Nothing+      , inventoryPatches =+          [ ( rawPatchInfo+                "20180311141206"+                "Add d/f and e."+                "tester"+                [ "Ignore-this: b541ff7ea385297c8ad07fe58016efa8" ]+                False+            , mkValidHash+                "0000000154-703d7811c2e3f1e1aa81e4be5fab31a291cc18158ec8a75733b6faa5fb406286"+            )+          , ( rawPatchInfo+                "20180311141206"+                "Move d/f to e/f."+                "tester"+                [ "Ignore-this: b71452c8a91c573f7e7fa2e8eb34afd1" ]+                False+            , mkValidHash+                "0000000106-4b1bc6db02d2eea04efe888b64ce853a416c14ae1ae43550b0137f11a8a8dfee"+            )+          ]+      }+  )++rawHeadInv1 :: B.ByteString+rawHeadInv1 = BC.pack+  "pristine:57fb9c1abbed1c0b880e2fffebe32a2163762b87e67e9bf4dcd3168e5abcad83\n\+  \[Add d/f and e.\n\+  \tester**20180311141206\n\+  \ Ignore-this: b541ff7ea385297c8ad07fe58016efa8\n\+  \] \n\+  \hash: 0000000154-703d7811c2e3f1e1aa81e4be5fab31a291cc18158ec8a75733b6faa5fb406286\n\+  \[Move d/f to e/f.\n\+  \tester**20180311141206\n\+  \ Ignore-this: b71452c8a91c573f7e7fa2e8eb34afd1\n\+  \] \n\+  \hash: 0000000106-4b1bc6db02d2eea04efe888b64ce853a416c14ae1ae43550b0137f11a8a8dfee\n\+  \"++headInv2 :: HeadInventory+headInv2 =+  ( mkValidHash "f2f70f1326252fc53077d7cd71769f405618829ba40a8f00f112ac97213f5f4b"+  , Inventory+      { inventoryParent =+          Just+            (mkValidHash+               "0000220070-6ef010a955c38fc4301787092979994bafd366eb50152b66e089deff649d35da")+      , inventoryPatches =+          [ ( rawPatchInfo+                "20160429142058"+                "TAG 2.12.0"+                "Guillaume Hoffmann <guillaumh@gmail.com>"+                [ "Ignore-this: 5c8cbe0424942686a2168f9e6fd8e35d" ]+                False+            , mkValidHash+                "0000088075-e1cc4489099cfff1df5875a8146dc012110c156f3dad839f4632d62ee2331e43"+            )+          , ( rawPatchInfo+                "20160429143015"+                "bump version to 2.13.0"+                "Guillaume Hoffmann <guillaumh@gmail.com>"+                [ "Ignore-this: 7468e30e96f3bf833f4e374e9cc7e515" ]+                False+            , mkValidHash+                "0000000198-0f5455b7c229e132a2fc2173dcce2b567f806c1d3eb1c37fd9fe8d8e42ef4fc9"+            )+          ]+      }+  )++rawHeadInv2 :: B.ByteString+rawHeadInv2 = BC.pack+  "pristine:f2f70f1326252fc53077d7cd71769f405618829ba40a8f00f112ac97213f5f4b\n\+  \Starting with inventory:\n\+  \0000220070-6ef010a955c38fc4301787092979994bafd366eb50152b66e089deff649d35da\n\+  \[TAG 2.12.0\n\+  \Guillaume Hoffmann <guillaumh@gmail.com>**20160429142058\n\+  \ Ignore-this: 5c8cbe0424942686a2168f9e6fd8e35d\n\+  \] \n\+  \hash: 0000088075-e1cc4489099cfff1df5875a8146dc012110c156f3dad839f4632d62ee2331e43\n\+  \[bump version to 2.13.0\n\+  \Guillaume Hoffmann <guillaumh@gmail.com>**20160429143015\n\+  \ Ignore-this: 7468e30e96f3bf833f4e374e9cc7e515\n\+  \] \n\+  \hash: 0000000198-0f5455b7c229e132a2fc2173dcce2b567f806c1d3eb1c37fd9fe8d8e42ef4fc9\n\+  \"
harness/Darcs/Test/Util/TestResult.hs view
@@ -1,4 +1,3 @@- module Darcs.Test.Util.TestResult   ( TestResult   , succeeded@@ -8,56 +7,51 @@   , fromMaybe   , isOk   , isFailed-  )-  where-+  ) where -import Darcs.Util.Printer ( Doc, renderString, RenderMode(..) )+import Darcs.Util.Printer (Doc, renderString)  import qualified Test.QuickCheck.Property as Q ---data TestResult = TestSucceeded-                | TestFailed Doc-                | TestRejected      -- ^ Rejects test case-+data TestResult+  = TestSucceeded+  | TestFailed Doc+  | TestRejected  succeeded :: TestResult succeeded = TestSucceeded -failed :: Doc             -- ^ Error message-          -> TestResult+failed :: Doc -> TestResult failed = TestFailed  rejected :: TestResult rejected = TestRejected --- | @t <&&> s@ fails <=> t or s fails---   @t <&&> s@ succeeds <=> none fails and some succeeds---   @t <&&> s@ is rejected <=> both are rejected+-- | Succeed even if one of the arguments is rejected. (<&&>) :: TestResult -> TestResult -> TestResult-t@(TestFailed _) <&&> _s               = t-_t               <&&> s@(TestFailed _) = s-TestRejected     <&&> s                = s-t                <&&> TestRejected     = t-TestSucceeded    <&&> TestSucceeded    = TestSucceeded+t@(TestFailed _) <&&> _s = t+_t <&&> s@(TestFailed _) = s+TestRejected <&&> s = s+t <&&> TestRejected = t+TestSucceeded <&&> TestSucceeded = TestSucceeded  -- | 'Nothing' is considered success whilst 'Just' is considered failure. fromMaybe :: Maybe Doc -> TestResult-fromMaybe Nothing       = succeeded+fromMaybe Nothing = succeeded fromMaybe (Just errMsg) = failed errMsg  isFailed :: TestResult -> Bool isFailed (TestFailed _) = True-isFailed _other         = False+isFailed _other = False --- | A test is considered OK if it does not fail.+-- | A test is considered Ok if it does not fail. isOk :: TestResult -> Bool isOk = not . isFailed -  -- 'Testable' instance is defined by converting 'TestResult' to 'QuickCheck.Property.Result'+-- | 'Testable' instance is defined by converting 'TestResult' to+-- 'QuickCheck.Property.Result' instance Q.Testable TestResult where-  property TestSucceeded         = Q.property Q.succeeded-  property (TestFailed errorMsg) = Q.property (Q.failed{Q.reason = renderString Encode errorMsg})-  property TestRejected          = Q.property Q.rejected+  property TestSucceeded = Q.property Q.succeeded+  property (TestFailed errorMsg) =+    Q.property (Q.failed {Q.reason = renderString errorMsg})+  property TestRejected = Q.property Q.rejected
− harness/Storage/Hashed/Test.hs
@@ -1,542 +0,0 @@-{-# LANGUAGE ScopedTypeVariables, FlexibleInstances, CPP #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}-module Storage.Hashed.Test( tests ) where--import Prelude hiding ( filter, readFile, writeFile, lookup, (<$>) )-import qualified Prelude-import qualified Data.ByteString.Lazy.Char8 as BL-import qualified Data.ByteString.Char8 as BS-import System.Directory( doesFileExist, removeFile, doesDirectoryExist-                       , createDirectory, removeDirectoryRecursive-                       , setCurrentDirectory )-import System.FilePath( (</>) )-import Control.Monad.Identity-import Control.Monad.Trans( lift )-import Control.Applicative( (<$>) )-import Control.Exception ( catch, IOException )-import Codec.Archive.Zip( extractFilesFromArchive, toArchive )--import Data.Maybe-import Data.Word-import Data.List( sort, intercalate, intersperse )--import Darcs.Util.Path hiding ( setCurrentDirectory )-import Darcs.Util.Tree hiding ( lookup )-import Darcs.Util.Index-import Darcs.Util.Tree.Hashed-import Darcs.Util.Hash-import Darcs.Util.Tree.Monad hiding ( tree, createDirectory )-import Darcs.Util.Tree.Plain--import System.Mem( performGC )--import qualified Data.Set as S-import qualified Data.Map as M--import qualified Bundled.Posix as Posix-    ( getFileStatus, getSymbolicLinkStatus, fileSize, fileExists )--import Test.HUnit hiding ( path )-import Test.Framework( testGroup )-import qualified Test.Framework as TF ( Test )-import Test.QuickCheck--import Test.Framework.Providers.HUnit-import Test.Framework.Providers.QuickCheck2----------------------------- Test Data-----blobs :: [(AnchoredPath, BL.ByteString)]-blobs = [ (floatPath "foo_a", BL.pack "a\n")-        , (floatPath "foo_dir/foo_a", BL.pack "a\n")-        , (floatPath "foo_dir/foo_b", BL.pack "b\n")-        , (floatPath "foo_dir/foo_subdir/foo_a", BL.pack "a\n")-        , (floatPath "foo space/foo\nnewline", BL.pack "newline\n")-        , (floatPath "foo space/foo\\backslash", BL.pack "backslash\n")-        , (floatPath "foo space/foo_a", BL.pack "a\n") ]--files :: [AnchoredPath]-files = map fst blobs--dirs :: [AnchoredPath]-dirs = [ floatPath "foo_dir"-       , floatPath "foo_dir/foo_subdir"-       , floatPath "foo space" ]--emptyStub :: TreeItem IO-emptyStub = Stub (return emptyTree) NoHash--testTree :: Tree IO-testTree =-    makeTree [ (makeName "foo", emptyStub)-             , (makeName "subtree", SubTree sub)-             , (makeName "substub", Stub getsub NoHash) ]-    where sub = makeTree [ (makeName "stub", emptyStub)-                         , (makeName "substub", Stub getsub2 NoHash)-                         , (makeName "x", SubTree emptyTree) ]-          getsub = return sub-          getsub2 = return $ makeTree [ (makeName "file", File emptyBlob)-                                      , (makeName "file2",-                                         File $ Blob (return $ BL.pack "foo") NoHash) ]--equals_testdata :: Tree IO -> IO ()-equals_testdata t = sequence_ [-                     do isJust (findFile t p) @? show p ++ " in tree"-                        ours <- readBlob (fromJust $ findFile t p)-                        ours @?= stored-                     | (p, stored) <- blobs ] >>-                    sequence_ [ isJust (Prelude.lookup p blobs) @? show p ++ " extra in tree"-                                | (p, File _) <- list t ]-------------------------------- Test list-----tests :: [TF.Test]-tests = [ testGroup "Bundled.Posix" posix-        , testGroup "Darcs.Util.Hash" hash-        , testGroup "Darcs.Util.Tree" tree-        , testGroup "Darcs.Util.Index" index-        , testGroup "Darcs.Util.Tree.Monad" monad-        , testGroup "Hashed Storage" hashed ]------------------------------- Tests-----hashed :: [TF.Test]-hashed = [ testCase "plain has all files" have_files-         , testCase "pristine has all files" have_pristine_files-         , testCase "pristine has no extras" pristine_no_extra-         , testCase "pristine file contents match" pristine_contents-         , testCase "plain file contents match" plain_contents-         , testCase "writePlainTree works" write_plain ]-    where-      check_file t f = assertBool-                       ("path " ++ show f ++ " is missing in tree " ++ show t)-                       (isJust $ find t f)-      check_files = forM_ files . check_file--      pristine_no_extra = extractRepoAndRun $-       do-        t <- readDarcsPristine "." >>= expand-        forM_ (list t) $ \(path,_) -> assertBool (show path ++ " is extraneous in tree")-                                                 (path `elem` (dirs ++ files))-      have_files = extractRepoAndRun ( readPlainTree "." >>= expand >>= check_files )-      have_pristine_files = extractRepoAndRun ( readDarcsPristine "." >>= expand >>= check_files )--      pristine_contents = extractRepoAndRun $-       do-        t <- readDarcsPristine "." >>= expand-        equals_testdata t--      plain_contents = extractRepoAndRun $-       do-        t <- expand =<< filter nondarcs `fmap` readPlainTree "."-        equals_testdata t--      write_plain = extractRepoAndRun $-       do-        orig <- readDarcsPristine "." >>= expand-        writePlainTree orig "_darcs/plain"-        t <- expand =<< readPlainTree "_darcs/plain"-        equals_testdata t--index :: [TF.Test]-index = [ testCase "index versioning" check_index_versions-        , testCase "index listing" check_index-        , testCase "index content" check_index_content-        , testProperty "xlate32" prop_xlate32-        , testProperty "xlate64" prop_xlate64-        , testProperty "align bounded" prop_align_bounded-        , testProperty "align aligned" prop_align_aligned ]-    where pristine = readDarcsPristine "." >>= expand-          build_index =-            do x <- pristine-               exist <- doesFileExist "_darcs/index"-               performGC -- required in win32 to trigger file close-               when exist $ removeFile "_darcs/index"-               idx <- updateIndex =<< updateIndexFrom "_darcs/index" darcsTreeHash x-               return (x, idx)-          check_index = extractRepoAndRun $-            do (pris, idx) <- build_index-               (sort $ map fst $ list idx) @?= (sort $ map fst $ list pris)-          check_blob_pair p x y =-              do a <- readBlob x-                 b <- readBlob y-                 assertEqual ("content match on " ++ show p) a b-          check_index_content = extractRepoAndRun $-            do (_, idx) <- build_index-               plain <- readPlainTree "."-               x <- sequence $ zipCommonFiles check_blob_pair plain idx-               assertBool "files match" (length x > 0)-          check_index_versions = extractRepoAndRun $-            do performGC -- required in win32 to trigger file close-               Prelude.writeFile "_darcs/index" "nonsense index... do not crash!"-               valid <- indexFormatValid "_darcs/index"-               assertBool "index format invalid" $ not valid-          prop_xlate32 x = (xlate32 . xlate32) x == x where _types = x :: Word32-          prop_xlate64 x = (xlate64 . xlate64) x == x where _types = x :: Word64-          prop_align_bounded (bound, x) =-              bound > 0 && bound < 1024 && x >= 0 ==>-                    align bound x >= x && align bound x < x + bound-              where _types = (bound, x) :: (Int, Int)-          prop_align_aligned (bound, x) =-              bound > 0 && bound < 1024 && x >= 0 ==>-                    align bound x `rem` bound == 0-              where _types = (bound, x) :: (Int, Int)--tree :: [TF.Test]-tree = [ testCase "modifyTree" check_modify-       , testCase "complex modifyTree" check_modify_complex-       , testCase "modifyTree removal" check_modify_remove-       , testCase "expand" check_expand-       , testCase "expandPath" check_expand_path-       , testCase "expandPath of sub" check_expand_path_sub-       , testCase "diffTrees" check_diffTrees-       , testCase "diffTrees identical" check_diffTrees_ident-       , testProperty "expandPath" prop_expandPath-       , testProperty "shapeEq" prop_shape_eq-       , testProperty "expandedShapeEq" prop_expanded_shape_eq-       , testProperty "expand is identity" prop_expand_id-       , testProperty "filter True is identity" prop_filter_id-       , testProperty "filter False is empty" prop_filter_empty-       , testProperty "restrict both ways keeps shape" prop_restrict_shape_commutative-       , testProperty "restrict is a subtree of both" prop_restrict_subtree-       , testProperty "overlay keeps shape" prop_overlay_shape-       , testProperty "overlay is superset of over" prop_overlay_super ]-    where blob x = File $ Blob (return (BL.pack x)) (sha256 $ BL.pack x)-          name = Name . BS.pack-          check_modify =-              let t = makeTree [(name "foo", blob "bar")]-                  modify = modifyTree t (floatPath "foo") (Just $ blob "bla")-               in do x <- readBlob $ fromJust $ findFile t (floatPath "foo")-                     y <- readBlob $ fromJust $ findFile modify (floatPath "foo")-                     assertEqual "old version" x (BL.pack "bar")-                     assertEqual "new version" y (BL.pack "bla")-                     assertBool "list has foo" $-                                isJust (Prelude.lookup (floatPath "foo") $ list modify)-                     length (list modify) @?= 1-          check_modify_complex =-              let t = makeTree [ (name "foo", blob "bar")-                               , (name "bar", SubTree t1) ]-                  t1 = makeTree [ (name "foo", blob "bar") ]-                  modify = modifyTree t (floatPath "bar/foo") (Just $ blob "bla")-               in do foo <- readBlob $ fromJust $ findFile t (floatPath "foo")-                     foo' <- readBlob $ fromJust $ findFile modify (floatPath "foo")-                     bar_foo <- readBlob $ fromJust $-                                findFile t (floatPath "bar/foo")-                     bar_foo' <- readBlob $ fromJust $-                                 findFile modify (floatPath "bar/foo")-                     assertEqual "old foo" foo (BL.pack "bar")-                     assertEqual "old bar/foo" bar_foo (BL.pack "bar")-                     assertEqual "new foo" foo' (BL.pack "bar")-                     assertEqual "new bar/foo" bar_foo' (BL.pack "bla")-                     assertBool "list has bar/foo" $-                                isJust (Prelude.lookup (floatPath "bar/foo") $ list modify)-                     assertBool "list has foo" $-                                isJust (Prelude.lookup (floatPath "foo") $ list modify)-                     length (list modify) @?= length (list t)-          check_modify_remove =-              let t1 = makeTree [(name "foo", blob "bar")]-                  t2 :: Tree Identity = makeTree [ (name "foo", blob "bar")-                                                 , (name "bar", SubTree t1) ]-                  modify1 = modifyTree t1 (floatPath "foo") Nothing-                  modify2 = modifyTree t2 (floatPath "bar") Nothing-                  file = findFile modify1 (floatPath "foo")-                  subtree = findTree modify2 (floatPath "bar")-               in do assertBool "file is gone" (isNothing file)-                     assertBool "subtree is gone" (isNothing subtree)--          no_stubs t = null [ () | (_, Stub _ _) <- list t ]-          path = floatPath "substub/substub/file"-          badpath = floatPath "substub/substub/foo"-          check_expand = do-            x <- expand testTree-            assertBool "no stubs in testTree" $ not (no_stubs testTree)-            assertBool "stubs in expanded tree" $ no_stubs x-            assertBool "path reachable" $ path `elem` (map fst $ list x)-            assertBool "badpath not reachable" $-                       badpath `notElem` (map fst $ list x)-          check_expand_path = do-            test_exp <- expand testTree-            t <- expandPath testTree path-            t' <- expandPath test_exp path-            t'' <- expandPath testTree $ floatPath "substub/x"-            assertBool "path not reachable in testTree" $ path `notElem` (map fst $ list testTree)-            assertBool "path reachable in t" $ path `elem` (map fst $ list t)-            assertBool "path reachable in t'" $ path `elem` (map fst $ list t')-            assertBool "path reachable in t (with findFile)" $-                       isJust $ findFile t path-            assertBool "path reachable in t' (with findFile)" $-                       isJust $ findFile t' path-            assertBool "path not reachable in t''" $ path `notElem` (map fst $ list t'')-            assertBool "badpath not reachable in t" $-                       badpath `notElem` (map fst $ list t)-            assertBool "badpath not reachable in t'" $-                       badpath `notElem` (map fst $ list t')--          check_expand_path_sub = do-            t <- expandPath testTree $ floatPath "substub"-            t' <- expandPath testTree $ floatPath "substub/stub"-            t'' <- expandPath testTree $ floatPath "subtree/stub"-            assertBool "leaf is not a Stub" $-                isNothing (findTree testTree $ floatPath "substub")-            assertBool "leaf is not a Stub" $ isJust (findTree t $ floatPath "substub")-            assertBool "leaf is not a Stub (2)" $ isJust (findTree t' $ floatPath "substub/stub")-            assertBool "leaf is not a Stub (3)" $ isJust (findTree t'' $ floatPath "subtree/stub")--          check_diffTrees = extractRepoAndRun $-                 do Prelude.writeFile "foo_dir/foo_a" "b\n"-                    working_plain <- filter nondarcs `fmap` readPlainTree "."-                    working <- updateIndex =<<-                                 updateIndexFrom "_darcs/index" darcsTreeHash working_plain-                    pristine <- readDarcsPristine "."-                    (working', pristine') <- diffTrees working pristine-                    let foo_work = findFile working' (floatPath "foo_dir/foo_a")-                        foo_pris = findFile pristine' (floatPath "foo_dir/foo_a")-                    working' `shapeEq` pristine'-                             @? show working' ++ " `shapeEq` " ++ show pristine'-                    assertBool "foo_dir/foo_a is in working'" $ isJust foo_work-                    assertBool "foo_dir/foo_a is in pristine'" $ isJust foo_pris-                    foo_work_c <- readBlob (fromJust foo_work)-                    foo_pris_c <- readBlob (fromJust foo_pris)-                    BL.unpack foo_work_c @?= "b\n"-                    BL.unpack foo_pris_c @?= "a\n"-                    assertEqual "working' tree is minimal" 2 (length $ list working')-                    assertEqual "pristine' tree is minimal" 2 (length $ list pristine')--          check_diffTrees_ident = do-            pristine <- readDarcsPristine "."-            (t1, t2) <- diffTrees pristine pristine-            assertBool "t1 is empty" $ null (list t1)-            assertBool "t2 is empty" $ null (list t2)--          prop_shape_eq x = no_stubs x ==> x `shapeEq` x-              where _types = x :: Tree Identity-          prop_expanded_shape_eq x = runIdentity $ expandedShapeEq x x-              where _types = x :: Tree Identity-          prop_expand_id x = no_stubs x ==> runIdentity (expand x) `shapeEq` x-              where _types = x :: Tree Identity-          prop_filter_id x = runIdentity $ expandedShapeEq x $ filter (\_ _ -> True) x-              where _types = x :: Tree Identity-          prop_filter_empty x = runIdentity $ expandedShapeEq emptyTree $ filter (\_ _ -> False) x-              where _types = x :: Tree Identity-          prop_restrict_shape_commutative (t1, t2) =-              no_stubs t1 && no_stubs t2 && not (restrict t1 t2 `shapeEq` emptyTree) ==>-                  restrict t1 t2 `shapeEq` restrict t2 t1-              where _types = (t1 :: Tree Identity, t2 :: Tree Identity)-          prop_restrict_subtree (t1, t2) =-              no_stubs t1 && not (restrict t1 t2 `shapeEq` emptyTree) ==>-                  let restricted = S.fromList (map fst $ list $ restrict t1 t2)-                      orig1 = S.fromList (map fst $ list t1)-                      orig2 = S.fromList (map fst $ list t2)-                   in and [restricted `S.isSubsetOf` orig1, restricted `S.isSubsetOf` orig2]-              where _types = (t1 :: Tree Identity, t2 :: Tree Identity)-          prop_overlay_shape (t1 :: Tree Identity, t2) =-              (Just LT == runIdentity (t2 `cmpExpandedShape` t1)) ==>-              runIdentity $ (t1 `overlay` t2) `expandedShapeEq` t1-          prop_overlay_super (t1 :: Tree Identity, t2) =-              (Just LT == runIdentity (t2 `cmpExpandedShape` t1)) && no_stubs t2 ==>-              Just EQ == (runIdentity $ restrict t2 (t1 `overlay` t2) `cmpTree` t2)-          prop_expandPath (TreeWithPath t p) =-              notStub $ find (runIdentity $ expandPath t p) p-            where notStub (Just (Stub _ _)) = False-                  notStub Nothing = error "Did not exist."-                  notStub _ = True--hash :: [TF.Test]-hash = [ testProperty "decodeBase16 . encodeBase16 == id" prop_base16 ]-    where prop_base16 x = (decodeBase16 . encodeBase16) x == x--monad :: [TF.Test]-monad = [ testCase "path expansion" check_virtual-        , testCase "rename" check_rename ]-    where check_virtual = virtualTreeMonad run testTree >> return ()-              where run = do file <- readFile (floatPath "substub/substub/file")-                             file2 <- readFile (floatPath "substub/substub/file2")-                             lift $ BL.unpack file @?= ""-                             lift $ BL.unpack file2 @?= "foo"-          check_rename = do (_, t) <- virtualTreeMonad run testTree-                            t' <- darcsAddMissingHashes =<< expand t-                            forM_ [ (p, i) | (p, i) <- list t' ] $ \(p,i) ->-                               assertBool ("have hash: " ++ show p) $ itemHash i /= NoHash-              where run = do rename (floatPath "substub/substub/file") (floatPath "substub/file2")--posix :: [TF.Test]-posix = [ testCase "getFileStatus" $ check_stat Posix.getFileStatus-        , testCase "getSymbolicLinkStatus" $ check_stat Posix.getSymbolicLinkStatus ]-    where check_stat fun = extractRepoAndRun $ do-            x <- Posix.fileSize `fmap` fun "foo_a"-            Prelude.writeFile "test_empty" ""-            y <- Posix.fileSize `fmap` fun "test_empty"-            exist_nonexistent <- Posix.fileExists `fmap` fun "test_does_not_exist"-            exist_existent <- Posix.fileExists `fmap` fun "test_empty"-            assertEqual "file size" x 2-            assertEqual "file size" y 0-            assertBool "existence check" $ not exist_nonexistent-            assertBool "existence check" exist_existent--------------------------------------- Arbitrary instances-----#if !MIN_VERSION_QuickCheck(2,8,2)--- these instances were added to QuickCheck itself in version 2.8.2-instance (Arbitrary a, Ord a) => Arbitrary (S.Set a)-    where arbitrary = S.fromList `fmap` arbitrary--instance (Arbitrary k, Arbitrary v, Ord k) => Arbitrary (M.Map k v)-    where arbitrary = M.fromList `fmap` arbitrary-#endif--instance Arbitrary BL.ByteString where-    arbitrary = BL.pack `fmap` arbitrary--instance Arbitrary Hash where-    arbitrary = sized hash'-        where hash' 0 = return NoHash-              hash' _ = do-                tag <- oneof [return False, return True]-                case tag of-                  False -> SHA256 . BS.pack <$> sequence [ arbitrary | _ <- [1..32] :: [Int] ]-                  True -> SHA1 . BS.pack <$> sequence [ arbitrary | _ <- [1..20] :: [Int] ]--instance (Monad m) => Arbitrary (TreeItem m) where-  arbitrary = sized tree'-    where tree' 0 = oneof [ return (File emptyBlob), return (SubTree emptyTree) ]-          tree' n = oneof [ file n, subtree n ]-          file 0 = return (File emptyBlob)-          file _ = do content <- arbitrary-                      return (File $ Blob (return content) NoHash)-          subtree n = do branches <- choose (1, n)-                         let sub name = do t <- tree' ((n - 1) `div` branches)-                                           return (makeName $ show name, t)-                         sublist <- mapM sub [0..branches]-                         oneof [ tree' 0-                               , return (SubTree $ makeTree sublist)-                               , return $ (Stub $ return (makeTree sublist)) NoHash ]--instance (Monad m) => Arbitrary (Tree m) where-  arbitrary = do item <- arbitrary-                 case item of-                   File _ -> arbitrary-                   Stub _ _ -> arbitrary-                   SubTree t -> return t--data TreeWithPath = TreeWithPath (Tree Identity) AnchoredPath deriving (Show)--instance Arbitrary TreeWithPath where-  arbitrary = do t <- arbitrary-                 p <- oneof $ return (AnchoredPath []) :-                             (map (return . fst) $ list (runIdentity $ expand t))-                 return $ TreeWithPath t p-------------------------------- Other instances-----instance Show (Blob m) where-    show (Blob _ h) = "Blob " ++ show h--instance Show (TreeItem m) where-    show (File f) = "File (" ++ show f ++ ")"-    show (Stub _ h) = "Stub _ " ++ show h-    show (SubTree s) = "SubTree (" ++ show s ++ ")"--instance Show (Tree m) where-    show t = "Tree " ++ show (treeHash t) ++ " { " ++-             (concat . intersperse ", " $ itemstrs) ++ " }"-        where itemstrs = map show $ listImmediate t--instance Show (Int -> Int) where-    show f = "[" ++ intercalate ", " (map val [1..20]) ++ " ...]"-        where val x = show x ++ " -> " ++ show (f x)---------------------------- Test utilities-----shapeEq :: Tree m -> Tree m -> Bool-shapeEq a b = Just EQ == cmpShape a b--expandedShapeEq :: (Monad m, Functor m) => Tree m -> Tree m -> m Bool-expandedShapeEq a b = (Just EQ ==) <$> cmpExpandedShape a b--cmpcat :: [Maybe Ordering] -> Maybe Ordering-cmpcat (x:y:rest) | x == y = cmpcat (x:rest)-                  | x == Just EQ = cmpcat (y:rest)-                  | y == Just EQ = cmpcat (x:rest)-                  | otherwise = Nothing-cmpcat [x] = x-cmpcat [] = Just EQ -- empty things are equal--cmpTree :: (Monad m, Functor m) => Tree m -> Tree m -> m (Maybe Ordering)-cmpTree x y = do x' <- expand x-                 y' <- expand y-                 con <- contentsEq x' y'-                 return $ cmpcat [cmpShape x' y', con]-    where contentsEq a b = cmpcat <$> sequence (zipTrees cmp a b)-          cmp _ (Just (File a)) (Just (File b)) = do a' <- readBlob a-                                                     b' <- readBlob b-                                                     return $ Just (compare a' b')-          cmp _ _ _ = return (Just EQ) -- neutral--cmpShape :: Tree m -> Tree m -> Maybe Ordering-cmpShape t r = cmpcat $ zipTrees cmp t r-    where cmp _ (Just a) (Just b) = a `item` b-          cmp _ Nothing (Just _) = Just LT-          cmp _ (Just _) Nothing = Just GT-          cmp _ Nothing Nothing = Just EQ-          item (File _) (File _) = Just EQ-          item (SubTree s) (SubTree p) = s `cmpShape` p-          item _ _ = Nothing--cmpExpandedShape :: (Monad m) => Tree m -> Tree m -> m (Maybe Ordering)-cmpExpandedShape a b = do x <- expand a-                          y <- expand b-                          return $ x `cmpShape` y--nondarcs :: AnchoredPath -> TreeItem m -> Bool-nondarcs (AnchoredPath (Name x:_)) _ | x == BS.pack "_darcs" = False-                                     | otherwise = True-nondarcs (AnchoredPath []) _ = True--readDarcsPristine :: FilePath -> IO (Tree IO)-readDarcsPristine dir = do-  let darcs = dir </> "_darcs"-      h_inventory = darcs </> "hashed_inventory"-  repo <- doesDirectoryExist darcs-  unless repo $ fail $ "Not a darcs repository: " ++ dir-  isHashed <- doesFileExist h_inventory-  if isHashed-     then do inv <- BS.readFile h_inventory-             let thelines = BS.split '\n' inv-             case thelines of-               [] -> return emptyTree-               (pris_line:_) -> do-                          let thehash = decodeDarcsHash $ BS.drop 9 pris_line-                              thesize = decodeDarcsSize $ BS.drop 9 pris_line-                          when (thehash == NoHash) $ fail $ "Bad pristine root: " ++ show pris_line-                          readDarcsHashed (darcs </> "pristine.hashed") (thesize, thehash)-     else do have_pristine <- doesDirectoryExist $ darcs </> "pristine"-             have_current <- doesDirectoryExist $ darcs </> "current"-             case (have_pristine, have_current) of-               (True, _) -> readPlainTree $ darcs </> "pristine"-               (False, True) -> readPlainTree $ darcs </> "current"-               (_, _) -> fail "No pristine tree is available!"--extractRepoAndRun :: IO a -> IO a-extractRepoAndRun action =-  do zipFile <- toArchive `fmap` BL.readFile "harness/hstestdata.zip"-     removeDirectoryRecursive "_test_playground" `catch` \(_ :: IOException) -> return ()-     createDirectory "_test_playground"-     setCurrentDirectory "_test_playground"-     extractFilesFromArchive [] zipFile-     result <- action-     setCurrentDirectory ".."-     removeDirectoryRecursive "_test_playground"-     return result-
harness/test.hs view
@@ -3,26 +3,16 @@ {-# OPTIONS_GHC -fno-warn-type-defaults #-} module Main ( main ) where -#ifdef DISABLE_TESTING-main :: IO ()-main = fail $   "test infrastructure not built,"-             ++ " please pass --enable-tests to configure, then rebuild"-#else- import qualified Darcs.Test.Misc import qualified Darcs.Test.Patch import qualified Darcs.Test.Email-import qualified Storage.Hashed.Test+import qualified Darcs.Test.Repository.Inventory+import qualified Darcs.Test.HashedStorage  import Control.Monad ( filterM ) import Control.Exception ( SomeException )-import qualified Control.Monad.Trans import Data.Text ( Text, pack, unpack )-import Data.Char ( toLower ) import Data.List ( isPrefixOf, isSuffixOf, sort )-import Data.List.Split ( splitOn )-import qualified Data.ByteString.Char8 as B-import Data.Maybe ( fromMaybe ) import GHC.IO.Encoding ( textEncodingName ) import System.Console.CmdArgs hiding ( args ) import System.Directory ( doesFileExist )@@ -40,13 +30,14 @@  -- | TODO make runnable in parallel doHashed :: IO [Test]-doHashed = return Storage.Hashed.Test.tests+doHashed = return Darcs.Test.HashedStorage.tests  -- | This is the big list of tests that will be run using testrunner. unitTests :: [Test] unitTests =   [ Darcs.Test.Email.testSuite   , Darcs.Test.Misc.testSuite+  , Darcs.Test.Repository.Inventory.testSuite   ] ++ Darcs.Test.Patch.testSuite  -- ----------------------------------------------------------------------@@ -72,7 +63,7 @@                            , testfile :: FilePath                            , testdir  :: Maybe FilePath -- ^ only if you want to set it explicitly                            , _darcspath :: FilePath-                           , _diffalgorithm :: DiffAlgorithm+                           , diffalgorithm :: DiffAlgorithm                            }                  deriving Typeable @@ -104,17 +95,15 @@                        case code of                         200 -> return Skipped                         _   -> Failed <$> unpack <$> lastStderr-  where defaults = pack $ unlines (["ALL " ++ fmtstr, "send no-edit-description", "ALL ignore-times"] ++ dcs)+  where defaults = pack $ unlines+          [ "ALL " ++ fmtstr+          , "send no-edit-description"+          , "ALL ignore-times"+          , "ALL " ++ daf+          ]         fmtstr = case fmt of                   Darcs2 -> "darcs-2"                   Darcs1 -> "darcs-1"-        dcs = [dc ++ " " ++ daf | dc <- ["revert","unrevert", "whatsnew",-                                         "record", "unpull", "obliterate",-                                         "amend-record", "mark-conflicts",-                                         "rebase", "pull", "repair",-                                         "rollback", "apply",-                                         "rebase pull", "rebase suspend",-                                         "rebase unsuspend", "rebase obliterate"] ]         daf = case da of                 PatienceDiff -> "patience"                 MyersDiff -> "myers"@@ -125,33 +114,19 @@         pathVarSeparator = ":" #endif --- TODO: add a 'all' option (implement using an Enum instance)?-readOptionList :: (String -> a) -> (String -> [a])-readOptionList readElem str = map readElem (splitOn "," str)--readDiffAlgorithm :: String -> DiffAlgorithm-readDiffAlgorithm (map toLower -> "myers") = MyersDiff-readDiffAlgorithm (map toLower -> "patience") = PatienceDiff-readDiffAlgorithm _ = error "Valid diff algorithms: myers, patience"--readRepoFormat :: String -> Format-readRepoFormat (map toLower -> "darcs-1") = Darcs1-readRepoFormat (map toLower -> "darcs-2") = Darcs2-readRepoFormat _ = error "Valid repo formats: darcs-1, darcs-2"- runtest :: ShellTest -> Sh Result runtest t =  withTmp $ \dir -> do   cp "tests/lib" dir   cp "tests/network/sshlib" dir-  cp ("tests" </> testfile t) (dir </> "test")+  cp (fromText $ pack $ testfile t) (dir </> "test")   srcdir <- pwd   silently $ sub $ cd dir >> runtest' t (toTextIgnore srcdir)  where   withTmp =    case testdir t of      Just dir -> \job -> do-       let d = (dir </> show (format t) </> takeBaseName (testfile t))+       let d = (dir </> show (format t) </> show (diffalgorithm t) </> takeBaseName (testfile t))        mkdir_p d        job d      Nothing  -> withTmpDir@@ -162,53 +137,22 @@                                        liftIO (shelly $ runtest test)  shellTest :: FilePath -> Format -> Maybe FilePath -> String -> DiffAlgorithm -> Test-shellTest dp fmt tdir file da = Test (file ++ " (" ++ show fmt ++ ")" ++ " (" ++ show da ++ ")") $ ShellTest fmt file tdir dp da--hasPrefix :: B.ByteString -> B.ByteString -> Maybe B.ByteString-hasPrefix prefix =-    let len = B.length prefix in-    \str -> if B.take len str == prefix then Just (B.drop len str) else Nothing+shellTest dp fmt tdir file da =+  Test (takeBaseName file ++ " (" ++ show fmt ++ ")" ++ " (" ++ show da ++ ")") $+  ShellTest fmt file tdir dp da  toString :: Shelly.FilePath -> String toString = unpack . toTextIgnore --- use of a pragma in a test script overrides the user's selection for that particular test,--- based on the assumption that the test author knows best-parsePragmas :: FilePath -> FilePath -> IO (FilePath, (Maybe [DiffAlgorithm], Maybe [Format]))-parsePragmas path file = do-  contents <- B.lines <$> B.readFile (toString $ path </> file)-  let parseLine-          (_diffAlgorithms, repoFormats)-          (hasPrefix (B.pack "#pragma diff-algorithm ") -> Just (readOptionList readDiffAlgorithm . B.unpack -> newDiffAlgorithms))-         = (Just newDiffAlgorithms, repoFormats)-      parseLine-          (diffAlgorithms, _repoFormats)-          (hasPrefix (B.pack "#pragma repo-format ") -> Just (readOptionList readRepoFormat . B.unpack -> newRepoFormats))-         = (diffAlgorithms, Just newRepoFormats)-      parseLine _ (hasPrefix (B.pack "#pragma ") -> Just pragma) = error $ "Unknown pragma " ++ B.unpack pragma ++ " in " ++ (toString $ path </> file)-      parseLine x _ = x-      pragmas = foldl parseLine (Nothing, Nothing) contents-  return (file, pragmas)--findShell :: FilePath -> Maybe FilePath -> Bool -> [DiffAlgorithm] -> [Format] -> Sh [Test]-findShell dp tdir isFailing diffAlgorithmsDefault repoFormatsDefault =-  do allFiles <- map (drop (length ("tests/"::String)) . toString)  <$> ls (fromText "tests")-     let files = sort $ filter relevant $ filter (".sh" `isSuffixOf`) allFiles-     annotatedFiles <- Control.Monad.Trans.liftIO $ mapM (parsePragmas "tests") files+findShell :: FilePath -> Text -> Maybe FilePath -> Bool -> [DiffAlgorithm] -> [Format] -> Sh [Test]+findShell dp sdir tdir isFailing diffAlgorithms repoFormats =+  do files <- ls (fromText sdir)+     let test_files = sort $ filter relevant $ filter (hasExt "sh") files      return [ shellTest dp fmt tdir file da-            | (file, (diffAlgorithmsPragma, repoFormatsPragma)) <- annotatedFiles-            , fmt <- fromMaybe repoFormatsDefault repoFormatsPragma-            , da <- fromMaybe diffAlgorithmsDefault diffAlgorithmsPragma ]-  where relevant = (if isFailing then id else not) . ("failing-" `isPrefixOf`)--findNetwork :: FilePath -> Maybe FilePath -> [DiffAlgorithm] -> [Format] -> Sh [Test]-findNetwork dp tdir diffAlgorithmsDefault repoFormatsDefault =-  do files <- sort <$> filter (".sh" `isSuffixOf`) <$> map (drop (length ("tests/network/"::String)) . toString) <$> ls "tests/network"-     annotatedFiles <- Control.Monad.Trans.liftIO $ mapM (parsePragmas "tests/network") files-     return [ shellTest dp fmt tdir (toString $ "network" </> file) da-            | (file, (diffAlgorithmsPragma, repoFormatsPragma)) <- annotatedFiles-            , fmt <- fromMaybe repoFormatsDefault repoFormatsPragma-            , da <- fromMaybe diffAlgorithmsDefault diffAlgorithmsPragma ]+            | file <- map toString test_files+            , fmt <- repoFormats+            , da <- diffAlgorithms ]+  where relevant = (if isFailing then id else not) . ("failing-" `isPrefixOf`) . takeBaseName . toString  -- ---------------------------------------------------------------------- -- harness@@ -223,6 +167,7 @@                      , patience :: Bool                      , darcs1 :: Bool                      , darcs2 :: Bool+                     , full :: Bool                      , darcs :: String                      , tests :: [String]                      , testDir :: Maybe FilePath@@ -240,12 +185,15 @@      [ hashed        := False    += help "Run hashed-storage tests [no]"      , failing       := False    += help "Run the failing (shell) tests [no]"      , shell         := True     += help "Run the passing, non-network shell tests [yes]"+-- RELEASE BRANCH ONLY: disable network tests (too fragile)+--     , network       := True     += help "Run the network shell tests [yes]"      , network       := False    += help "Run the network shell tests [no]"      , unit          := True     += help "Run the unit tests [yes]"      , myers         := False    += help "Use myers diff [no]"      , patience      := True     += help "Use patience diff [yes]" += name "p"      , darcs1        := False    += help "Use darcs-1 repo format [no]" += name "1"      , darcs2        := True     += help "Use darcs-2 repo format [yes]" += name "2"+     , full          := False    += help "Run all tests in all variants"      , darcs         := ""       += help "Darcs binary path" += typ "PATH"      , tests         := []       += help "Pattern to limit the tests to run" += typ "PATTERN" += name "t"      , testDir       := Nothing  += help "Directory to run tests in" += typ "PATH" += name "d"@@ -306,12 +254,14 @@                       . (if patience conf then (PatienceDiff:) else id)                       $ [] -    ftests <- shelly $ if failing conf then findShell darcsBin (testDir conf) True diffAlgorithm repoFormat else return []-    stests <- shelly $ if shell conf then findShell darcsBin (testDir conf) False diffAlgorithm repoFormat else return []+    stests <- shelly $+      if shell conf+        then findShell darcsBin "tests" (testDir conf) (failing conf) diffAlgorithm repoFormat+        else return []     utests <- if unit conf then doUnit else return []-    ntests <- shelly $ if network conf then findNetwork darcsBin (testDir conf) diffAlgorithm repoFormat else return []+    ntests <- shelly $ if network conf then findShell darcsBin "tests/network" (testDir conf) (failing conf) diffAlgorithm repoFormat else return []     hstests <- if hashed conf then doHashed else return []-    defaultMainWithArgs (ftests ++ stests ++ utests ++ ntests ++ hstests) args+    defaultMainWithArgs (stests ++ utests ++ ntests ++ hstests) args        where           exeSuffix :: String #ifdef WIN32@@ -326,6 +276,15 @@           hSetBinaryMode stderr True           hSetBinaryMode stdin True           clp  <- cmdArgs_ defaultConfig-          run clp--#endif+          run $+            if full clp then clp+              { hashed   = True+              , shell    = True+              , network  = True+              , unit     = True+              , myers    = True+              , patience = True+              , darcs1   = True+              , darcs2   = True+              }+            else clp
release/distributed-context view
@@ -1,1 +1,1 @@-Just "\nContext:\n\n[TAG 2.12.5\nGanesh Sittampalam <ganesh@earth.li>**20170111174540\n Ignore-this: 5e9ed0bfd6de3ef43d6933f2bda92147\n] \n"+Just "\nContext:\n\n[branch-2.14: disable network tests\nGuillaume Hoffmann <guillaumh@gmail.com>**20180404141317\n Ignore-this: 8d6e4b0590002fbe7b0a1d1299d4b\n] \n\n[branch-2.14: fix cabal sdist on newer Cabals\nGuillaume Hoffmann <guillaumh@gmail.com>**20180404141206\n Ignore-this: 69de5e3a3c40f4fc94536db0e7f276a9\n The trick we found is to remove other-modules: Version from\n the darcs executable.\n] \n\n[TAG 2.14.0\nGuillaume Hoffmann <guillaumh@gmail.com>**20180404141149\n Ignore-this: 6181e294bb45bb98b7c9e481990534c0\n] \n"
release/distributed-version view
@@ -1,1 +1,1 @@-Just 0+Just 2
− src/Bundled/Posix.hsc
@@ -1,116 +0,0 @@-{-# LANGUAGE CPP, RankNTypes #-}--module Bundled.Posix( getFdStatus, getSymbolicLinkStatus, getFileStatus-                    , getFileStatusBS-                    , fileExists-                    , modificationTime, fileSize, FileStatus-                    , EpochTime, isDirectory, isRegularFile ) where--import qualified Data.ByteString.Char8 as BS-#if mingw32_HOST_OS-#else-import Data.ByteString.Unsafe( unsafeUseAsCString )-#endif-import Foreign.Marshal.Alloc ( allocaBytes )-import Foreign.C.Error ( throwErrno, getErrno, eNOENT )-import Foreign.C.Types ( CTime, CInt )-import Foreign.Ptr ( Ptr )--import System.Posix.Internals-          ( CStat, c_fstat, sizeof_stat-          , st_mode, st_size, st_mtime, s_isdir, s_isreg )-#if mingw32_HOST_OS-import System.Posix.Internals ( c_stat, CFilePath )-#endif--import System.Posix.Types ( Fd(..), CMode, EpochTime )--#if mingw32_HOST_OS-import Foreign.C.String( withCWString, CWString )-#else-import Foreign.C.String ( withCString, CString )-#endif--#if mingw32_HOST_OS-import Data.Int ( Int64 )--type FileOffset = Int64-lstat :: CFilePath -> Ptr CStat -> IO CInt-lstat = c_stat-#else-import System.Posix.Types ( FileOffset )-import System.Posix.Internals( lstat )-#endif--#if mingw32_HOST_OS-bsToPath :: forall a. BS.ByteString -> (CWString -> IO a) -> IO a-bsToPath s f = withCWString (BS.unpack s) f-strToPath :: forall a. String -> (CWString -> IO a) -> IO a-strToPath = withCWString-#else-bsToPath :: forall a. BS.ByteString -> (CString -> IO a) -> IO a-bsToPath = unsafeUseAsCString-strToPath :: forall a. String -> (CString -> IO a) -> IO a-strToPath = withCString-#endif--data FileStatus = FileStatus {-    fst_exists :: !Bool,-    fst_mode :: !CMode,-    fst_mtime :: !CTime,-    fst_size :: !FileOffset- }--getFdStatus :: Fd -> IO FileStatus-getFdStatus (Fd fd) = do-  do_stat (c_fstat fd)--do_stat :: (Ptr CStat -> IO CInt) -> IO FileStatus-do_stat stat_func = do-  allocaBytes sizeof_stat $! \p -> do-     ret <- stat_func p-     if (ret == -1) then do err <- getErrno-                            if (err == eNOENT)-                               then return $! (FileStatus False 0 0 0)-                               else throwErrno "do_stat"-                    else do mode <- st_mode p-                            mtime <- st_mtime p-                            size <- st_size p-                            return $! FileStatus True mode mtime size-{-# INLINE  do_stat #-}--isDirectory :: FileStatus -> Bool-isDirectory = s_isdir . fst_mode--isRegularFile :: FileStatus -> Bool-isRegularFile = s_isreg . fst_mode--modificationTime :: FileStatus -> EpochTime-modificationTime = fst_mtime--fileSize :: FileStatus -> FileOffset-fileSize = fst_size--fileExists :: FileStatus -> Bool-fileExists = fst_exists--#include <sys/stat.h>---- lstat is broken on win32 with at least GHC 6.10.3-getSymbolicLinkStatus :: FilePath -> IO FileStatus-##if mingw32_HOST_OS-getSymbolicLinkStatus = getFileStatus-##else-getSymbolicLinkStatus fp =-  do_stat (\p -> (fp `strToPath` (`lstat` p)))-##endif--getFileStatus :: FilePath -> IO FileStatus-getFileStatus fp =-  do_stat (\p -> (fp `strToPath` (`lstat` p)))---- | Requires NULL-terminated bytestring -> unsafe! Use with care.-getFileStatusBS :: BS.ByteString -> IO FileStatus-getFileStatusBS fp =-  do_stat (\p -> (fp `bsToPath` (`lstat` p)))-{-# INLINE getFileStatusBS #-}
src/Darcs/Patch.hs view
@@ -18,13 +18,11 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}  module Darcs.Patch-    ( RepoPatch-    , RepoType+    ( RepoType     , IsRepoType     , PrimOf     , Named     , WrappedNamed-    , Patchy     , fromPrim     , fromPrims     , rmfile@@ -39,7 +37,9 @@     , binary     , description     , showContextPatch+    , ShowPatchFor(..)     , showPatch+    , displayPatch     , showNicely     , infopatch     , changepref@@ -88,15 +88,18 @@     , getdeps     , listConflictedFiles     , isInconsistent+    , module Darcs.Patch.RepoPatch     ) where  -import Darcs.Patch.Apply ( applyToFilePaths, effectOnFilePaths, applyToTree,-                           maybeApplyToTree, ApplyState )-import Darcs.Patch.Commute ( commuteFL, commuteFLorComplain, commuteRL )+import Darcs.Patch.Apply ( apply,applyToFilePaths, effectOnFilePaths, applyToTree,+                           maybeApplyToTree )+import Darcs.Patch.Commute ( commute, commuteFL, commuteFLorComplain, commuteRL ) import Darcs.Patch.Conflict ( listConflictedFiles, resolveConflicts ) import Darcs.Patch.Effect ( Effect(effect) )-import Darcs.Patch.Invert ( invertRL, invertFL )+import Darcs.Patch.Invert ( invert, invertRL, invertFL )+import Darcs.Patch.Inspect ( listTouchedFiles, hunkMatches )+import Darcs.Patch.Merge ( merge ) import Darcs.Patch.Named ( Named,                            adddeps, namepatch,                            anonymous,@@ -104,14 +107,6 @@                            infopatch,                            patch2patchinfo, patchname, patchcontents ) import Darcs.Patch.Named.Wrapped ( WrappedNamed )-import Darcs.Patch.Patchy ( Patchy,-                            showPatch, showNicely, showContextPatch,-                            invert,-                            thing, things,-                            apply,-                            description, summary, summaryFL,-                            commute, listTouchedFiles, hunkMatches-                          ) import Darcs.Patch.Prim ( fromPrims, fromPrim,                           canonize,                           sortCoalesceFL,@@ -125,12 +120,7 @@ import Darcs.Patch.Repair ( isInconsistent ) import Darcs.Patch.RepoPatch ( RepoPatch ) import Darcs.Patch.RepoType ( RepoType, IsRepoType )+import Darcs.Patch.Show ( description, showPatch, showNicely, displayPatch+                        , summary, summaryFL, thing, things, ShowPatchFor(..), ShowContextPatch(..) ) import Darcs.Patch.Summary ( xmlSummary, plainSummary, plainSummaryPrims ) import Darcs.Patch.TokenReplace ( forceTokReplace )-import Darcs.Patch.V1.Commute ( merge )--import Darcs.Util.Tree( Tree )---instance (Patchy p, ApplyState p ~ Tree) => Patchy (Named p)-instance (Patchy p, ApplyState p ~ Tree) => Patchy (WrappedNamed rt p)
src/Darcs/Patch/Annotate.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, OverloadedStrings, TypeSynonymInstances, MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings, TypeSynonymInstances, MultiParamTypeClasses #-}  -- Copyright (C) 2010 Petr Rockai --@@ -32,16 +32,19 @@  module Darcs.Patch.Annotate     (-      annotate+      annotateFile     , annotateDirectory     , format     , machineFormat     , AnnotateResult+    , Annotate(..)     ) where  import Prelude () import Darcs.Prelude +import Control.Monad.State ( modify, modify', when, gets, State, execState )+ import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC import qualified Data.Map as M@@ -51,175 +54,171 @@ import Data.List( nub, groupBy ) import Data.Maybe( isJust, mapMaybe ) -import Control.Monad.State ( modify, when, gets, State, execState )+import qualified Darcs.Patch.Prim.FileUUID as FileUUID -import Darcs.Patch.ApplyMonad( ApplyMonad(..), ApplyMonadTree(..) )-import Darcs.Patch.Apply ( Apply, apply, ApplyState )-import Darcs.Patch.Info ( PatchInfo(..), showPatchInfoUI, piAuthor, makePatchname )-import Darcs.Patch.PatchInfoAnd( info, PatchInfoAnd )+import Darcs.Patch.Info ( PatchInfo(..), displayPatchInfo, piAuthor, makePatchname )+import Darcs.Patch.Named ( Named(..) )+import Darcs.Patch.Named.Wrapped ( WrappedNamed(..) )+import Darcs.Patch.PatchInfoAnd( info, PatchInfoAnd, hopefully )+import Darcs.Patch.Prim.V1.Core ( Prim(..), DirPatchType(..), FilePatchType(..) )+import Darcs.Patch.TokenReplace ( annotateReplace ) import Darcs.Patch.Witnesses.Ordered -import Darcs.Util.Tree( Tree ) import Darcs.Util.Path ( FileName, movedirfilename, fn2ps, ps2fn )-import Darcs.Util.Printer( renderString, RenderMode(..) )-import Darcs.Util.ByteString ( linesPS, unlinesPS )-import Darcs.Util.Diff ( getChanges )-import qualified Darcs.Util.Diff as D ( DiffAlgorithm )--#include "impossible.h"-+import Darcs.Util.Printer( renderString )+import Darcs.Util.ByteString ( linesPS, decodeLocale )  data FileOrDirectory = File                      | Directory                        deriving (Show, Eq) +type AnnotateResult = V.Vector (Maybe PatchInfo, B.ByteString)+ data Annotated = Annotated-    { annotated     :: V.Vector (Maybe PatchInfo, B.ByteString)-    , current       :: [(Int, B.ByteString)]-    , path          :: Maybe FileName+    { annotated     :: !AnnotateResult+    , current       :: ![(Int, B.ByteString)]+    , path          :: (Maybe FileName)     , what          :: FileOrDirectory     , currentInfo   :: PatchInfo-    , diffAlgorithm :: D.DiffAlgorithm     } deriving Show -type AnnotateResult = V.Vector (Maybe PatchInfo, B.ByteString)- type AnnotatedM = State Annotated -instance ApplyMonad Tree AnnotatedM where-  type ApplyMonadBase AnnotatedM = AnnotatedM--  nestedApply _ _ = undefinedFun "nestedApply"-  liftApply _ _   = undefinedFun "liftApply"-  getApplyState   = undefinedFun "getApplyState"--instance ApplyMonadTree AnnotatedM where-  mReadFilePS     = undefinedFun "mReadFilePS"--  mDoesFileExist _      = return True-  mDoesDirectoryExist _ = return True-  mCreateDirectory _    = return ()-  mCreateFile _         = return ()--  mRemoveFile f = do-      p <- gets path-      when (p == Just f) $ modify (\x -> x { path = Nothing })-      updateDirectory f+class Annotate p where+  annotate :: p wX wY -> AnnotatedM () -  mRemoveDirectory = mRemoveFile+instance Annotate Prim where+  annotate (FP fn fp) = case fp of+    RmFile -> do+      whenPathIs fn $ modify' (\s -> s { path = Nothing })+      whenWhatIs Directory $ updateDirectory fn+    AddFile -> return ()+    Hunk off o n -> whenPathIs fn $ whenWhatIs File $ do+      let remove = length o+      let add = length n+      i <- gets currentInfo+      c <- gets current+      a <- gets annotated+      -- NOTE patches are inverted and in inverse order+      modify' $ \s ->+        -- NOTE subtract one from offset because darcs counts from one,+        -- whereas vectors and lists count from zero.+        let (to,from) = splitAt (off-1) c+        in  s { current = map eval $ to ++ replicate add (-1, B.empty) ++ drop remove from+              , annotated = merge i a $ map eval $ take remove $ from+              }+    TokReplace t o n -> whenPathIs fn $ whenWhatIs File $ do+      let test = annotateReplace t (BC.pack o) (BC.pack n)+      i <- gets currentInfo+      c <- gets current+      a <- gets annotated+      modify' $ \s -> s+        { current = map (\(ix,b)->if test b then (-1,B.empty) else (ix,b)) c+        , annotated = merge i a $ map eval $ filter (test . snd) $ c+        }+    -- TODO what if the status of a file changed from text to binary?+    Binary _ _ -> whenPathIs fn $ bug "annotate: can't handle binary changes"+  annotate (DP _ AddDir) = return ()+  annotate (DP fn RmDir) = whenWhatIs Directory $ do+    whenPathIs fn $ modify' (\s -> s { path = Nothing })+    updateDirectory fn+  annotate (Move fn fn') = do+    modify' (\s -> s { path = fmap (movedirfilename fn fn') (path s) })+    whenWhatIs Directory $ do+      let fix (i, x) = (i, fn2ps $ movedirfilename fn fn' (ps2fn x))+      modify $ \s -> s { current = map fix $ current s }+  annotate (ChangePref _ _ _) = return () -  mRename a b = do-      p <- gets path-      w <- gets what-      when (isJust p) $-          modify $ \st -> st { path = Just $ movedirfilename a b (fromJust p) }-      when (w == Directory) $ do-          let fix (i, x) = (i, fn2ps $ movedirfilename a b (ps2fn x))-          modify $ \st -> st { current = map fix $ current st }+instance Annotate FileUUID.Prim where+  annotate _ = bug "annotate not implemented for FileUUID patches" -  mModifyFilePS f job = do-      p <- gets path-      when (p == Just f) $ updateFile (fmap linesPS . job . unlinesPS)+instance Annotate p => Annotate (FL p) where+  annotate = sequence_ . mapFL annotate -  mModifyFilePSs f job = do-      p <- gets path-      when (p == Just f) $ updateFile job+instance Annotate p => Annotate (Named p) where+  annotate (NamedP _ _ p) = annotate p -undefinedFun :: Monad m-             => String-             -> m a-undefinedFun name = fail $ name ++ " undefined for Annotated"+instance Annotate p => Annotate (WrappedNamed rt p) where+  annotate (NormalP n) = annotate n+  annotate (RebaseP _ _) = bug "annotate not implemented for Rebase patches" +instance Annotate p => Annotate (PatchInfoAnd rt p) where+  annotate = annotate . hopefully -updateFile :: ([B.ByteString]-           -> AnnotatedM [B.ByteString])-           -> AnnotatedM ()-updateFile job = (==File) <$> gets what >>= flip when go-  where-    go = do-        before <- map snd `fmap` gets current-        after <- job before-        da <- gets diffAlgorithm-        reannotate $ getChanges da before after+whenWhatIs :: FileOrDirectory -> AnnotatedM () -> AnnotatedM ()+whenWhatIs w actions = do+  w' <- gets what+  when (w == w') actions -    reannotate [] = return ()-    reannotate ((off, remove, add):rest) = do-        i <- gets currentInfo-        c <- gets current-        a <- gets annotated-        modify $ \s -> s { current = take off c ++ [ (-1, x) | x <- add ] ++-                                     drop (off + length remove) c-                         , annotated = merge i a $ take (length remove) $ drop off c-                         }-        reannotate rest+whenPathIs :: FileName -> AnnotatedM () -> AnnotatedM ()+whenPathIs fn actions = do+  p <- gets path+  when (p == Just fn) actions -    merge i a l = a V.// [ (line, (Just i, B.empty))-                         | (line, _) <- l, line >= 0 && line < V.length a]+eval :: (Int, B.ByteString) -> (Int, B.ByteString)+eval (i,b) = seq i $ seq b $ (i,b) +merge :: a+      -> V.Vector (Maybe a, BC.ByteString)+      -> [(Int, t)]+      -> V.Vector (Maybe a, BC.ByteString)+merge i a l = a V.// [ (line, (Just i, B.empty))+                     | (line, _) <- l, line >= 0 && line < V.length a]  updateDirectory :: FileName -> AnnotatedM ()-updateDirectory p = (==Directory) <$> gets what >>= flip when go+updateDirectory p = whenWhatIs Directory $ do+    let line = fn2ps p+    files <- gets current+    case filter ((==line) . snd) files of+      [match@(ident, _)] -> reannotate ident match line+      _ -> return ()   where-    go = do let line = fn2ps p-            files <- gets current-            case filter ((==line) . snd) files of-              [match@(ident, _)] -> reannotate ident match line-              _ -> return ()     reannotate ident match line =       modify $ \x -> x { annotated = annotated x V.// [ (ident, update line $ currentInfo x) ]                        , current = filter (/= match) $ current x }     update line inf = (Just inf, BC.concat [ " -- created as: ", line ]) - complete :: Annotated -> Bool complete x = V.all (isJust . fst) $ annotated x --annotate' :: (Apply p, ApplyState p ~ Tree)+annotate' :: Annotate p           => FL (PatchInfoAnd rt p) wX wY           -> Annotated           -> Annotated annotate' NilFL ann = ann annotate' (p :>: ps) ann     | complete ann = ann-    | otherwise = annotate' ps $ execState (apply p) (ann { currentInfo = info p })-+    | otherwise = annotate' ps $ execState (annotate p) (ann { currentInfo = info p }) -annotate :: (Apply p, ApplyState p ~ Tree)-         => D.DiffAlgorithm-         -> FL (PatchInfoAnd rt p) wX wY-         -> FileName-         -> B.ByteString-         -> AnnotateResult-annotate da patches inipath inicontent = annotated $ annotate' patches initial+annotateFile :: Annotate p+             => FL (PatchInfoAnd rt p) wX wY+             -> FileName+             -> B.ByteString+             -> AnnotateResult+annotateFile patches inipath inicontent = annotated $ annotate' patches initial   where     initial = Annotated { path = Just inipath-                        , currentInfo = error "There is no currentInfo."+                        , currentInfo = bug "There is no currentInfo."                         , current = zip [0..] (linesPS inicontent)                         , what = File                         , annotated = V.replicate (length $ breakLines inicontent)                                                       (Nothing, B.empty)-                        , diffAlgorithm = da                         } --annotateDirectory :: (Apply p, ApplyState p ~ Tree)-                  => D.DiffAlgorithm-                  -> FL (PatchInfoAnd rt p) wX wY+annotateDirectory :: Annotate p+                  => FL (PatchInfoAnd rt p) wX wY                   -> FileName                   -> [FileName]                   -> AnnotateResult-annotateDirectory da patches inipath inicontent = annotated $ annotate' patches initial+annotateDirectory patches inipath inicontent = annotated $ annotate' patches initial   where     initial = Annotated { path = Just inipath-                        , currentInfo = error "There is no currentInfo."+                        , currentInfo = bug "There is no currentInfo."                         , current = zip [0..] (map fn2ps inicontent)                         , what = Directory                         , annotated = V.replicate (length inicontent) (Nothing, B.empty)-                        , diffAlgorithm = da                         } - machineFormat :: B.ByteString -> AnnotateResult -> String machineFormat d a = unlines [ case i of                                  Just inf -> show $ makePatchname inf@@ -228,10 +227,7 @@                               ++ " | " ++ BC.unpack line ++ " " ++ BC.unpack add                             | ((i, add), line) <- zip (V.toList a) (breakLines d) ] --format :: B.ByteString-       -> AnnotateResult-       -> String+format :: B.ByteString -> AnnotateResult -> String format d a = pi_list ++ "\n" ++ numbered   where     numberedLines = zip [(1 :: Int)..] . lines $ file@@ -244,7 +240,7 @@      numbered = unlines . map prependNum $ numberedLines -    pi_list = unlines [ show n ++ ": " ++ renderString Encode (showPatchInfoUI i)+    pi_list = unlines [ show n ++ ": " ++ renderString (displayPatchInfo i)                       | (n :: Int, i) <- zip [1..] pis ]      file = concat [ annotation (fst $ head chunk) ++ " | " ++ line (head chunk) ++@@ -257,7 +253,7 @@      file_ann = groupBy ((==) `on` fst) $ zip (V.toList a) (breakLines d) -    line ((_, add), l) = BC.unpack $ BC.concat [l, " ", add]+    line ((_, add), l) = decodeLocale $ BC.concat [l, " ", add]      annotation (Just i, _) | Just n <- M.lookup i pi_map =         pad 20 (piMail i) ++ " " ++ pad 4 ('#' : show n)@@ -271,11 +267,8 @@         | '<' `elem` piAuthor pi = takeWhile (/= '>') . drop 1 . dropWhile (/= '<') $ piAuthor pi         | otherwise = piAuthor pi --breakLines :: BC.ByteString-           -> [BC.ByteString]+breakLines :: BC.ByteString -> [BC.ByteString] breakLines s = case BC.split '\n' s of     [] -> []     split | BC.null (last split) -> init split           | otherwise -> split-
src/Darcs/Patch/Apply.hs view
@@ -16,7 +16,7 @@ --  Boston, MA 02110-1301, USA.  -{-# LANGUAGE CPP, MultiParamTypeClasses #-}+{-# LANGUAGE MultiParamTypeClasses #-}   -- |@@ -34,25 +34,20 @@     , applyToTree     , applyToState     , maybeApplyToTree-    , applyToFileMods     , effectOnFilePaths     ) where  import Prelude () import Darcs.Prelude -import Data.Set ( Set )- import Control.Exception ( catch, IOException ) import Control.Arrow ( (***) )  import Darcs.Util.Tree( Tree )  import Darcs.Patch.ApplyMonad ( ApplyMonad(..), withFileNames, ApplyMonadTrans(..) )-import Darcs.Util.Path( FileName, fn2fp, fp2fn )+import Darcs.Util.Path( fn2fp, fp2fn ) import Darcs.Patch.Witnesses.Ordered ( FL(..), RL(..) )-import Darcs.Patch.Index.Monad ( withPatchMods )-import Darcs.Patch.Index.Types ( PatchMod )  class Apply p where     type ApplyState p :: (* -> *) -> *@@ -90,7 +85,7 @@   -- | Apply a patch to a 'Tree', yielding a new 'Tree'.-applyToTree :: (Apply p, Functor m, Monad m, ApplyState p ~ Tree)+applyToTree :: (Apply p, Monad m, ApplyState p ~ Tree)             => p wX wY             -> Tree m             -> m (Tree m)@@ -109,8 +104,3 @@                  -> IO (Maybe (Tree IO)) maybeApplyToTree patch tree =     (Just `fmap` applyToTree patch tree) `catch` (\(_ :: IOException) -> return Nothing)------------------------------------------------------------------------------------- | Apply a patch to set of 'FileName's, yielding the new set of 'FileName's and 'PatchMod's-applyToFileMods :: (Apply p, ApplyState p ~ Tree) => p wX wY -> Set FileName -> (Set FileName, [PatchMod FileName])-applyToFileMods patch = withPatchMods (apply patch)
src/Darcs/Patch/ApplyMonad.hs view
@@ -1,9 +1,7 @@ {-# OPTIONS_GHC -fno-warn-missing-methods -fno-warn-orphans #-} {-# LANGUAGE TypeSynonymInstances, MultiParamTypeClasses-           , ConstraintKinds, UndecidableInstances, CPP #-}-#if __GLASGOW_HASKELL__ >= 800-{-# LANGUAGE UndecidableSuperClasses #-}-#endif+           , ConstraintKinds, UndecidableInstances+           , UndecidableSuperClasses #-} -- Copyright (C) 2010, 2011 Petr Rockai -- -- Permission is hereby granted, free of charge, to any person@@ -40,9 +38,8 @@ import qualified Darcs.Util.Tree.Monad as TM import Darcs.Util.Tree ( Tree ) import Data.Maybe ( fromMaybe )-import Darcs.Util.ByteString( linesPS, unlinesPS )-import Darcs.Util.Path ( FileName, movedirfilename, fn2fp, isParentOrEqOf,-                    floatPath, AnchoredPath )+import Darcs.Util.Path+    ( FileName, movedirfilename, fn2fp, isParentOrEqOf, floatPath, AnchoredPath ) import Control.Monad.State.Strict import Control.Monad.Identity( Identity ) import Darcs.Patch.MonadProgress@@ -75,8 +72,6 @@     mDoesDirectoryExist ::  FileName -> m Bool     mDoesFileExist ::  FileName -> m Bool     mReadFilePS ::  FileName -> m B.ByteString-    mReadFilePSs ::  FileName -> m [B.ByteString]-    mReadFilePSs f = linesPS `fmap` mReadFilePS f     mCreateDirectory ::  FileName -> m ()     mRemoveDirectory ::  FileName -> m ()     mCreateFile ::  FileName -> m ()@@ -84,8 +79,6 @@     mRemoveFile ::  FileName -> m ()     mRename ::  FileName -> FileName -> m ()     mModifyFilePS ::  FileName -> (B.ByteString -> m B.ByteString) -> m ()-    mModifyFilePSs ::  FileName -> ([B.ByteString] -> m [B.ByteString]) -> m ()-    mModifyFilePSs f j = mModifyFilePS f (fmap unlinesPS . j . linesPS)     mChangePref ::  String -> String -> String -> m ()     mChangePref _ _ _ = return () 
src/Darcs/Patch/ApplyPatches.hs view
@@ -2,22 +2,21 @@     ( applyPatches     ) where -import Darcs.Patch.Info ( showPatchInfoUI )+import Darcs.Patch.Info ( displayPatchInfo ) import Darcs.Patch.ApplyMonad ( ApplyMonad(..) ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, hopefully, info ) import Darcs.Patch.Apply ( Apply(..) )-import Darcs.Patch.Patchy ( Patchy ) import Darcs.Patch.MonadProgress ( MonadProgress, ProgressAction(..), runProgressActions)  import Darcs.Patch.Witnesses.Ordered ( FL(..), mapFL ) import Darcs.Util.Printer ( text, ($$) ) -applyPatches :: (MonadProgress m, ApplyMonad (ApplyState p) m, Patchy p)+applyPatches :: (MonadProgress m, ApplyMonad (ApplyState p) m, Apply p)              => FL (PatchInfoAnd rt p) wX wY -> m () applyPatches ps = runProgressActions "Applying patch" (mapFL doApply ps)   where     doApply hp = ProgressAction { paAction = apply (hopefully hp)-                                , paMessage = showPatchInfoUI (info hp)+                                , paMessage = displayPatchInfo (info hp)                                 , paOnError = text "Unapplicable patch:" $$-                                              showPatchInfoUI (info hp)+                                              displayPatchInfo (info hp)                                 }
src/Darcs/Patch/Bracketed/Instances.hs view
@@ -32,10 +32,10 @@     fromPrim p = Singleton (fromPrim p)  instance ShowPatchBasic p => ShowPatchBasic (Bracketed p) where-    showPatch (Singleton p) = showPatch p-    showPatch (Braced NilFL) = blueText "{" $$ blueText "}"-    showPatch (Braced ps) = blueText "{" $$ vcat (mapFL showPatch ps) $$ blueText "}"-    showPatch (Parens ps) = blueText "(" $$ vcat (mapFL showPatch ps) $$ blueText ")"+    showPatch f (Singleton p) = showPatch f p+    showPatch _ (Braced NilFL) = blueText "{" $$ blueText "}"+    showPatch f (Braced ps) = blueText "{" $$ vcat (mapFL (showPatch f) ps) $$ blueText "}"+    showPatch f (Parens ps) = blueText "(" $$ vcat (mapFL (showPatch f) ps) $$ blueText ")"  -- the ReadPatch instance is defined in Darcs.Patch.Read as it is -- used as an intermediate form during reading of lists of patches
src/Darcs/Patch/Bundle.hs view
@@ -15,19 +15,13 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.Patch.Bundle-    ( hashBundle-    , makeBundle2-    , makeBundleN+    ( makeBundleN     , scanBundle     , contextPatches     , scanContextFile     , patchFilename-    , getContext     , minContext-    , parseBundle     ) where  import Prelude ()@@ -50,7 +44,7 @@ import Darcs.Patch.Depends ( slightlyOptimizePatchset ) import Darcs.Patch.Format ( PatchListFormat ) import Darcs.Patch.Info ( PatchInfo, readPatchInfo, showPatchInfo,-                          showPatchInfoUI, isTag )+                          displayPatchInfo, isTag ) import Darcs.Patch.Named.Wrapped ( WrappedNamed ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, piap, fmapFLPIAP, info,                                   patchInfoAndPatch, unavailable, hopefully,@@ -59,17 +53,18 @@ import Darcs.Patch.ReadMonads ( parseStrictly ) import Darcs.Patch.RepoType ( RepoType(..), RebaseType(..) ) import Darcs.Patch.Set ( PatchSet(..), Tagged(..), SealedPatchSet, Origin )-import Darcs.Patch.Show ( ShowPatchBasic )+import Darcs.Patch.Show ( ShowPatchBasic, ShowPatchFor(ForStorage) ) import Darcs.Patch.Witnesses.Ordered     ( RL(..), FL(..), (:>)(..), reverseFL, (+<+),     mapFL, mapFL_FL, mapRL ) import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed), seal ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP ) -import Darcs.Util.ByteString ( mmapFilePS, linesPS, unlinesPS, dropSpace, substrPS)-import Darcs.Util.Crypt.SHA1 ( sha1PS )+import Darcs.Util.ByteString+    ( mmapFilePS, linesPS, unlinesPS, dropSpace, substrPS, decodeLocale )+import Darcs.Util.Hash ( sha1PS ) import Darcs.Util.Printer ( Doc, renderPS, newline, text, ($$),-                 (<>), vcat, vsep, renderString, RenderMode(..) )+                 (<>), vcat, vsep, renderString )  -- |hashBundle creates a SHA1 string of a given a FL of named patches. This -- allows us to ensure that the patches in a received patchBundle have not been@@ -77,7 +72,7 @@ hashBundle :: (PatchListFormat p, ShowPatchBasic p) => FL (WrappedNamed rt p) wX wY            -> String hashBundle to_be_sent =-    show $ sha1PS $ renderPS Standard $ vcat (mapFL showPatch to_be_sent) <> newline+    show $ sha1PS $ renderPS $ vcat (mapFL (showPatch ForStorage) to_be_sent) <> newline  makeBundleN :: (ApplyState p ~ Tree, RepoPatch p) => Maybe (Tree IO)             -> PatchSet rt p wStart wX -> FL (WrappedNamed rt p) wX wY -> IO Doc@@ -96,8 +91,8 @@             -> FL (WrappedNamed rt p) wX wY -> IO Doc makeBundle2 the_s common' to_be_sent to_be_sent2 = do     patches <- case the_s of-                   Just tree -> fst `fmap` virtualTreeIO (showContextPatch to_be_sent) tree-                   Nothing -> return (vsep $ mapFL showPatch to_be_sent)+                   Just tree -> fst `fmap` virtualTreeIO (showContextPatch ForStorage to_be_sent) tree+                   Nothing -> return (vsep $ mapFL (showPatch ForStorage) to_be_sent)     return $ format patches   where     format the_new = text ""@@ -107,7 +102,7 @@                      $$ text ""                      $$ text "Context:"                      $$ text ""-                     $$ vcat (map showPatchInfo common)+                     $$ vcat (map (showPatchInfo ForStorage) common)                      $$ text "Patch bundle hash:"                      $$ text (hashBundle to_be_sent2)                      $$ text ""@@ -153,7 +148,7 @@      sealCtxAndPs ctx ps = Right $ sealContextWithPatches ctx ps -    sealContextWithPatches :: RepoPatch p => [PatchInfo]+    sealContextWithPatches :: [PatchInfo]                            -> FL (PatchInfoAnd ('RepoType 'NoRebase) (Bracketed p)) wX wY                            -> Sealed                                   ((PatchSet rt p :> FL (PatchInfoAnd rt p)) Origin)@@ -201,14 +196,14 @@  -- |unavailablePatches converts a list of PatchInfos into a RL of PatchInfoAnd -- Unavailable patches. This is used to represent the Context of a patchBundle.-unavailablePatches :: RepoPatch p => [PatchInfo] -> RL (PatchInfoAnd rt p) wX wY+unavailablePatches :: [PatchInfo] -> RL (PatchInfoAnd rt p) wX wY unavailablePatches = foldr (flip (:<:) . piUnavailable) (unsafeCoerceP NilRL)  -- |piUnavailable returns an Unavailable within a PatchInfoAnd given a -- PatchInfo.-piUnavailable :: RepoPatch p => PatchInfo -> PatchInfoAnd rt p wX wY+piUnavailable :: PatchInfo -> PatchInfoAnd rt p wX wY piUnavailable i = patchInfoAndPatch i . unavailable $-    "Patch not stored in patch bundle:\n" ++ renderString Encode (showPatchInfoUI i)+    "Patch not stored in patch bundle:\n" ++ renderString (displayPatchInfo i)  -- |getContext parses a context list, returning a tuple containing the list, -- and remaining ByteString input.@@ -238,11 +233,11 @@ -- removed any leading spaces. The before-newline part is unpacked to a String, -- and tupled up with the remaining ByteString. sillyLex :: B.ByteString -> (String, B.ByteString)-sillyLex ps = (BC.unpack a, b)+sillyLex ps = (decodeLocale a, b)   where     (a, b) = BC.break (== '\n') (dropSpace ps) -contextPatches :: RepoPatch p => PatchSet rt p Origin wX+contextPatches :: PatchSet rt p Origin wX                -> (PatchSet rt p :> RL (PatchInfoAnd rt p)) Origin wX contextPatches set = case slightlyOptimizePatchset set of     PatchSet (ts :<: Tagged t _ ps') ps ->@@ -250,11 +245,11 @@     PatchSet NilRL ps -> PatchSet NilRL NilRL :> ps  -- |'scanContextFile' scans the context in the file of the given name.-scanContextFile :: RepoPatch p => FilePath -> IO (PatchSet rt p Origin wX)+scanContextFile :: FilePath -> IO (PatchSet rt p Origin wX) scanContextFile filename = scanContext `fmap` mmapFilePS filename   where     -- are the type witnesses sensible?-    scanContext :: RepoPatch p => B.ByteString -> PatchSet rt p Origin wX+    scanContext :: B.ByteString -> PatchSet rt p Origin wX     scanContext input         | B.null input = error "Bad context!"         | otherwise = case sillyLex input of
src/Darcs/Patch/Choices.hs view
@@ -15,116 +15,134 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}----- | PatchChoices divides a sequence of patches into three sets: "first",--- "middle" and "last", such that all patches can be applied, if you first--- apply the first ones then the middle ones and then the last ones.--- Obviously if there are dependencies between the patches that will put a--- constraint on how you can choose to divide them up.  The PatchChoices data--- type and associated functions are here to deal with many of the common+-- | The purpose of this module is to deal with many of the common -- cases that come up when choosing a subset of a group of patches. ----- 'forceLast' tells PatchChoices that a particular patch is required to be in--- the "last" group, which also means that any patches that depend on it--- must be in the "last" group.+-- The idea is to divide a sequence of candidate patches into an initial+-- section named 'InFirst', a final section named 'InLast', and between them a+-- third section of not yet decided patches named 'InMiddle'. The reason for the+-- neutral terminology 'InFirst', 'InMiddle', and 'InLast', is that which of 'InFirst'+-- and 'InLast' counts as @selected@ or @deselected@ depends on+-- what we want to achive, that is, on the command and its options.+-- See "Darcs.UI.SelectChanges" for examples of how to use the functions from+-- this module. ----- Internally, a PatchChoices doesn't always reorder the patches until--- it is asked for the final output (e.g. by 'get_first_choice').--- Instead, each patch is placed in a state of definitely first,--- definitely last and undecided; undecided leans towards--- "middle". The patches that are first are commuted to the head--- immediately, but patches that are middle and last are mixed--- together. In case you're wondering about the first-middle-last--- language, it's because in some cases the "yes" answers will be last--- (as is the case for the revert command), and in others first (as in--- record, pull and push).+-- Obviously if there are dependencies between the patches that will put a+-- constraint on how you can choose to divide them up. Unless stated otherwise,+-- functions that move patches from one section to another pull all dependent+-- patches with them. ----- Some patch marked "middle" may in fact be unselectable because of--- dependencies: when a patch is marked "last", its dependencies are--- not updated until patchSlot is called on them.-module Darcs.Patch.Choices ( PatchChoices, patchChoices, patchChoicesLps,-                             patchChoicesLpsSub,-                      patchSlot, patchSlot',-                      getChoices, refineChoices,-                      separateFirstMiddleFromLast,-                      separateFirstFromMiddleLast,-                      forceFirst, forceFirsts, forceLast, forceLasts,-                      forceMatchingFirst, forceMatchingLast,-                      selectAllMiddles,-                      makeUncertain, makeEverythingLater, makeEverythingSooner,-                      LabelledPatch, Label, label, lpPatch, getLabelInt,-                             Slot(..),-                      substitute-                    ) where+-- Internally, we don't necessarily reorder patches immediately, but merely+-- tag them with the desired status, and thus postpone the actual commutation.+-- This saves a lot of unnecessary work, especially when choices are made+-- interactively, where the user can revise earlier decisions.+module Darcs.Patch.Choices+    ( -- * Choosing patches+      PatchChoices+    , Slot(..)+      -- ** Constructing+    , patchChoices+    , mkPatchChoices+      -- ** Querying+    , patchSlot+    , getChoices+    , separateFirstMiddleFromLast+    , separateFirstFromMiddleLast+      -- ** Forcing patches into a given 'Slot'+    , forceMatchingFirst+    , forceFirsts+    , forceFirst+    , forceMatchingLast+    , forceLasts+    , forceLast+    , forceMiddle+    , makeEverythingSooner+    , makeEverythingLater+      -- ** Operations on 'InMiddle' patches+    , selectAllMiddles+    , refineChoices+      -- ** Substitution+    , substitute+      -- * Labelling patches+    , LabelledPatch+    , Label+    , label+    , unLabel+    , labelPatches+    , getLabelInt+    ) where  import Prelude () import Darcs.Prelude -import Control.Monad.Identity ( Identity )-import Control.Monad.State ( StateT(..) )--import Prelude hiding ( pred )--import Darcs.Patch-     ( Patchy, commuteRL, commute, merge, listTouchedFiles, hunkMatches-     , invert )-import Darcs.Patch.Merge ( Merge )+import Darcs.Patch.Merge ( Merge, merge )+import Darcs.Patch.Invert ( Invert, invert )+import Darcs.Patch.Commute ( Commute, commute, commuteRL )+import Darcs.Patch.Inspect ( PatchInspect, listTouchedFiles, hunkMatches ) import Darcs.Patch.Permutations ( commuteWhatWeCanRL, commuteWhatWeCanFL )-import Darcs.Patch.Patchy ( Invert, Commute, PatchInspect )-import Darcs.Patch.Witnesses.Eq ( MyEq(..), EqCheck(..) )-import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )+import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) ) import Darcs.Patch.Witnesses.Ordered-    ( FL(..), RL(..),-    (:>)(..), (:\/:)(..), (:/\:)(..), (:||:)(..),-    zipWithFL, mapFL_FL, concatFL,-    (+>+), reverseRL, anyFL )+    ( FL(..), RL(..)+    , (:>)(..), (:\/:)(..), (:/\:)(..), (:||:)(..)+    , zipWithFL, mapFL_FL, concatFL+    , (+>+), reverseRL, anyFL ) import Darcs.Patch.Witnesses.Sealed ( Sealed2(..) )---#include "impossible.h"-+import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )  -- | 'Label' @mp i@ acts as a temporary identifier to help us keep track of patches --   during the selection process.  These are useful for finding patches that --   may have moved around during patch selection (being pushed forwards or --   backwards as dependencies arise). -----   The identifier is implemented as a tuple @Label mp i@. The @i@ is just some---   arbitrary label, expected to be unique within the patches being+--   The identifier is implemented as a tuple @Label mp i@. The @i@ is an+--   integer, expected to be unique within the patches being --   scrutinised.  The @mp@ is motivated by patch splitting; it --   provides a convenient way to generate a new identifier from the patch --   being split.  For example, if we split a patch identified as @Label Nothing---   5@, the resulting sub-patches could be identified as @Label (Label Nothing 5)---   1@, @Label (Label Nothing 5) 2@, etc.-data Label = Label (Maybe Label) Integer deriving ( Eq, Ord )+--   5@, the resulting sub-patches could be identified as+--   @Label (Just (Label Nothing 5))1@, @Label (Just (Label Nothing 5)) 2@, etc.+--+--   IOW, 'Label' is a non-empty, reversed list of 'Int's.+data Label = Label (Maybe Label) Int deriving Eq++-- | A patch with a 'Label' attached to it. data LabelledPatch p wX wY = LP Label (p wX wY) --- | The @Bool@ parameter indicates whether the patch has been explicitely--- selected (or rejected) by the user.-data PatchChoice p wX wY = PC { pcPatch :: (LabelledPatch p wX wY)-                               , _pcChoice :: Bool}+-- | This internal type tags a 'LabelledPatch' with a 'Bool', to distinguish+-- 'InMiddle' from 'InLast' patches.+data PatchChoice p wX wY = PC+  { pcPatch :: (LabelledPatch p wX wY) -- ^ the 'LabelledPatch' in question+  , _pcIsLast :: Bool                  -- ^ 'False' = 'InMiddle', 'True' = 'InLast'+  } +-- | Internal function to tag a 'LabelledPatch' as 'InMiddle' or 'InLast'.+pcSetLast :: Bool -> LabelledPatch p wX wY -> PatchChoice p wX wY+pcSetLast = flip PC++-- TODO pcsFirsts should be an 'RL', not an 'FL'.+-- | A sequence of 'LabelledPatch'es where each patch is either+-- 'InFirst', 'InMiddle', or 'InLast'. The representation is+-- optimized for the case where we start chosing patches from the left+-- of the sequence: patches that are 'InFirst' are commuted to the head+-- immediately, but patches that are 'InMiddle' or 'InLast' are mixed+-- together; when a patch is marked 'InLast', its dependencies are+-- not updated until we retrieve the final result. data PatchChoices p wX wY where   PCs :: { pcsFirsts :: FL (LabelledPatch p) wX wM-         , pcsLasts :: FL (PatchChoice p) wM wY}+         , pcsMiddleLasts :: FL (PatchChoice p) wM wY}       -> PatchChoices p wX wY --- | See module documentation for 'Darcs.Patch.Choices'+-- | See module documentation for "Darcs.Patch.Choices". data Slot = InFirst | InMiddle | InLast  label :: LabelledPatch p wX wY -> Label label (LP tg _) = tg -getLabelInt :: Label -> Integer+getLabelInt :: Label -> Int getLabelInt (Label _ i) = i -lpPatch :: LabelledPatch p wX wY -> p wX wY-lpPatch (LP _ p) = p--liftLP :: (p wX wY -> p wA wB) -> (LabelledPatch p wX wY -> LabelledPatch p wA wB)-liftLP f (LP t p) = LP t (f p)+unLabel :: LabelledPatch p wX wY -> p wX wY+unLabel (LP _ p) = p  -- This is dangerous if two patches from different labelled series are compared -- ideally Label (and hence LabelledPatch/PatchChoices) would have a witness type@@ -132,75 +150,94 @@ compareLabels :: LabelledPatch p wA wB -> LabelledPatch p wC wD -> EqCheck (wA, wB) (wC, wD) compareLabels (LP l1 _) (LP l2 _) = if l1 == l2 then unsafeCoerceP IsEq else NotEq -instance MyEq p => MyEq (LabelledPatch p) where-    unsafeCompare (LP l1 p1) (LP l2 p2) = l1 == l2 && unsafeCompare p1 p2+instance Eq2 p => Eq2 (LabelledPatch p) where+  unsafeCompare (LP l1 p1) (LP l2 p2) = l1 == l2 && unsafeCompare p1 p2  instance Invert p => Invert (LabelledPatch p) where-    invert = liftLP invert+  invert (LP t p) = LP t (invert p)  instance Commute p => Commute (LabelledPatch p) where-    commute (LP l1 p1 :> LP l2 p2) = do p2' :> p1' <- commute (p1 :> p2)-                                        return (LP l2 p2' :> LP l1 p1')+  commute (LP l1 p1 :> LP l2 p2) = do+    p2' :> p1' <- commute (p1 :> p2)+    return (LP l2 p2' :> LP l1 p1')  instance PatchInspect p => PatchInspect (LabelledPatch p) where-    listTouchedFiles (LP _ p) = listTouchedFiles p-    hunkMatches f (LP _ p) = hunkMatches f p+  listTouchedFiles = listTouchedFiles . unLabel+  hunkMatches f = hunkMatches f . unLabel  instance Merge p => Merge (LabelledPatch p) where-    merge (LP l1 p1 :\/: LP l2 p2) = case merge (p1 :\/: p2) of-                                     p2' :/\: p1' -> LP l2 p2' :/\: LP l1 p1'+  merge (LP l1 p1 :\/: LP l2 p2) =+    case merge (p1 :\/: p2) of+      p2' :/\: p1' -> LP l2 p2' :/\: LP l1 p1'  instance Commute p => Commute (PatchChoice p) where-  commute (PC p1 c1 :> PC p2 c2) = do p2' :> p1' <- commute (p1 :> p2)-                                      return (PC p2' c2 :> PC p1' c1)+  commute (PC p1 c1 :> PC p2 c2) = do+    p2' :> p1' <- commute (p1 :> p2)+    return (PC p2' c2 :> PC p1' c1)  instance PatchInspect p => PatchInspect (PatchChoice p) where-  listTouchedFiles (PC p _) = listTouchedFiles p-  hunkMatches f (PC p _) = hunkMatches f p+  listTouchedFiles = listTouchedFiles . pcPatch+  hunkMatches f = hunkMatches f . pcPatch  instance Merge p => Merge (PatchChoice p) where   merge (PC lp1 c1 :\/: PC lp2 c2) = case merge (lp1 :\/: lp2) of     lp2' :/\: lp1' -> PC lp2' c2 :/\: PC lp1' c1 -patchChoices :: Patchy p => FL p wX wY -> PatchChoices p wX wY-patchChoices = fst . patchChoicesLps+-- | Create a 'PatchChoices' from a sequence of patches, so that+-- all patches are initially 'InMiddle'.+patchChoices :: FL p wX wY -> PatchChoices p wX wY+patchChoices = mkPatchChoices . labelPatches Nothing --- |Label a sequence of patches as subpatches of an existing label. This is intended for--- use when substituting a patch for an equivalent patch or patches.-patchChoicesLpsSub :: Patchy p-                      => Maybe Label -> FL p wX wY-                      -> (PatchChoices p wX wY, FL (LabelledPatch p) wX wY)-patchChoicesLpsSub tg ps = let lps = zipWithFL LP (map (Label tg) [1..]) ps-                           in (PCs NilFL (mapFL_FL (\lp -> PC lp False) lps), lps)+-- | Label a sequence of patches, maybe using the given parent label.+labelPatches :: Maybe Label -> FL p wX wY -> FL (LabelledPatch p) wX wY+labelPatches tg ps = zipWithFL LP (map (Label tg) [1..]) ps --- |Label a sequence of patches.-patchChoicesLps :: Patchy p => FL p wX wY -> (PatchChoices p wX wY, FL (LabelledPatch p) wX wY)-patchChoicesLps = patchChoicesLpsSub Nothing+-- | Create a 'PatchChoices' from an already labelled sequence of patches,+-- so that all patches are initially 'InMiddle'.+mkPatchChoices :: FL (LabelledPatch p) wX wY -> PatchChoices p wX wY+mkPatchChoices = PCs NilFL . mapFL_FL (pcSetLast False) -instance MyEq p => MyEq (PatchChoice p) where-    unsafeCompare (PC lp1 _) (PC lp2 _) = unsafeCompare lp1 lp2+instance Eq2 p => Eq2 (PatchChoice p) where+  unsafeCompare (PC lp1 _) (PC lp2 _) = unsafeCompare lp1 lp2  -separateFirstFromMiddleLast :: Patchy p => PatchChoices p wX wZ-                                -> (FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wZ-separateFirstFromMiddleLast (PCs f l) = f :> mapFL_FL (\ (PC lp _) -> lp) l+-- | Like 'getChoices' but lumps together 'InMiddle' and 'InLast' patches.+-- This is more efficient than using 'getChoices' and then catenating 'InMiddle'+-- and 'InLast' sections because we have to commute less.+-- (This is what 'PatchChoices' are optimized for.)+--+-- prop> separateFirstFromMiddleLast c == case getChoices c of f:>m:>l -> f:>m+>+l+separateFirstFromMiddleLast :: PatchChoices p wX wZ+                            -> (FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wZ+separateFirstFromMiddleLast (PCs f ml) = f :> mapFL_FL pcPatch ml -separateFirstMiddleFromLast :: Patchy p => PatchChoices p wX wZ-                                -> (FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wZ+-- | Like 'getChoices' but lumps together 'InFirst' and 'InMiddle' patches.+--+-- prop> separateFirstMiddleFromLast c == case getChoices c of f:>m:>l -> f+>+m:>l+separateFirstMiddleFromLast :: Commute p+                            => PatchChoices p wX wZ+                            -> (FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wZ separateFirstMiddleFromLast (PCs f l) =   case pushLasts l of     (m :> l') -> f +>+ m :> l' --- | @getChoices@ evaluates a @PatchChoices@ into the first, middle and last sequences--- by doing the commutes that were needed.-getChoices :: Patchy p => PatchChoices p wX wY-            -> (FL (LabelledPatch p) :> FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wY-getChoices (PCs f l) =-  case pushLasts l of-       (m :> l') -> f :> m :> l'+-- | Retrieve the resulting sections from a 'PatchChoice'.  The result is a+-- triple @first:>middle:>last@, such that all patches in @first@ are+-- 'InFirst', all patches in @middle@ are 'InMiddle', and all patches in @last@+-- are 'InLast'.+getChoices :: Commute p+           => PatchChoices p wX wY+           -> (FL (LabelledPatch p) :> FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wY+getChoices (PCs f ml) =+  case pushLasts ml of+    (m :> l') -> f :> m :> l' -pushLasts :: Patchy p => FL (PatchChoice p) wX wY-            -> (FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wY+-- | Internal function to commute patches in the common 'pcsMiddleLasts' segment+-- so that all 'InLast' patches are behind 'InMiddle' ones. Patches 'InMiddle'+-- that depend on any 'InLast' are promoted to 'InLast'.+pushLasts :: Commute p+          => FL (PatchChoice p) wX wY+          -> (FL (LabelledPatch p) :> FL (LabelledPatch p)) wX wY pushLasts NilFL = NilFL :> NilFL pushLasts (PC lp False :>: pcs) =   case pushLasts pcs of@@ -211,27 +248,32 @@       case commuteWhatWeCanFL (lp :> m) of         (m' :> lp' :> deps) -> m' :> (lp' :>: deps +>+ l) --- | @refineChoices act@ performs @act@ on the middle part of a sequence--- of choices, in order to hopefully get more patches into the @first@ and--- @last@ parts of a @PatchChoices@.-refineChoices :: (Patchy p, Monad m, Functor m) =>-                (forall wU wV . FL (LabelledPatch p) wU wV ->-                      PatchChoices p wU wV ->-                      m (PatchChoices p wU wV))-                -> PatchChoices p wX wY -> m (PatchChoices p wX wY)+-- TODO for the way we use this function it is too restrictive IMO: it does not+-- allow the user to select anything that doesn't match the pre-filters.+-- | Use the given monadic 'PatchChoices' transformer on the 'InMiddle' section+-- of a 'PatchChoices', then fold the result back into the original 'PatchChoices'.+refineChoices :: (Commute p, Monad m)+              => (forall wU wV . FL (LabelledPatch p) wU wV ->+                  PatchChoices p wU wV -> m (PatchChoices p wU wV))+              -> PatchChoices p wX wY -> m (PatchChoices p wX wY) refineChoices act ps =-      case getChoices ps of-        (f :> m :> l) -> do-          let mchoices = PCs NilFL . mapFL_FL (flip PC False) $ m-          (PCs f' l') <- act m mchoices-          return . PCs (f +>+ f') $ l' +>+ mapFL_FL (flip PC True) l+  case getChoices ps of+    (f :> m :> l) -> do+      (PCs f' l') <- act m (mkPatchChoices m)+      return . PCs (f +>+ f') $ l' +>+ mapFL_FL (pcSetLast True) l -patchSlot :: forall p wA wB wX wY. Patchy p => LabelledPatch p wA wB-          -> PatchChoices p wX wY -> (Slot, PatchChoices p wX wY)-patchSlot (LP t _) pc@(PCs f l) =-  if foundIn f-  then (InFirst, pc)-  else psLast f NilRL NilRL l+-- | Given a 'LabelledPatch' determine to which section of the given+-- 'PatchChoices' it belongs. This is not trivial to compute, since a patch+-- tagged as 'InMiddle' may be forced to actually be 'InLast' by dependencies. We+-- return a possibly re-ordered 'PatchChoices' so as not to waste the+-- commutation effort.+patchSlot :: forall p wA wB wX wY. Commute p+          => LabelledPatch p wA wB+          -> PatchChoices p wX wY+          -> (Slot, PatchChoices p wX wY)+patchSlot (LP t _) pc@(PCs f ml)+  | foundIn f = (InFirst, pc)+  | otherwise = psLast f NilRL NilRL ml   where     foundIn = anyFL ((== t) . label)     psLast :: forall wM wC wL .@@ -243,7 +285,7 @@     psLast firsts middles bubble (PC lp True :>: ls)       | label lp == t = (InLast                       , PCs { pcsFirsts = firsts-                            , pcsLasts = settleM middles+                            , pcsMiddleLasts = settleM middles                                          +>+ settleB bubble                                          +>+ PC lp True :>: ls})     psLast firsts middles bubble (PC lp False :>: ls)@@ -251,13 +293,13 @@         case commuteRL (bubble :> lp) of         Just (lp' :> bubble') -> (InMiddle,                                  PCs { pcsFirsts = firsts-                                     , pcsLasts = settleM middles+                                     , pcsMiddleLasts = settleM middles                                                   +>+ PC lp' False                                                   :>: settleB bubble'                                                   +>+ ls})         Nothing -> (InLast,                    PCs { pcsFirsts = firsts-                       , pcsLasts = settleM middles+                       , pcsMiddleLasts = settleM middles                                     +>+ settleB bubble                                     +>+ PC lp True                                     :>: ls})@@ -271,16 +313,14 @@     settleM middles = mapFL_FL (\lp -> PC lp False) $ reverseRL middles     settleB bubble = mapFL_FL (\lp -> PC lp True) $ reverseRL bubble -patchSlot' :: Patchy p =>-              LabelledPatch p wA wB -> StateT (PatchChoices p wX wY) Identity Slot-patchSlot' lp = StateT (return . patchSlot lp)--forceMatchingFirst :: forall p wA wB. Patchy p =>-                      ( forall wX wY . LabelledPatch p wX wY -> Bool)-                      -> PatchChoices p wA wB-                      -> PatchChoices p wA wB-forceMatchingFirst pred (PCs fn l) =-  fmfLasts fn NilRL l+-- | Force all patches matching the given predicate to be 'InFirst',+-- pulling any dependencies with them. This even forces any patches+-- that were already tagged 'InLast'.+forceMatchingFirst :: forall p wA wB. Commute p+                   => ( forall wX wY . LabelledPatch p wX wY -> Bool)+                   -> PatchChoices p wA wB+                   -> PatchChoices p wA wB+forceMatchingFirst pred (PCs f0 ml) = fmfLasts f0 NilRL ml     where       fmfLasts :: FL (LabelledPatch p) wA wM                  -> RL (PatchChoice p) wM wN@@ -295,21 +335,30 @@                 in fmfLasts f' l1' l2       fmfLasts f l1 (a :>: l2) = fmfLasts f (l1 :<: a) l2       fmfLasts f l1 NilFL = PCs { pcsFirsts = f-                                , pcsLasts = reverseRL l1 }+                                , pcsMiddleLasts = reverseRL l1 }       pred_pc :: forall wX wY . PatchChoice p wX wY -> Bool       pred_pc (PC lp _) = pred lp -forceFirsts :: Patchy p => [Label] -> PatchChoices p wA wB-              -> PatchChoices p wA wB+-- | Force all patches labelled with one of the given labels to be 'InFirst',+-- pulling any dependencies with them. This even forces any patches+-- that were already tagged 'InLast'.+forceFirsts :: Commute p+            => [Label] -> PatchChoices p wA wB -> PatchChoices p wA wB forceFirsts ps = forceMatchingFirst ((`elem` ps) . label) -forceFirst :: Patchy p => Label -> PatchChoices p wA wB-              -> PatchChoices p wA wB+-- | Force a single patch labelled with the given label to be 'InFirst',+-- pulling any dependencies with them. This even forces any patches+-- that were already tagged 'InLast'.+forceFirst :: Commute p+           => Label -> PatchChoices p wA wB -> PatchChoices p wA wB forceFirst p = forceMatchingFirst ((== p) . label) --TODO: stop after having seen the patch we want to force first -selectAllMiddles :: forall p wX wY. Patchy p => Bool-                   -> PatchChoices p wX wY -> PatchChoices p wX wY+-- | Make all 'InMiddle' patches either 'InFirst' or 'InLast'. This does *not*+-- modify any patches that are already determined to be 'InLast' by+-- dependencies.+selectAllMiddles :: forall p wX wY. Commute p+                 => Bool -> PatchChoices p wX wY -> PatchChoices p wX wY selectAllMiddles True (PCs f l) = PCs f (mapFL_FL g l)     where g (PC lp _) = PC lp True selectAllMiddles False (PCs f l) = samf f NilRL NilRL l@@ -327,73 +376,98 @@     samf f1 f2 l1 (PC lp True :>: l2) = samf f1 f2 (l1 :<: PC lp True) l2     samf f1 f2 l1 NilFL = PCs (f1 +>+ reverseRL f2) (reverseRL l1) -forceMatchingLast :: Patchy p => (forall wX wY . LabelledPatch p wX wY -> Bool)-                     -> PatchChoices p wA wB-                     -> PatchChoices p wA wB-forceMatchingLast pred (PCs f l) = do-  fmlFirst pred True NilRL f l+-- | Similar to 'forceMatchingFirst' only that patches are forced to be+-- 'InLast' regardless of their previous status.+forceMatchingLast :: Commute p => (forall wX wY . LabelledPatch p wX wY -> Bool)+                  -> PatchChoices p wA wB+                  -> PatchChoices p wA wB+forceMatchingLast pred (PCs f ml) =+  forceMatchingMiddleOrLast pred True NilRL f ml -fmlFirst :: forall p wA wB wM1 wM2 . Patchy p =>-           (forall wX wY . LabelledPatch p wX wY -> Bool) -> Bool-           -> RL (LabelledPatch p) wA wM1-           -> FL (LabelledPatch p) wM1 wM2-           -> FL (PatchChoice p) wM2 wB-           -> PatchChoices p wA wB-fmlFirst pred b f1 (a :>: f2) l-        | pred a =-          case commuteWhatWeCanFL (a :> f2) of-            (f2' :> a' :> deps) ->-              let-                l' = mapFL_FL (\lp -> PC lp b) (a' :>: deps) +>+ l-              in-              fmlFirst pred b f1 f2' l'-fmlFirst pred b f1 (a :>: f2) l = fmlFirst pred b (f1 :<: a) f2 l-fmlFirst pred b f1 NilFL l = PCs { pcsFirsts = reverseRL f1-                                 , pcsLasts = mapFL_FL ch l}-  where ch (PC lp c) = (PC lp (if pred lp then b else c) )+-- | Internal function working directly on the constituent parts of a+-- 'PatchChoices' and taking an accumulating 'RL' to build up a new 'InFirst'+-- section.  It forces patches to be 'InMiddle' or 'InLast', depending+-- on the 'Bool' parameter ('True' means 'InLast', 'False' means 'InMiddle').+-- It does this regardless of the previous status of patches and also pulls+-- any dependent patches with it.+forceMatchingMiddleOrLast+  :: forall p wA wB wM1 wM2 . Commute p+  => (forall wX wY . LabelledPatch p wX wY -> Bool)+  -> Bool+  -> RL (LabelledPatch p) wA wM1  -- ^ accumulator for 'InFirst' patches+  -> FL (LabelledPatch p) wM1 wM2 -- ^ original 'InFirst' section+  -> FL (PatchChoice p) wM2 wB    -- ^ original 'InMiddle' and 'InLast' section+  -> PatchChoices p wA wB+forceMatchingMiddleOrLast pred b f1 (a :>: f2) ml+  | pred a =+    case commuteWhatWeCanFL (a :> f2) of+      (f2' :> a' :> deps) ->+        let+          ml' = mapFL_FL (pcSetLast b) (a' :>: deps) +>+ ml+        in+        forceMatchingMiddleOrLast pred b f1 f2' ml'+forceMatchingMiddleOrLast pred b f1 (a :>: f2) ml =+  forceMatchingMiddleOrLast pred b (f1 :<: a) f2 ml+forceMatchingMiddleOrLast pred b f1 NilFL ml =+  PCs { pcsFirsts = reverseRL f1+      , pcsMiddleLasts = mapFL_FL choose ml+      }+  where+    choose (PC lp c) = (PC lp (if pred lp then b else c) ) -forceLasts :: Patchy p => [Label]-                    -> PatchChoices p wA wB -> PatchChoices p wA wB+-- | Force all patches labelled with one of the given labels to be 'InLast',+-- pulling any dependencies with them. This even forces any patches+-- that were previously tagged 'InFirst'.+forceLasts :: Commute p+           => [Label] -> PatchChoices p wA wB -> PatchChoices p wA wB forceLasts ps = forceMatchingLast ((`elem` ps) . label) -forceLast :: Patchy p => Label-                    -> PatchChoices p wA wB -> PatchChoices p wA wB+-- | Force a single patch labelled with the given label to be 'InLast',+-- pulling any dependencies with them, regardless of their previous status.+forceLast :: Commute p+          => Label -> PatchChoices p wA wB -> PatchChoices p wA wB forceLast p = forceMatchingLast ((== p) . label) -makeUncertain :: Patchy p => Label -> PatchChoices p wA wB -> PatchChoices p wA wB-makeUncertain t (PCs f l) = fmlFirst ((== t) . label) False NilRL f l+-- | Force a patch with the given 'Label' to be 'InMiddle',+-- pulling any dependencies with it, regardless of their previous status.+forceMiddle :: Commute p => Label -> PatchChoices p wA wB -> PatchChoices p wA wB+forceMiddle t (PCs f l) = forceMatchingMiddleOrLast ((== t) . label) False NilRL f l -makeEverythingLater :: Patchy p => PatchChoices p wX wY -> PatchChoices p wX wY-makeEverythingLater (PCs f l) =-  let m = mapFL_FL (\lp -> PC lp False) f-      l' = mapFL_FL (\(PC lp _) -> PC lp True) l-  in-  PCs NilFL $ m +>+ l'+-- | Turn 'InFirst' patches into 'InMiddle' ones and 'InMiddle' into 'InLast' ones.+makeEverythingLater :: PatchChoices p wX wY -> PatchChoices p wX wY+makeEverythingLater (PCs f ml) =+  let m = mapFL_FL (pcSetLast False) f+      ml' = mapFL_FL (\(PC lp _) -> PC lp True) ml+  in PCs NilFL $ m +>+ ml' -makeEverythingSooner :: forall p wX wY.-  Patchy p => PatchChoices p wX wY -> PatchChoices p wX wY-makeEverythingSooner (PCs f l) =-  case mes NilRL NilRL l-       of (m :> l') ->-            PCs (f +>+ m) l'+-- | Turn 'InMiddle' patches into 'InFirst' and 'InLast' patches into 'InMiddle'.+-- Does *not* pull dependencies into 'InFirst', instead patches that+-- cannot be commuted past 'InLast' patches stay 'InMiddle'.+makeEverythingSooner :: forall p wX wY. Commute p+                     => PatchChoices p wX wY -> PatchChoices p wX wY+makeEverythingSooner (PCs f ml) =+  case mes NilRL NilRL ml+       of (m :> ml') ->+            PCs (f +>+ m) ml'     where       mes :: forall wM1 wM2 wM3 .             RL (LabelledPatch p) wM1 wM2 ->             RL (LabelledPatch p) wM2 wM3 ->             FL (PatchChoice p) wM3 wY ->             (FL (LabelledPatch p) :> FL (PatchChoice p)) wM1 wY-      mes middle bubble (PC lp True :>: ls) = mes middle (bubble :<: lp) ls-      mes middle bubble (PC lp False :>: ls) =+      mes middle bubble (PC lp True :>: mls) = mes middle (bubble :<: lp) mls+      mes middle bubble (PC lp False :>: mls) =         case commuteRL (bubble :> lp) of-          Nothing -> mes middle (bubble :<: lp) ls-          Just (lp' :> bubble') -> mes (middle :<: lp') bubble' ls-      mes middle bubble NilFL = (reverseRL middle) :> mapFL_FL (\lp -> PC lp False) (reverseRL bubble)+          Nothing -> mes middle (bubble :<: lp) mls+          Just (lp' :> bubble') -> mes (middle :<: lp') bubble' mls+      mes middle bubble NilFL =+        (reverseRL middle) :> mapFL_FL (\lp -> PC lp False) (reverseRL bubble) --- | 'substitute' @(a :||: bs)@ @pcs@ replaces @a@ with @bs@ in @pcs@ preserving the choice---   associated with @a@-substitute :: forall p wX wY-            . Patchy p-           => Sealed2 (LabelledPatch p :||: FL (LabelledPatch p))+-- | Substitute a single 'LabelledPatch' with an equivalent list of patches,+-- preserving its status as 'InFirst', 'InMiddle' or 'InLast').+-- The patch is looked up using equality of 'Label's.+substitute :: forall p wX wY .+              Sealed2 (LabelledPatch p :||: FL (LabelledPatch p))            -> PatchChoices p wX wY            -> PatchChoices p wX wY substitute (Sealed2 (lp :||: new_lps)) (PCs f l) =@@ -405,5 +479,5 @@        | otherwise = lp' :>: NilFL      substPc :: PatchChoice p wA wB -> FL (PatchChoice p) wA wB      substPc (PC lp' c)-       | IsEq <- compareLabels lp lp' = mapFL_FL (flip PC c) new_lps+       | IsEq <- compareLabels lp lp' = mapFL_FL (pcSetLast c) new_lps        | otherwise = PC lp' c :>: NilFL
src/Darcs/Patch/Conflict.hs view
@@ -1,5 +1,5 @@ --  Copyright (C) 2002-2003 David Roundy, 2010 Ganesh Sittampalam-{-# LANGUAGE CPP, ViewPatterns #-}+{-# LANGUAGE ViewPatterns #-} module Darcs.Patch.Conflict     ( Conflict(..), CommuteNoConflicts(..), listConflictedFiles     , IsConflictedPrim(..), ConflictState(..)@@ -31,8 +31,6 @@ import Darcs.Util.Path ( FileName, fn2fp, fp2fn ) import Darcs.Util.Show ( appPrec ) -#include "impossible.h"- listConflictedFiles :: Conflict p => p wX wY -> [FilePath] listConflictedFiles p =     nubSort $ concatMap (unseal listTouchedFiles) $ concat $ resolveConflicts p@@ -61,14 +59,32 @@                                          return $ ys' :> reverseRL rxs'  instance (CommuteNoConflicts p, Conflict p) => Conflict (RL p) where+    -- By definition, a conflicting (primitive) patch is resolved if+    -- another (primitive) patch depends on the conflict.+    -- +    -- So, when looking for conflicts in a list of patches, we go+    -- through the whole list looking for individual patches that are+    -- in conflict. But then we try to commute them past all the+    -- patches we've already seen. If we fail, i.e. there's something+    -- that depends on the conflict, then we forget about the conflict;+    -- this is the Nothing case of the 'commuteNoConflictsFL' call.+    --+    -- Note that 'primitive' does not mean Prim (this is a case of bad+    -- naming) but rather a RepoPatchV1 or RepoPatchV2. Prim patches+    -- are merely a 'base class' containing everything common to V1 and+    -- V2 primitive patches.     resolveConflicts x = rcs x NilFL-        where rcs :: RL p wX wY -> FL p wY wW -> [[Sealed (FL (PrimOf p) wW)]]-              rcs NilRL _ = []-              rcs (ps:<:p) passedby | (_:_) <- resolveConflicts p =-                  case commuteNoConflictsFL (p:>passedby) of-                    Just (_:> p') -> resolveConflicts p' ++ rcs ps (p:>:passedby)-                    Nothing -> rcs ps (p:>:passedby)-              rcs (ps:<:p) passedby = seq passedby $ rcs ps (p:>:passedby)+      where+        rcs :: RL p wX wY -> FL p wY wW -> [[Sealed (FL (PrimOf p) wW)]]+        rcs NilRL _ = []+        rcs (ps :<: p) passedby+          | null (resolveConflicts p) = seq passedby rest -- TODO why seq here?+          | otherwise =+            case commuteNoConflictsFL (p :> passedby) of+              Just (_ :> p') -> resolveConflicts p' ++ rest+              Nothing -> rest+          where+            rest = rcs ps (p :>: passedby)     conflictedEffect = concat . reverse . mapRL conflictedEffect  instance CommuteNoConflicts p => CommuteNoConflicts (RL p) where
src/Darcs/Patch/Depends.hs view
@@ -15,7 +15,7 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP , ScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables #-}  module Darcs.Patch.Depends     ( getUncovered@@ -28,8 +28,8 @@     , slightlyOptimizePatchset     , getPatchesBeyondTag     , splitOnTag-    , newsetUnion-    , newsetIntersection+    , patchSetUnion+    , patchSetIntersection     , findUncommon     , merge2FL     , getDeps@@ -39,41 +39,35 @@ import Prelude () import Darcs.Prelude -#include "impossible.h"- import Prelude hiding ( pi ) import Data.List ( delete, intersect, (\\) ) import Data.Maybe ( fromMaybe )-import qualified Data.ByteString.Char8 as BC ( unpack ) import Control.Arrow ( (&&&) )  import Darcs.Patch ( RepoPatch )-import Darcs.Patch.Apply( ApplyState )-import Darcs.Patch.Patchy ( Patchy ) import Darcs.Patch.Named ( Named (..), patch2patchinfo ) import Darcs.Patch.Named.Wrapped ( getdeps ) import Darcs.Patch.Choices ( Label, patchChoices, forceFirst-                           , PatchChoices, lpPatch, getChoices+                           , PatchChoices, unLabel, getChoices                            , LabelledPatch, label )-import Darcs.Patch.Commute ( commute, commuteFL, commuteRL )-import Darcs.Patch.Info ( PatchInfo, isTag, showPatchInfoUI, _piName )+import Darcs.Patch.Commute ( Commute, commute, commuteFL, commuteRL )+import Darcs.Patch.Info ( PatchInfo, isTag, displayPatchInfo, piName ) import Darcs.Patch.Merge ( Merge, mergeFL ) import Darcs.Patch.Permutations ( partitionFL, partitionRL ) import Darcs.Patch.PatchInfoAnd( PatchInfoAnd, hopefully, hopefullyM, info )-import Darcs.Patch.Set ( PatchSet(..), Tagged(..), SealedPatchSet, newset2RL,+import Darcs.Patch.Set ( PatchSet(..), Tagged(..), SealedPatchSet, patchSet2RL,                          appendPSFL ) import Darcs.Patch.Progress ( progressRL ) import Darcs.Patch.Witnesses.Eq ( EqCheck(..), (=\/=), (=/\=) ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP, unsafeCoercePStart ) import Darcs.Patch.Witnesses.Ordered     ( (:\/:)(..), (:/\:)(..), (:>)(..), Fork(..),-    (+>+), mapFL, RL(..), FL(..), isShorterThanRL,+    (+>>+), (+<<+), mapFL, RL(..), FL(..), isShorterThanRL,     (+<+), reverseFL, reverseRL, mapRL, lengthFL, splitAtFL ) import Darcs.Patch.Witnesses.Sealed     ( Sealed(..), FlippedSeal(..), flipSeal, seal, Sealed2(..), seal2 ) -import Darcs.Util.Printer ( renderString, vcat, RenderMode(..) )-import Darcs.Util.Tree ( Tree )+import Darcs.Util.Printer ( renderString, vcat )  {-  - This module uses the following definitions:@@ -100,17 +94,17 @@                        )  -- | Searchs dependencies in @repoFL@ of the patches in @getDepsFL@.-getDeps :: (RepoPatch p, ApplyState p ~ Tree) =>+getDeps :: (RepoPatch p) =>             FL (Named p) wA wR -> FL (PatchInfoAnd rt p) wX wY -> [SPatchAndDeps p] getDeps repoFL getDepsFL =         let repoChoices   = patchChoices repoFL-            getDepsFL'    = mapFL (BC.unpack . _piName . info) getDepsFL+            getDepsFL'    = mapFL (piName . info) getDepsFL             labelledDeps  = getLabelledDeps getDepsFL' repoChoices         in             map (deps repoChoices) labelledDeps     where         -- Search dependencies for the patch with label @l@ in @repoChoices@.-        deps :: (Patchy (Named p)) => PatchChoices (Named p) wX wY ->+        deps :: (Commute p) => PatchChoices (Named p) wX wY ->                 (String,Label) -> SPatchAndDeps p         deps repoChoices (_,l) =             case getChoices $ forceFirst l repoChoices of@@ -122,7 +116,7 @@                                                     -- has r, which is the patch                                                     -- that we are looking at                                                     -- dependencies.-        getLabelledDeps :: Patchy (Named p) => [String] ->+        getLabelledDeps :: (Commute p) => [String] ->                            PatchChoices (Named p) x y -> [(String, Label)]         getLabelledDeps patchnames repoChoices =             case getChoices repoChoices of@@ -138,7 +132,7 @@                                     else filterDepsFL patchnames lps             where                 lpTostring :: LabelledPatch (Named p) wA wB -> String-                lpTostring = BC.unpack . _piName . patch2patchinfo . lpPatch+                lpTostring = piName . patch2patchinfo . unLabel                 dep :: (String, Label)                 dep = lpTostring &&& label $ lp @@ -155,13 +149,13 @@ taggedIntersection does its best to reduce the number of inventories that are accessed from its rightmost argument. -}-taggedIntersection :: forall rt p wStart wX wY . Patchy p =>-                      PatchSet rt p wStart wX -> PatchSet rt p wStart wY ->+taggedIntersection :: forall rt p wStart wX wY . Commute p+                   => PatchSet rt p wStart wX -> PatchSet rt p wStart wY ->                       Fork (RL (Tagged rt p))                            (RL (PatchInfoAnd rt p))                            (RL (PatchInfoAnd rt p)) wStart wX wY-taggedIntersection (PatchSet NilRL ps1) s2 = Fork NilRL ps1 (newset2RL s2)-taggedIntersection s1 (PatchSet NilRL ps2) = Fork NilRL (newset2RL s1) ps2+taggedIntersection (PatchSet NilRL ps1) s2 = Fork NilRL ps1 (patchSet2RL s2)+taggedIntersection s1 (PatchSet NilRL ps2) = Fork NilRL (patchSet2RL s1) ps2 taggedIntersection s1 (PatchSet (_ :<: Tagged t _ _) ps2)     | Just (PatchSet ts1 ps1) <- maybeSplitSetOnTag (info t) s1 =     Fork ts1 ps1 (unsafeCoercePStart ps2)@@ -172,7 +166,7 @@                        Just (PatchSet com NilRL :> us) ->                            Fork com us (unsafeCoercePStart ps2)                        Just _ -> impossible-                       Nothing -> Fork NilRL (newset2RL s1) (newset2RL s2)+                       Nothing -> Fork NilRL (patchSet2RL s1) (patchSet2RL s2)  -- |'maybeSplitSetOnTag' takes a tag's 'PatchInfo', @t0@, and a 'PatchSet' and -- attempts to find @t0@ in one of the 'Tagged's in the PatchSet. If the tag is@@ -188,7 +182,7 @@         Just $ PatchSet ts' (ps' +<+ ps) maybeSplitSetOnTag _ _ = Nothing -getPatchesBeyondTag :: Patchy p => PatchInfo -> PatchSet rt p wStart wX+getPatchesBeyondTag :: Commute p => PatchInfo -> PatchSet rt p wStart wX                     -> FlippedSeal (RL (PatchInfoAnd rt p)) wX getPatchesBeyondTag t (PatchSet (_ :<: Tagged hp _ _) ps) | info hp == t =     flipSeal ps@@ -203,7 +197,7 @@         else case getPatchesBeyondTag t (PatchSet ts ps) of                  FlippedSeal xxs -> FlippedSeal (xxs :<: hp) getPatchesBeyondTag t (PatchSet NilRL NilRL) =-    bug $ "tag\n" ++ renderString Encode (showPatchInfoUI t)+    bug $ "tag\n" ++ renderString (displayPatchInfo t)           ++ "\nis not in the patchset in getPatchesBeyondTag." getPatchesBeyondTag t0 (PatchSet (ts :<: Tagged t _ ps) NilRL) =     getPatchesBeyondTag t0 (PatchSet ts (ps :<: t))@@ -212,7 +206,7 @@ -- find the tag in the PatchSet, returning a pair: the clean PatchSet "up to" -- the tag, and a RL of patches after the tag; If the tag is not in the -- PatchSet, we return Nothing.-splitOnTag :: Patchy p => PatchInfo -> PatchSet rt p wStart wX+splitOnTag :: Commute p => PatchInfo -> PatchSet rt p wStart wX            -> Maybe ((PatchSet rt p :> RL (PatchInfoAnd rt p)) wStart wX) -- If the tag we are looking for is the first Tagged tag of the patchset, just -- separate out the patchset's patches.@@ -323,7 +317,7 @@                      appendPSFL ps' (hp :>: NilFL)         | otherwise = appendPSFL (sops $ PatchSet ts ps) (hp :>: NilFL) -removeFromPatchSet :: Patchy p => FL (PatchInfoAnd rt p) wX wY+removeFromPatchSet :: Commute p => FL (PatchInfoAnd rt p) wX wY                    -> PatchSet rt p wStart wY -> Maybe (PatchSet rt p wStart wX) removeFromPatchSet bad (PatchSet ts ps) | all (`elem` mapRL info ps) (mapFL info bad) = do     ps' <- fastRemoveSubsequenceRL (reverseFL bad) ps@@ -332,14 +326,14 @@ removeFromPatchSet bad (PatchSet (ts :<: Tagged t _ tps) ps) =     removeFromPatchSet bad (PatchSet ts (tps :<: t +<+ ps)) -fastRemoveSubsequenceRL :: Patchy p+fastRemoveSubsequenceRL :: Commute p                         => RL (PatchInfoAnd rt p) wY wZ                         -> RL (PatchInfoAnd rt p) wX wZ                         -> Maybe (RL (PatchInfoAnd rt p) wX wY) fastRemoveSubsequenceRL NilRL ys = Just ys fastRemoveSubsequenceRL (xs:<:x) ys = fastRemoveRL x ys >>= fastRemoveSubsequenceRL xs -findCommonAndUncommon :: forall rt p wStart wX wY . Patchy p+findCommonAndUncommon :: forall rt p wStart wX wY . Commute p                       => PatchSet rt p wStart wX -> PatchSet rt p wStart wY                       -> Fork (PatchSet rt p)                               (FL (PatchInfoAnd rt p))@@ -349,21 +343,21 @@         case partitionFL (infoIn them') $ reverseRL us' of             _ :> bad@(_ :>: _) :> _ ->                 bug $ "Failed to commute common patches:\n"-                      ++ renderString Encode-                          (vcat $ mapRL (showPatchInfoUI . info) $ reverseFL bad)+                      ++ renderString+                          (vcat $ mapRL (displayPatchInfo . info) $ reverseFL bad)             (common2 :> NilFL :> only_ours) ->                 case partitionFL (infoIn us') $ reverseRL them' of                     _ :> bad@(_ :>: _) :> _ ->                         bug $ "Failed to commute common patches:\n"-                            ++ renderString Encode (vcat $-                                mapRL (showPatchInfoUI . info) $ reverseFL bad)+                            ++ renderString (vcat $+                                mapRL (displayPatchInfo . info) $ reverseFL bad)                     _ :> NilFL :> only_theirs ->                         Fork (PatchSet common (reverseFL common2))                             only_ours (unsafeCoercePStart only_theirs)   where     infoIn inWhat = (`elem` mapRL info inWhat) . info -findCommonWithThem :: Patchy p+findCommonWithThem :: Commute p                    => PatchSet rt p wStart wX                    -> PatchSet rt p wStart wY                    -> (PatchSet rt p :> FL (PatchInfoAnd rt p)) wStart wX@@ -372,12 +366,12 @@         case partitionFL ((`elem` mapRL info them') . info) $ reverseRL us' of             _ :> bad@(_ :>: _) :> _ ->                 bug $ "Failed to commute common patches:\n"-                      ++ renderString Encode-                          (vcat $ mapRL (showPatchInfoUI . info) $ reverseFL bad)+                      ++ renderString+                          (vcat $ mapRL (displayPatchInfo . info) $ reverseFL bad)             common2 :> _nilfl :> only_ours ->                 PatchSet common (reverseFL common2) :> unsafeCoerceP only_ours -findUncommon :: Patchy p+findUncommon :: Commute p              => PatchSet rt p wStart wX -> PatchSet rt p wStart wY              -> (FL (PatchInfoAnd rt p) :\/: FL (PatchInfoAnd rt p)) wX wY findUncommon us them =@@ -385,7 +379,7 @@         _common :> us' -> case findCommonWithThem them us of             _ :> them' -> unsafeCoercePStart us' :\/: them' -countUsThem :: Patchy p+countUsThem :: Commute p             => PatchSet rt p wStart wX             -> PatchSet rt p wStart wY             -> (Int, Int)@@ -395,7 +389,7 @@                                 tt = mapRL info them' in                             (length $ uu \\ tt, length $ tt \\ uu) -mergeThem :: (Patchy p, Merge p)+mergeThem :: (Merge p)           => PatchSet rt p wStart wX -> PatchSet rt p wStart wY           -> Sealed (FL (PatchInfoAnd rt p) wX) mergeThem us them =@@ -404,28 +398,28 @@             case merge2FL (reverseRL us') (reverseRL them') of                them'' :/\: _ -> Sealed them'' -newsetIntersection :: Patchy p+patchSetIntersection :: Commute p                    => [SealedPatchSet rt p wStart]                    -> SealedPatchSet rt p wStart-newsetIntersection [] = seal $ PatchSet NilRL NilRL-newsetIntersection [x] = x-newsetIntersection (Sealed y : ys) =-    case newsetIntersection ys of+patchSetIntersection [] = seal $ PatchSet NilRL NilRL+patchSetIntersection [x] = x+patchSetIntersection (Sealed y : ys) =+    case patchSetIntersection ys of         Sealed z -> case taggedIntersection y z of             Fork common a b -> case mapRL info a `intersect` mapRL info b of                 morecommon ->                     case partitionRL (\e -> info e `notElem` morecommon) a of                         commonps :> _ -> seal $ PatchSet common commonps -newsetUnion :: (Patchy p, Merge p)+patchSetUnion :: (Merge p)             => [SealedPatchSet rt p wStart]             -> SealedPatchSet rt p wStart-newsetUnion [] = seal $ PatchSet NilRL NilRL-newsetUnion [x] = x-newsetUnion (Sealed y@(PatchSet tsy psy) : Sealed y2 : ys) =+patchSetUnion [] = seal $ PatchSet NilRL NilRL+patchSetUnion [x] = x+patchSetUnion (Sealed y@(PatchSet tsy psy) : Sealed y2 : ys) =     case mergeThem y y2 of         Sealed p2 ->-            newsetUnion $ seal (PatchSet tsy (psy +<+ reverseFL p2)) : ys+            patchSetUnion $ seal (PatchSet tsy (psy +<+ reverseFL p2)) : ys  -- | Merge two FLs (say L and R), starting in a common context. The result is a -- FL starting in the original end context of L, going to a new context that is@@ -440,7 +434,7 @@ --   (bf: I guess what was meant here is that 'merge2FL' works in the --    the way it does because it considers patch meta data whereas --    'mergeFL' cannot since it must work for primitive patches, too.-merge2FL :: (Patchy p, Merge p)+merge2FL :: (Merge p)          => FL (PatchInfoAnd rt p) wX wY          -> FL (PatchInfoAnd rt p) wX wZ          -> (FL (PatchInfoAnd rt p) :/\: FL (PatchInfoAnd rt p)) wY wZ@@ -454,7 +448,7 @@                                                 ys'' :/\: xs' ->                                                    ys'' :/\: (x' :>: xs') -areUnrelatedRepos :: Patchy p+areUnrelatedRepos :: Commute p                   => PatchSet rt p wStart wX                   -> PatchSet rt p wStart wY -> Bool areUnrelatedRepos us them =@@ -477,12 +471,7 @@ -- The types fit together (internally, in this module) because we commute the -- patch to the front before removing it and commutation inside a sequence does -- not change the sequence's contexts.------ However, the use sites outside this module are something different. We--- usually need coercions to get the patch(es) to be removed in shape. This is--- not very nice but probably unavoidable given the approximative nature of--- context witnesses.-fastRemoveFL :: Patchy p+fastRemoveFL :: Commute p              => PatchInfoAnd rt p wX wY -- this type assumes element is at the front              -> FL (PatchInfoAnd rt p) wX wZ              -> Maybe (FL (PatchInfoAnd rt p) wY wZ)@@ -496,18 +485,18 @@     Just (b' :>: bs')   where     i = info a-    pullout :: Patchy p+    pullout :: Commute p             => RL (PatchInfoAnd rt p) wA wB             -> FL (PatchInfoAnd rt p) wB wC             -> Maybe ((PatchInfoAnd rt p :> FL (PatchInfoAnd rt p)) wA wC)     pullout _ NilFL = Nothing     pullout acc (x :>: xs)         | info x == i = do x' :> acc' <- commuteRL (acc :> x)-                           Just (x' :> reverseRL acc' +>+ xs)+                           Just (x' :> acc' +>>+ xs)         | otherwise = pullout (acc :<: x) xs  -- | Same as 'fastRemoveFL' only for 'RL'.-fastRemoveRL :: Patchy p+fastRemoveRL :: Commute p              => PatchInfoAnd rt p wY wZ -- this type assumes element is at the back              -> RL (PatchInfoAnd rt p) wX wZ              -> Maybe (RL (PatchInfoAnd rt p) wX wY)@@ -521,12 +510,12 @@     Just (bs' :<: b')   where     i = info a-    pullout :: Patchy p+    pullout :: Commute p             => RL (PatchInfoAnd rt p) wA wB             -> FL (PatchInfoAnd rt p) wB wC             -> Maybe ((RL (PatchInfoAnd rt p) :> PatchInfoAnd rt p) wA wC)     pullout NilRL _ = Nothing     pullout (xs :<: x) acc         | info x == i = do acc' :> x' <- commuteFL (x :> acc)-                           Just (xs +<+ reverseFL acc' :> x')+                           Just (xs +<<+ acc' :> x')         | otherwise = pullout xs (x :>: acc)
src/Darcs/Patch/Dummy.hs view
@@ -2,24 +2,28 @@ {-# LANGUAGE EmptyDataDecls #-} module Darcs.Patch.Dummy ( DummyPatch ) where +import Darcs.Patch.Annotate ( Annotate ) import Darcs.Patch.Conflict ( Conflict, CommuteNoConflicts ) import Darcs.Patch.Debug ( PatchDebug(..) ) import Darcs.Patch.Effect ( Effect ) import Darcs.Patch.FileHunk ( IsHunk ) import Darcs.Patch.Format ( PatchListFormat ) import Darcs.Patch.Matchable ( Matchable )-import Darcs.Patch.Patchy-    ( Patchy, ShowPatch, Invert, Commute, Apply(..), PatchInspect-    , ReadPatch )-import Darcs.Patch.Prim ( FromPrim, PrimPatch, PrimPatchBase(..) )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute )+import Darcs.Patch.Invert ( Invert )+import Darcs.Patch.Inspect ( PatchInspect )+import Darcs.Patch.Read ( ReadPatch )+import Darcs.Patch.Show ( ShowPatch )+import Darcs.Patch.Prim ( FromPrim, PrimPatchCommon, PrimPatch, PrimPatchBase(..) ) import Darcs.Patch.Prim.Class         ( PrimConstruct, PrimCanonize, PrimClassify         , PrimDetails, PrimShow, PrimRead, PrimApply ) import Darcs.Patch.Merge ( Merge) import Darcs.Patch.Repair ( Check, RepairToFL ) import Darcs.Patch.RepoPatch ( RepoPatch )-import Darcs.Patch.Show ( ShowPatchBasic )-import Darcs.Patch.Witnesses.Eq ( MyEq )+import Darcs.Patch.Show ( ShowPatchBasic, ShowContextPatch )+import Darcs.Patch.Witnesses.Eq ( Eq2 ) import Darcs.Patch.Witnesses.Show ( Show2 ) import Darcs.Util.Tree( Tree ) @@ -29,15 +33,16 @@  instance IsHunk DummyPrim instance PatchListFormat DummyPrim-instance MyEq DummyPrim+instance Eq2 DummyPrim instance Invert DummyPrim instance PatchInspect DummyPrim instance ReadPatch DummyPrim instance ShowPatchBasic DummyPrim instance ShowPatch DummyPrim+instance ShowContextPatch DummyPrim instance Commute DummyPrim-instance Apply DummyPrim-instance Patchy DummyPrim+instance Apply DummyPrim where+  type ApplyState DummyPrim = Tree  instance RepairToFL DummyPrim instance PrimConstruct DummyPrim@@ -52,20 +57,23 @@  instance PatchDebug DummyPrim +instance PrimPatchCommon DummyPrim+ instance IsHunk DummyPatch instance PatchListFormat DummyPatch-instance MyEq DummyPatch+instance Eq2 DummyPatch instance Invert DummyPatch instance PatchInspect DummyPatch instance ReadPatch DummyPatch instance ShowPatchBasic DummyPatch instance ShowPatch DummyPatch+instance ShowContextPatch DummyPatch instance Show2 DummyPatch instance Commute DummyPatch instance Apply DummyPatch where   type ApplyState DummyPatch = Tree instance Matchable DummyPatch-instance Patchy DummyPatch+instance Annotate DummyPatch  instance Effect DummyPatch instance Merge DummyPatch
src/Darcs/Patch/Format.hs view
@@ -1,7 +1,6 @@ module Darcs.Patch.Format     ( PatchListFormat(..)     , ListFormat(..)-    , copyListFormat     , FileNameFormat(..)     ) where @@ -29,10 +28,8 @@     | ListFormatV2      -- ^ Show lists without braces. Read with arbitrary                         -- nested parens and flatten them out. -copyListFormat :: ListFormat p -> ListFormat q-copyListFormat ListFormatDefault = ListFormatDefault-copyListFormat ListFormatV1 = ListFormatV1-copyListFormat ListFormatV2 = ListFormatV2--data FileNameFormat = OldFormat-                    | NewFormat+data FileNameFormat+    = OldFormat  -- ^ on-disk format for V1 patches+    | NewFormat  -- ^ on-disk format for V2 patches+    | UserFormat -- ^ display format+    deriving (Eq, Show)
src/Darcs/Patch/Index/Monad.hs view
@@ -17,15 +17,21 @@ -- Boston, MA 02110-1301, USA.  -{-# LANGUAGE CPP,GeneralizedNewtypeDeriving #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} -module Darcs.Patch.Index.Monad ( FileModMonad, withPatchMods ) where+module Darcs.Patch.Index.Monad+    ( withPatchMods+    , applyToFileMods+    , makePatchID+    ) where  import Prelude () import Darcs.Prelude -import Darcs.Patch.Index.Types ( PatchMod(..) )+import Darcs.Patch.Index.Types ( PatchMod(..), PatchId(..) )+import Darcs.Patch.Info ( makePatchname, PatchInfo )+import Darcs.Patch.Apply ( Apply(..) ) import Darcs.Patch.ApplyMonad ( ApplyMonad(..), ApplyMonadTree(..) ) import Control.Monad.State import Control.Arrow@@ -34,7 +40,6 @@ import Data.Set ( Set ) import Data.List ( isPrefixOf ) import Darcs.Util.Tree (Tree)-#include "impossible.h"  newtype FileModMonad a = FMM (State (Set FileName, [PatchMod FileName]) a)   deriving (Functor, Applicative, Monad, MonadState (Set FileName, [PatchMod FileName]))@@ -79,7 +84,6 @@                addMod (PRename fn newfn)      mModifyFilePS f _ = addMod (PTouch f)-    mModifyFilePSs f _ = addMod (PTouch f)  -- --------------------------------------------------------------------- -- State Handling Functions@@ -117,3 +121,11 @@  modifyFps :: (Set FileName -> Set FileName) -> FileModMonad () modifyFps f = modify $ first f++makePatchID :: PatchInfo -> PatchId+makePatchID = PID . makePatchname++--------------------------------------------------------------------------------+-- | Apply a patch to set of 'FileName's, yielding the new set of 'FileName's and 'PatchMod's+applyToFileMods :: (Apply p, ApplyState p ~ Tree) => p wX wY -> Set FileName -> (Set FileName, [PatchMod FileName])+applyToFileMods patch = withPatchMods (apply patch)
src/Darcs/Patch/Index/Types.hs view
@@ -21,9 +21,8 @@ import Prelude () import Darcs.Prelude -import Darcs.Util.Crypt.SHA1( SHA1(..) )-import Darcs.Util.Path ( fp2fn, fn2fp, FileName )-import Darcs.Patch.Info ( makePatchname, PatchInfo )+import Darcs.Util.Hash( SHA1, sha1short, sha1zero )+import Darcs.Util.Path ( fn2fp, FileName ) import Data.Binary ( Binary(..) ) import Data.Word ( Word32 ) @@ -40,10 +39,6 @@    (rfp,cnt) <- get    return $ FileId rfp cnt --- | Parse FileId from a string-parseFileId :: String -> FileId-parseFileId s = let (f,'.':i) = break (=='.') s in FileId (fp2fn f) (read i)- -- | Convert FileId to string showFileId :: FileId -> String showFileId (FileId fn i) = show i++"#"++fn2fp fn@@ -59,12 +54,6 @@ pid2string :: PatchId -> String pid2string = show . patchId --- | describes a filepath that is interpreted relative to a certain---   point in the history of the repository. The point is given by---   Just pid which denotes the history up to (including) pid or---   Nothing which denotes the history including the last patch-data DatedFilePath = DatedFilePath FilePath (Maybe PatchId)- -- | This is used to track changes to files data PatchMod a = PTouch a                 | PCreateFile a@@ -79,9 +68,9 @@                                      --   track of them  deriving (Show, Eq, Functor) -makePatchID :: PatchInfo -> PatchId-makePatchID = PID . makePatchname- short :: PatchId -> Word32-short (PID (SHA1 a _ _ _ _)) = a+short (PID sha1) = sha1short sha1++zero :: PatchId+zero = PID sha1zero 
src/Darcs/Patch/Info.hs view
@@ -15,48 +15,77 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -module Darcs.Patch.Info ( PatchInfo(..), patchinfo, invertName,-                          rawPatchInfo,-                          addJunk, makePatchname,-                          makeFilename, readPatchInfo,-                          justName, justAuthor, justLog,-                          showPatchInfoUI, toXml, piDate,-                          setPiDate, piDateString, piDateBytestring,-                          piName, piRename, piAuthor, piTag, piLog,-                          showPatchInfo, isTag, readPatchInfos, escapeXML-                        ) where+module Darcs.Patch.Info+    ( PatchInfo(..) -- constructor and fields exported *only for tests*+    , rawPatchInfo  -- exported *only for tests*+    , patchinfo+    , invertName+    , addJunk+    , makePatchname+    , readPatchInfo+    , justName+    , justAuthor+    , justLog+    , displayPatchInfo+    , toXml+    , toXmlShort+    , piDate+    , setPiDate+    , piDateString+    , piName+    , piRename+    , piAuthor+    , piTag+    , piLog+    , showPatchInfo+    , isTag+    , escapeXML+    , validDate+    , validLog+    , validAuthor+    , validDatePS+    , validLogPS+    , validAuthorPS+    ) where -import Prelude ()+import Prelude ( (^) ) import Darcs.Prelude +import Data.Char ( isAscii ) import System.Random ( randomRIO ) import Numeric ( showHex ) import Control.Monad ( when, unless, void ) -import Darcs.Util.ByteString ( unlinesPS, packStringToUTF8, unpackPSFromUTF8, decodeLocale)+import Darcs.Util.ByteString+    ( decodeLocale+    , packStringToUTF8+    , unlinesPS+    , unpackPSFromUTF8+    ) import qualified Darcs.Patch.ReadMonads as RM ( take ) import Darcs.Patch.ReadMonads as RM ( skipSpace, char,                                       takeTill, anyChar, ParserM,-                                      option, parseStrictly,+                                      option,                                       takeTillChar,                                       linesStartingWithEndingWith)+import Darcs.Patch.Show ( ShowPatchFor(..) ) import qualified Data.ByteString       as B  (length, splitAt, null                                              ,isPrefixOf, tail, concat                                              ,empty, head, cons, append                                              ,ByteString )-import qualified Data.ByteString.Char8 as BC (index, head, unpack, pack)+import qualified Data.ByteString.Char8 as BC+    ( index, head, notElem, all, unpack, pack ) import Data.List( isPrefixOf )  import Darcs.Util.Printer ( Doc, packedString,                  empty, ($$), (<>), (<+>), vcat, text, cyanText, blueText, prefix )-import Darcs.Patch.OldDate ( readUTCDate, showIsoDateTime )-import System.Time ( CalendarTime(ctTZ), calendarTimeToString, toClockTime,+import Darcs.Util.IsoDate ( readUTCDate )+import System.Time ( CalendarTime, calendarTimeToString, toClockTime,                      toCalendarTime ) import System.IO.Unsafe ( unsafePerformIO )-import Darcs.Util.Crypt.SHA1 ( sha1PS, SHA1 )+import Darcs.Util.Hash ( sha1PS, SHA1 ) import Darcs.Util.Prompt ( promptYorn ) import Darcs.Util.Show ( appPrec )-import Prelude hiding (pi, log)  -- | A PatchInfo value contains the metadata of a patch. The date, name, author -- and log fields are UTF-8 encoded text in darcs 2.4 and later, and just@@ -82,13 +111,47 @@             showString " " . showsPrec (appPrec + 1) log .             showString " " . showsPrec (appPrec + 1) inverted +-- Validation++-- We need these functions to ensure that we can parse the+-- result of showPatchInfo.++validDate :: String -> Bool+validDate = all validCharForDate++validDatePS :: B.ByteString -> Bool+validDatePS = BC.all validCharForDate++-- | The isAscii limitation is due to the use of BC.pack below.+validCharForDate :: Char -> Bool+validCharForDate c = isAscii c && c /= '\n' && c /= ']'++validLog :: String -> Bool+validLog = notElem '\n'++validLogPS :: B.ByteString -> Bool+validLogPS = BC.notElem '\n'++validAuthor :: String -> Bool+validAuthor = notElem '*'++validAuthorPS :: B.ByteString -> Bool+validAuthorPS = BC.notElem '*'+ rawPatchInfo :: String -> String -> String -> [String] -> Bool -> PatchInfo rawPatchInfo date name author log inverted =-    PatchInfo { _piDate     = BC.pack date-              , _piName     = packStringToUTF8 name-              , _piAuthor   = packStringToUTF8 author-              , _piLog      = map packStringToUTF8 log+    PatchInfo { _piDate     = BC.pack $ validateDate date+              , _piName     = packStringToUTF8 $ validateName name+              , _piAuthor   = packStringToUTF8 $ validateAuthor author+              , _piLog      = map (packStringToUTF8 . validateLog) log               , isInverted  = inverted }+  where+    validateAuthor = validate validAuthor "author"+    validateName = validate validLog "patch name"+    validateLog = validate validLog "log line"+    validateDate = validate validDate "date"+    validate test meta x =+      if test x then x else error (unwords ["invalid",meta,show x])  -- | @patchinfo date name author log@ constructs a new 'PatchInfo' value -- with the given details, automatically assigning an Ignore-this header@@ -104,7 +167,8 @@ addJunk pinf =     do x <- randomRIO (0,2^(128 ::Integer) :: Integer)        when (_piLog pinf /= ignoreJunk (_piLog pinf)) $-            do putStrLn "Lines beginning with 'Ignore-this: ' will be ignored."+            do putStrLn $ "Lines beginning with 'Ignore-this: ' " +++                          "will not be shown when displaying a patch."                confirmed <- promptYorn "Proceed? "                unless confirmed $ fail "User cancelled because of Ignore-this."        return $ pinf { _piLog = BC.pack (head ignored++showHex x ""):@@ -136,8 +200,8 @@ justLog :: PatchInfo -> String justLog = unlines . map BC.unpack . _piLog -showPatchInfoUI :: PatchInfo -> Doc-showPatchInfoUI pi =+displayPatchInfo :: PatchInfo -> Doc+displayPatchInfo pi =     cyanText "patch " <> cyanText (show $ makePatchname pi)  $$ text "Author: " <> text (piAuthor pi)  $$ text "Date:   " <> text (friendlyD $ _piDate pi)@@ -163,16 +227,12 @@ isTag :: PatchInfo -> Bool isTag pinfo = "TAG " `isPrefixOf` justName pinfo --- | Note: we ignore timezone information in the date string,---   systematically treating a time as UTC.  So if the patch---   tells me it's 17:00 EST, we're actually treating it as---   17:00 UTC, in other words 11:00 EST.  This is for---   backwards compatibility to darcs prior to 2003-11, sometime---   before 1.0.  Fortunately, newer patch dates are written in---   UTC, so this timezone truncation is harmless for them.+-- | Read the date from raw patch (meta) data and convert it to UTC.+-- The raw data may contain timezone info. This is for compatibiltity+-- with patches that were created before 2003-11, when darcs still+-- created patches that contained localized date strings. readPatchDate :: B.ByteString -> CalendarTime-readPatchDate = ignoreTz . readUTCDate . BC.unpack-  where ignoreTz ct = ct { ctTZ = 0 }+readPatchDate = readUTCDate . BC.unpack  piDate :: PatchInfo -> CalendarTime piDate = readPatchDate . _piDate@@ -180,9 +240,6 @@ piDateString :: PatchInfo -> String piDateString = BC.unpack . _piDate -piDateBytestring :: PatchInfo -> B.ByteString-piDateBytestring = _piDate- setPiDate :: String -> PatchInfo -> PatchInfo setPiDate date pi = pi { _piDate = BC.pack date } @@ -209,23 +266,31 @@   where bsUtf8 = unpackPSFromUTF8 bs  friendlyD :: B.ByteString -> String---friendlyD d = calendarTimeToString . readPatchDate . d friendlyD d = unsafePerformIO $ do     ct <- toCalendarTime $ toClockTime $ readPatchDate d     return $ calendarTimeToString ct  toXml :: PatchInfo -> Doc-toXml pi =+toXml = toXml' True++toXmlShort :: PatchInfo -> Doc+toXmlShort = toXml' False++toXml' :: Bool -> PatchInfo -> Doc+toXml' includeComments pi =         text "<patch"     <+> text "author='" <> escapeXMLByteString (_piAuthor pi) <> text "'"     <+> text "date='" <> escapeXMLByteString (_piDate pi) <> text "'"     <+> text "local_date='" <> escapeXML (friendlyD $ _piDate pi) <> text "'"     <+> text "inverted='" <> text (show $ isInverted pi) <> text "'"     <+> text "hash='" <> text (show $ makePatchname pi) <> text "'>"- $$     prefix "\t" (-            text "<name>" <> escapeXMLByteString (_piName pi) <> text "</name>"-         $$ commentsAsXml (_piLog pi))- $$     text "</patch>"+    $$  indent abstract+    $$  text "</patch>"+      where+        indent = prefix "    "+        name = text "<name>" <> escapeXMLByteString (_piName pi) <> text "</name>"+        abstract | includeComments = name $$ commentsAsXml (_piLog pi)+                 | otherwise = name  commentsAsXml :: [B.ByteString] -> Doc commentsAsXml comments@@ -264,22 +329,6 @@                                      else B.cons (B.head bs)                                                  (bstrReplace c s (B.tail bs)) --- | This makes darcs-1 (non-hashed repos) filenames, and is also generally--- used in both in hashed and non-hashed repo code for making patch "hashes".------ The name consists of three segments:------  * timestamp (ISO8601-compatible yyyymmmddHHMMSS, UTC)------  * SHA1 hash of the author------  * SHA1 hash of the patch name, author, date, log, and \"inverted\"---    flag.-makeFilename :: PatchInfo -> String-makeFilename pi = showIsoDateTime d++"-"++sha1_a++"-"++ (show $ makePatchname pi) ++ ".gz"-    where d = readPatchDate $ _piDate pi-          sha1_a = take 5 $ show $ sha1PS $ _piAuthor pi- -- | Hash on patch metadata (patch name, author, date, log, and \"inverted\" -- flag. Robust against context changes but does not garantee patch contents. -- Usually used as matcher or patch identifier (see Darcs.Patch.Match).@@ -294,6 +343,10 @@                                   b2ps $ isInverted pi]  +showPatchInfo :: ShowPatchFor -> PatchInfo -> Doc+showPatchInfo ForDisplay = displayPatchInfo+showPatchInfo ForStorage = storePatchInfo+ -- |Patch is stored between square brackets. -- -- > [ <patch name>@@ -306,8 +359,9 @@ -- -- note that below I assume the name has no newline in it. -- See 'readPatchInfo' for the inverse operation.-showPatchInfo :: PatchInfo -> Doc-showPatchInfo pi =+-- There are more assumptions, see validation functions above.+storePatchInfo :: PatchInfo -> Doc+storePatchInfo pi =     blueText "[" <> packedString (_piName pi)  $$ packedString (_piAuthor pi) <> text inverted <> packedString (_piDate pi)                                  <> myunlines (_piLog pi) <> blueText "] "@@ -343,10 +397,3 @@                    , _piLog = log                    , isInverted = BC.index s2 1 /= '*'                    }--readPatchInfos :: B.ByteString -> [PatchInfo]-readPatchInfos inv | B.null inv = []-readPatchInfos inv = case parseStrictly readPatchInfo inv of-                     Just (pinfo,r) -> pinfo : readPatchInfos r-                     _ -> []-
src/Darcs/Patch/Invert.hs view
@@ -6,7 +6,8 @@ import Prelude () import Darcs.Prelude -import Darcs.Patch.Witnesses.Ordered ( FL(..), RL(..), reverseFL, reverseRL )+import Darcs.Patch.Witnesses.Ordered+    ( FL(..), RL(..), reverseFL, reverseRL, (:>)(..) )   class Invert p where@@ -25,3 +26,6 @@  instance Invert p => Invert (RL p) where     invert = reverseFL . invertRL++instance Invert p => Invert (p :> p) where+  invert (a :> b) = invert b :> invert a
src/Darcs/Patch/Match.hs view
@@ -15,7 +15,7 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, ScopedTypeVariables, MultiParamTypeClasses, FlexibleInstances, Rank2Types #-}+{-# LANGUAGE ScopedTypeVariables, MultiParamTypeClasses, FlexibleInstances #-}  -- | /First matcher, Second matcher and Nonrange matcher/ --@@ -47,11 +47,11 @@     , splitSecondFL     , matchPatch     , matchAPatch-    , matchAPatchread     , getNonrangeMatchS     , firstMatch     , secondMatch     , haveNonrangeMatch+    , haveNonrangeExplicitMatch     , havePatchsetMatch     , checkMatchSyntax     , applyInvToMatcher@@ -102,8 +102,7 @@  import Darcs.Util.Path ( AbsolutePath ) import Darcs.Patch-    ( Patchy-    , IsRepoType+    ( IsRepoType     , hunkMatches     , listTouchedFiles     , invert@@ -125,11 +124,12 @@ import Darcs.Patch.MonadProgress ( MonadProgress ) import Darcs.Patch.Named.Wrapped ( runInternalChecker, namedIsInternal, namedInternalChecker ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, info, conscientiously, hopefully )-import Darcs.Patch.Set ( PatchSet(..), Tagged(..), SealedPatchSet, newset2RL, Origin )+import Darcs.Patch.Set ( PatchSet(..), Tagged(..), SealedPatchSet, patchSet2RL, Origin ) import Darcs.Patch.Type ( PatchType(..) )-import Darcs.Patch.Apply( ApplyState )+import Darcs.Patch.Apply( Apply, ApplyState ) import Darcs.Patch.ApplyPatches( applyPatches ) import Darcs.Patch.Depends ( getPatchesBeyondTag, splitOnTag )+import Darcs.Patch.Invert( Invert )  import Darcs.Patch.Witnesses.Eq ( isIsEq ) import Darcs.Patch.Witnesses.Ordered ( RL(..), snocRLSealed, FL(..), (:>)(..) )@@ -142,7 +142,6 @@ import Darcs.Util.DateMatcher ( parseDateMatcher )  import Darcs.Util.Tree ( Tree )-#include "impossible.h"  -- | A type for predicates over patches which do not care about -- contexts@@ -177,7 +176,7 @@                  deriving ( Show )  -makeMatcher :: String -> (Sealed2 (PatchInfoAnd rt p) -> Bool) -> Matcher rt p+makeMatcher :: String -> MatchFun rt p -> Matcher rt p makeMatcher = MATCH  -- | @applyMatcher@ applies a matcher to a patch.@@ -197,7 +196,7 @@     Left err -> error err     Right m -> makeMatcher pattern m -addInternalMatcher :: (IsRepoType rt, Matchable p) => Maybe (Matcher rt p) -> Maybe (Matcher rt p)+addInternalMatcher :: (IsRepoType rt) => Maybe (Matcher rt p) -> Maybe (Matcher rt p) addInternalMatcher om =   case namedInternalChecker of     Nothing -> om@@ -218,16 +217,16 @@     -- When using <?>, Parsec prepends "expecting " to the given error message,     -- so the phrasing below makes sense.     helpfulErrorMsg = "valid expressions over: "-                      ++ intercalate ", " (map (\(name, _, _, _) -> name) ps)+                      ++ intercalate ", " (map (\(name, _, _, _, _) -> name) ps)                       ++ "\nfor more help, see `darcs help patterns`."      -- This type signature is just to bind an ambiguous type var.-    ps :: [(String, String, [String], String -> MatchFun rt DummyPatch)]+    ps :: [(String, String, String, [String], String -> MatchFun rt DummyPatch)]     ps = primitiveMatchers      -- matchAnyPatch is returned if submatch fails without consuming any     -- input, i.e. if we pass --match '', we want to match anything.-    matchAnyPatch :: Matchable p => MatchFun rt p+    matchAnyPatch :: MatchFun rt p     matchAnyPatch = const True  submatch :: Matchable p => CharParser st (MatchFun rt p)@@ -258,16 +257,15 @@   where     matchers_ = map createMatchHelper primitiveMatchers -createMatchHelper :: (String, String, [String], String -> MatchFun rt p)+createMatchHelper :: (String, String, String, [String], String -> MatchFun rt p)                   -> CharParser st (MatchFun rt p)-createMatchHelper (key,_,_,matcher) =+createMatchHelper (key,_,_,_,matcher) =   do _ <- trystring key      spaces      q <- quoted      return $ matcher q --- FIXME: would this be better defined in Darcs.Commands.Help?--- | The string that is emitted when the user runs @darcs help --match@.+-- | The string that is emitted when the user runs @darcs help patterns@. helpOnMatchers :: [String] helpOnMatchers =   ["Selecting Patches:",@@ -291,45 +289,42 @@   ++ ["", "Here are some examples:", ""]   ++ examples   where -- This type signature exists to appease GHC.-        ps :: [(String, String, [String], String -> MatchFun rt DummyPatch)]+        ps :: [(String, String, String, [String], String -> MatchFun rt DummyPatch)]         ps = primitiveMatchers-        keywords = [showKeyword k d | (k,d,_,_) <- ps]-        examples = [showExample k e | (k,_,es,_) <- ps, e <- es]+        keywords = [showKeyword (unwords [k,a]) d | (k,a,d,_,_) <- ps]+        examples = [showExample k e | (k,_,_,es,_) <- ps, e <- es]         showKeyword keyword description =-            -- FIXME: it would be nice to have a variable name here:-            -- "author REGEX - match against author (email address)"-            -- or "exact STRING - match against exact patch name".-            "- " ++ keyword ++ " - " ++ description ++ "."+            "  " ++ keyword ++ " - " ++ description ++ "."         showExample keyword example =-            "    darcs log --match "+            "  darcs log --match "             ++ "'" ++ keyword ++ " " ++ example ++ "'" -primitiveMatchers :: Matchable p => [(String, String, [String], String -> MatchFun rt p)]-                     -- ^ keyword (operator), help description, list+primitiveMatchers :: Matchable p => [(String, String, String, [String], String -> MatchFun rt p)]+                     -- ^ keyword (operator), argument name, help description, list                      -- of examples, matcher function primitiveMatchers =- [ ("exact", "check a literal string against the patch name"+ [ ("exact", "STRING", "check literal STRING is equal to patch name"            , ["\"Resolve issue17: use dynamic memory allocation.\""]            , exactmatch )- , ("name", "check a regular expression against the patch name"+ , ("name", "REGEX", "match REGEX against patch name"           , ["issue17", "\"^[Rr]esolve issue17\\>\""]           , namematch )- , ("author", "check a regular expression against the author name"+ , ("author", "REGEX", "match REGEX against patch author"             , ["\"David Roundy\"", "droundy", "droundy@darcs.net"]             , authormatch )- , ("hunk", "check a regular expression against the contents of a hunk patch"+ , ("hunk", "REGEX", "match REGEX against contents of a hunk patch"             , ["\"foo = 2\"", "\"^instance .* Foo where$\""]             , hunkmatch )- , ("comment", "check a regular expression against the log message"+ , ("comment", "REGEX", "match REGEX against the full log message"          , ["\"prevent deadlocks\""]          , logmatch )- , ("hash",  "match a full hash or a prefix for a patch"+ , ("hash", "HASH", "match HASH against (a prefix of) the hash of a patch"           ,  ["c719567e92c3b0ab9eddd5290b705712b8b918ef","c7195"]           ,  hashmatch )- , ("date", "match the patch date"+ , ("date", "DATE", "match DATE against the patch date"           , ["\"2006-04-02 22:41\"", "\"tea time yesterday\""]           , datematch )- , ("touch", "match file paths for a patch"+ , ("touch", "REGEX", "match file paths for a patch"           , ["src/foo.c", "src/", "\"src/*.(c|h)\""]           , touchmatch ) ] @@ -346,7 +341,10 @@          <|> between spaces spaces (many $ noneOf " ()")          <?> "string" -namematch, exactmatch, authormatch, hunkmatch, hashmatch, datematch, touchmatch+datematch, hashmatch, authormatch, exactmatch, namematch, logmatch+  :: String -> MatchFun rt p++hunkmatch, touchmatch   :: Matchable p => String -> MatchFun rt p  namematch r (Sealed2 hp) = isJust $ matchRegex (mkRegex r) $ justName (info hp)@@ -355,7 +353,6 @@  authormatch a (Sealed2 hp) = isJust $ matchRegex (mkRegex a) $ justAuthor (info hp) -logmatch :: Matchable p => String -> MatchFun rt p logmatch l (Sealed2 hp) = isJust $ matchRegex (mkRegex l) $ justLog (info hp)  hunkmatch r (Sealed2 hp) = let regexMatcher = isJust . matchRegex (mkRegex r) . BC.unpack@@ -373,14 +370,31 @@  data InclusiveOrExclusive = Inclusive | Exclusive deriving Eq +data IncludeInternalPatches = IncludeInternalPatches | ExcludeInternalPatches+                              deriving Eq+ -- | @haveNonrangeMatch flags@ tells whether there is a flag in -- @flags@ which corresponds to a match that is "non-range". Thus, -- @--match@, @--patch@, @--hash@ and @--index@ make @haveNonrangeMatch@ -- true, but not @--from-patch@ or @--to-patch@.-haveNonrangeMatch :: forall rt p . (IsRepoType rt, Matchable p) => PatchType rt p -> [MatchFlag] -> Bool-haveNonrangeMatch _ fs =+haveNonrangeMatch :: forall rt p . (IsRepoType rt, Matchable p)+                  => PatchType rt p -> [MatchFlag] -> Bool+haveNonrangeMatch pt fs = haveNonrangeMatch' IncludeInternalPatches pt fs++-- | @haveNonrangeExplicitMatch flags@ is just like @haveNonrangeMatch flags@,+-- but ignores "internal matchers" used to mask "internal patches"+haveNonrangeExplicitMatch :: forall rt p . (IsRepoType rt, Matchable p)+                          => PatchType rt p -> [MatchFlag] -> Bool+haveNonrangeExplicitMatch pt fs = haveNonrangeMatch' ExcludeInternalPatches pt fs++haveNonrangeMatch' :: forall rt p . (IsRepoType rt, Matchable p)+                   => IncludeInternalPatches -> PatchType rt p -> [MatchFlag] -> Bool+haveNonrangeMatch' i _ fs =      case hasIndexRange fs of Just (m,n) | m == n -> True; _ -> False-  || isJust (nonrangeMatcher fs::Maybe (Matcher rt p))+  || isJust (nonrangeMatch::Maybe (Matcher rt p))+    where+     nonrangeMatch | i == IncludeInternalPatches = nonrangeMatcher fs+                   | otherwise = nonrangeMatcherArgs fs  -- | @havePatchsetMatch flags@ tells whether there is a "patchset -- match" in the flag list. A patchset match is @--match@ or@@ -438,11 +452,11 @@ secondMatch :: [MatchFlag] -> Bool secondMatch fs = isJust (secondMatcher fs::Maybe (Matcher rt DummyPatch)) || isJust (hasIndexRange fs) -unpullLastN :: (ApplyMonad (ApplyState p) m, MonadProgress m, Patchy p, IsRepoType rt)+unpullLastN :: (Apply p, Invert p, ApplyMonad (ApplyState p) m, MonadProgress m, IsRepoType rt)             => PatchSet rt p wX wY             -> Int             -> m ()-unpullLastN repo n = applyInvRL `unsealFlipped` safetake n (newset2RL repo)+unpullLastN repo n = applyInvRL `unsealFlipped` safetake n (patchSet2RL repo)  checkMatchSyntax :: [MatchFlag] -> IO () checkMatchSyntax opts =@@ -456,16 +470,16 @@ getMatchPattern (SeveralPattern m:_) = Just m getMatchPattern (_:fs) = getMatchPattern fs -tagmatch :: Matchable p => String -> Matcher rt p+tagmatch :: String -> Matcher rt p tagmatch r = makeMatcher ("tag-name "++r) tm     where tm (Sealed2 p) =               let n = justName (info p) in               "TAG " `isPrefixOf` n && isJust (matchRegex (mkRegex r) $ drop 4 n) -patchmatch :: Matchable p => String -> Matcher rt p+patchmatch :: String -> Matcher rt p patchmatch r = makeMatcher ("patch-name "++r) (namematch r) -hashmatch' :: Matchable p => String -> Matcher rt p+hashmatch' :: String -> Matcher rt p hashmatch' r = makeMatcher ("hash "++r) (hashmatch r)  @@ -535,18 +549,11 @@ secondMatcherIsTag (UpToTag _:_) = True secondMatcherIsTag (_:fs) = secondMatcherIsTag fs --- | @matchAPatchread fs p@ tells whether @p@ matches the matchers in--- the flags listed in @fs@.-matchAPatchread :: (IsRepoType rt, Matchable p) => [MatchFlag] -> PatchInfoAnd rt p wX wY -> Bool-matchAPatchread fs = case nonrangeMatcher fs of-                       Nothing -> const True-                       Just m -> applyMatcher m- -- | @matchAPatch fs p@ tells whether @p@ matches the matchers in -- the flags @fs@ matchAPatch :: (IsRepoType rt, Matchable p) => [MatchFlag] -> PatchInfoAnd rt p wX wY -> Bool matchAPatch fs p =-    case nonrangeMatcher fs of+  case nonrangeMatcher fs of     Nothing -> True     Just m -> applyMatcher m p @@ -647,8 +654,8 @@ findAPatch m (PatchSet ts (ps:<:p)) | applyMatcher m p = seal2 $ hopefully p                                     | otherwise = findAPatch m (PatchSet ts ps) --- | @matchAPatchset m ps@ returns a (the largest?) subset of @ps@--- ending in patch which matches @m@. Calls 'error' if there is none.+-- | @matchAPatchset m ps@ returns a prefix of @ps@+-- ending in a patch matching @m@, and calls 'error' if there is none. matchAPatchset :: Matchable p => Matcher rt p -> PatchSet rt p wStart wX                -> SealedPatchSet rt p wStart matchAPatchset m (PatchSet NilRL NilRL) = error $ "Couldn't find patch matching " ++ show m@@ -723,7 +730,7 @@ -- | @applyInvp@ tries to get the patch that's in a 'PatchInfoAnd -- patch', and to apply its inverse. If we fail to fetch the patch -- then we share our sorrow with the user.-applyInvp :: (Patchy p, ApplyMonad (ApplyState p) m) => PatchInfoAnd rt p wX wY -> m ()+applyInvp :: (Apply p, Invert p, ApplyMonad (ApplyState p) m) => PatchInfoAnd rt p wX wY -> m () applyInvp hp = apply (invert $ fromHopefully hp)     where fromHopefully = conscientiously $ \e ->                      text "Sorry, patch not available:"@@ -739,5 +746,5 @@ safetake i (as:<:a) | isIsEq (namedIsInternal (hopefully a)) = safetake i as `snocRLSealed` a safetake i (as:<:a) = safetake (i-1) as `snocRLSealed` a -applyInvRL :: (ApplyMonad (ApplyState p) m, MonadProgress m, Patchy p) => RL (PatchInfoAnd rt p) wX wR -> m ()+applyInvRL :: (Apply p, Invert p, ApplyMonad (ApplyState p) m, MonadProgress m) => RL (PatchInfoAnd rt p) wX wR -> m () applyInvRL = applyPatches . invertRL -- this gives nicer feedback
src/Darcs/Patch/Matchable.hs view
@@ -5,7 +5,9 @@ module Darcs.Patch.Matchable ( Matchable ) where  import Darcs.Patch.Inspect ( PatchInspect )-import Darcs.Patch.Patchy ( Patchy )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Invert ( Invert(..) ) -class (Patchy p, PatchInspect p)+class (Apply p, Commute p, Invert p, PatchInspect p)     => Matchable p
src/Darcs/Patch/Merge.hs view
@@ -5,24 +5,43 @@ -- Portability : portable  module Darcs.Patch.Merge-    (+    ( -- * Definitions       Merge(..)     , selfMerger     , mergeFL+    , naturalMerge+      -- * Properties+    , prop_mergeSymmetric+    , prop_mergeCommute     ) where -import Darcs.Patch.Commute ( Commute )+import Darcs.Patch.Commute ( Commute(..) ) import Darcs.Patch.CommuteFn ( MergeFn )+import Darcs.Patch.Invert ( Invert(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..), isIsEq ) import Darcs.Patch.Witnesses.Ordered     ( (:\/:)(..)     , (:/\:)(..)     , FL(..)     , RL+    , (:>)(..)     , reverseFL     , reverseRL     ) --- | Things that can always be merged+-- | Things that can always be merged.+--+-- Instances should obey the following laws:+--+-- * Symmetry+--+--   prop> merge (p :\/: q) == q' :/\: p' <=> merge (q :\/: p) == p' :/\: q'+--+-- * MergesCommute+--+--   prop> merge (p :\/: q) == q' :/\: p' ==> commute (p :> q') == Just (q :> p')+--+--   that is, the two branches of a merge commute to each other class Commute p => Merge p where     merge :: (p :\/: p) wX wY           -> (p :/\: p) wX wY@@ -48,3 +67,35 @@ mergeFL (p :\/: (x :>: xs)) = case merge (p :\/: x) of     x' :/\: p' -> case mergeFL (p' :\/: xs) of       xs' :/\: p'' -> (x' :>: xs') :/\: p''++-- | The natural, non-conflicting merge.+naturalMerge :: (Invert p, Commute p)+             => (p :\/: p) wX wY -> Maybe ((p :/\: p) wX wY)+naturalMerge (p :\/: q) = do+  q' :> ip' <- commute (invert p :> q)+  -- TODO: find a small convincing example that demonstrates why+  -- it is necessary to do this extra check here+  _ <- commute (p :> q')+  return (q' :/\: invert ip')++prop_mergeSymmetric :: (Eq2 p, Merge p) => (p :\/: p) wX wY -> Bool+prop_mergeSymmetric (p :\/: q) =+  case merge (p :\/: q) of+    q' :/\: p' ->+      case merge (q :\/: p) of+        p'' :/\: q'' ->+          isIsEq (q' =\/= q'') && isIsEq (p' =\/= p'')++prop_mergeCommute :: (Eq2 p, Merge p) => (p :\/: p) wX wY -> Bool+prop_mergeCommute (p :\/: q) =+  case merge (p :\/: q) of+    q' :/\: p' ->+      case commute (p :> q') of+        Nothing -> False+        Just (q'' :> p'') ->+          isIsEq (q'' =\/= q) && isIsEq (p'' =/\= p')+      &&+      case commute (q :> p') of+        Nothing -> False+        Just (p'' :> q'') ->+          isIsEq (p'' =\/= p) && isIsEq (q'' =/\= q')
src/Darcs/Patch/MonadProgress.hs view
@@ -55,5 +55,5 @@ silentlyRunProgressActions :: Monad m => String -> [ProgressAction m ()] -> m () silentlyRunProgressActions _ = mapM_ paAction -instance (Functor m, Monad m) => MonadProgress (TM.TreeMonad m) where+instance (Monad m) => MonadProgress (TM.TreeMonad m) where   runProgressActions = silentlyRunProgressActions
src/Darcs/Patch/Named.hs view
@@ -15,9 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}-- module Darcs.Patch.Named        ( Named(..),          infopatch,@@ -42,25 +39,30 @@ import Darcs.Patch.FileHunk ( IsHunk(..) ) import Darcs.Patch.Format ( PatchListFormat ) import Darcs.Patch.Info ( PatchInfo, readPatchInfo, showPatchInfo, patchinfo,-                          showPatchInfoUI, makePatchname, invertName )+                          piName, displayPatchInfo, makePatchname, invertName ) import Darcs.Patch.Merge ( Merge(..) )-import Darcs.Patch.Patchy ( Commute(..), Invert(..), Apply(..),-                            PatchInspect(..), ReadPatch(..) )-import Darcs.Patch.Prim ( PrimOf, PrimPatchBase )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Invert ( Invert(..) )+import Darcs.Patch.Inspect ( PatchInspect(..) )+import Darcs.Patch.Read ( ReadPatch(..) )+import Darcs.Patch.Prim ( PrimPatchBase(..) ) import Darcs.Patch.ReadMonads ( ParserM, option, lexChar,                                 choice, skipWhile, anyChar ) import Darcs.Patch.Repair ( mapMaybeSnd, Repair(..), RepairToFL, Check(..) )-import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatch(..), showNamedPrefix )+import Darcs.Patch.Show+    ( ShowPatchBasic(..), ShowPatch(..), ShowContextPatch(..), ShowPatchFor(..) ) import Darcs.Patch.Summary ( plainSummary ) import Darcs.Patch.Viewing () -- for ShowPatch FL instances -import Darcs.Patch.Witnesses.Eq ( MyEq(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..) ) import Darcs.Patch.Witnesses.Ordered     ( (:>)(..), (:\/:)(..), (:/\:)(..), FL, mapFL, mapFL_FL ) import Darcs.Patch.Witnesses.Sealed ( Sealed, mapSeal ) import Darcs.Patch.Witnesses.Show ( ShowDict(..), Show1(..), Show2(..) ) -import Darcs.Util.Printer ( ($$), (<+>), (<>), prefix, text, vcat )+import Darcs.Util.Printer+    ( Doc, ($$), (<+>), (<>), prefix, text, vcat, cyanText, blueText )  -- | The @Named@ type adds a patch info about a patch, that is a name. data Named p wX wY where@@ -149,7 +151,7 @@ fmapFL_Named :: (FL p wA wB -> FL q wC wD) -> Named p wA wB -> Named q wC wD fmapFL_Named f (NamedP i deps p) = NamedP i deps (f p) -instance (Commute p, MyEq p) => MyEq (Named p) where+instance (Commute p, Eq2 p) => Eq2 (Named p) where     unsafeCompare (NamedP n1 d1 p1) (NamedP n2 d2 p2) =         n1 == n2 && d1 == d2 && unsafeCompare p1 p2 @@ -195,23 +197,73 @@ instance Check p => Check (Named p) where     isInconsistent (NamedP _ _ p) = isInconsistent p +-- ForStorage: note the difference between use of <> when there are+-- no explicit dependencies vs. <+> when there are+showNamedPrefix :: ShowPatchFor -> PatchInfo -> [PatchInfo] -> Doc -> Doc+showNamedPrefix f@ForStorage n [] p =+    showPatchInfo f n <> p+showNamedPrefix f@ForStorage n d p =+    showPatchInfo f n+    $$ blueText "<"+    $$ vcat (map (showPatchInfo f) d)+    $$ blueText ">"+    <+> p+showNamedPrefix f@ForDisplay n [] p =+    showPatchInfo f n+    $$ p+showNamedPrefix f@ForDisplay n d p =+    showPatchInfo f n+    $$ showDependencies ShowDepsVerbose d+    $$ p++data ShowDepsFormat = ShowDepsVerbose | ShowDepsSummary+                        deriving (Eq)++showDependencies :: ShowDepsFormat -> [PatchInfo] -> Doc+showDependencies format deps = vcat (map showDependency deps)+                    where+                      showDependency d = mark+                                         <+> cyanText "patch"+                                         <+> cyanText (show (makePatchname d))+                                         $$ asterisk <+> text (piName d)+                      mark | format == ShowDepsVerbose = blueText "depend"+                           | otherwise = text "D"+                      asterisk | format == ShowDepsVerbose = text "*"+                               | otherwise = text "  *"+ instance (PatchListFormat p, ShowPatchBasic p) => ShowPatchBasic (Named p) where-    showPatch (NamedP n [] p) = showPatchInfo n <> showPatch p-    showPatch (NamedP n d p) = showNamedPrefix n d <+> showPatch p+    showPatch f (NamedP n d p) = showNamedPrefix f n d $ showPatch f p -instance (Apply p, CommuteNoConflicts p, Conflict p, IsHunk p, PatchListFormat p,+instance (Apply p, IsHunk p, PatchListFormat p,+          ShowContextPatch p) => ShowContextPatch (Named p) where+    showContextPatch f (NamedP n d p) =+        showNamedPrefix f n d <$> showContextPatch f p++instance (CommuteNoConflicts p, Conflict p, PatchListFormat p,           PrimPatchBase p, ShowPatch p) => ShowPatch (Named p) where-    showContextPatch (NamedP n [] p) = showContextPatch p >>= return . (showPatchInfo n <>)-    showContextPatch (NamedP n d p) = showContextPatch p >>= return . (showNamedPrefix n d <+>)-    description (NamedP n _ _) = showPatchInfoUI n-    summary p = description p $$ text "" $$-                prefix "    " (plainSummary p) -- this isn't summary because summary does the-                                            -- wrong thing with (Named (FL p)) so that it can-                                            -- get the summary of a sequence of named patches-                                            -- right.+    description (NamedP n _ _) = displayPatchInfo n+    summary p@(NamedP _ ds _) =+        let+            indent = prefix "    "+            deps | ds == []  = text ""+                 | otherwise = text ""+                               $$ indent (showDependencies ShowDepsSummary ds)+        in+            description p $$ deps $$ indent (plainSummary p)+                                        -- this isn't summary because summary+                                        -- does the wrong thing with+                                        -- (Named (FL p)) so that it can get+                                        -- the summary of a sequence of named+                                        -- patches right.     summaryFL = vcat . mapFL summary-    showNicely p@(NamedP _ _ pt) = description p $$-                                   prefix "    " (showNicely pt)+    showNicely p@(NamedP _ ds pt) =+        let+            indent = prefix "    "+            deps | ds == []  = text ""+                 | otherwise = text ""+                               $$ indent (showDependencies ShowDepsVerbose ds)+        in+            description p <> deps $$ indent (showNicely pt)  instance Show2 p => Show1 (Named p wX) where     showDict1 = ShowDictClass
src/Darcs/Patch/Named/Wrapped.hs view
@@ -12,15 +12,16 @@  import Prelude () import Darcs.Prelude+import Data.Coerce ( coerce )  import Darcs.Patch.Apply ( Apply(..) ) import Darcs.Patch.Commute ( Commute(..) ) import Darcs.Patch.Conflict ( Conflict(..), CommuteNoConflicts(..) ) import Darcs.Patch.Effect ( Effect(..) ) import Darcs.Patch.FileHunk ( IsHunk(..) )-import Darcs.Patch.Format ( PatchListFormat(..), ListFormat, copyListFormat )+import Darcs.Patch.Format ( PatchListFormat(..), ListFormat ) import Darcs.Patch.Info-  ( PatchInfo, showPatchInfo, showPatchInfoUI, patchinfo+  ( PatchInfo, showPatchInfo, displayPatchInfo, patchinfo   ) import Darcs.Patch.Invert ( Invert(..) ) import Darcs.Patch.Named ( Named(..), fmapFL_Named )@@ -31,8 +32,8 @@   ) import Darcs.Patch.Inspect ( PatchInspect(..) ) import Darcs.Patch.Merge ( Merge(..) )-import Darcs.Patch.Prim ( FromPrim, PrimOf )-import Darcs.Patch.Prim.Class ( PrimPatchBase )+import Darcs.Patch.Prim ( FromPrim )+import Darcs.Patch.Prim.Class ( PrimPatchBase(..) ) import Darcs.Patch.Read ( ReadPatch(..) ) import qualified Darcs.Patch.Rebase.Container as Rebase   ( Suspended(..)@@ -43,7 +44,7 @@   ( RepoType(..), IsRepoType(..), SRepoType(..)   , RebaseType(..), RebaseTypeOf, SRebaseType(..)   )-import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatch(..) )+import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatch(..), ShowContextPatch(..), ShowPatchFor(..) )  import Darcs.Patch.Witnesses.Eq ( EqCheck(..) ) import Darcs.Patch.Witnesses.Sealed ( mapSeal )@@ -210,27 +211,35 @@ instance (ShowPatchBasic p, PatchListFormat p)   => ShowPatchBasic (WrappedNamed rt p) where -  showPatch (NormalP n) = showPatch n-  showPatch (RebaseP i s) = showPatchInfo i <> showPatch s+  showPatch f (NormalP n) = showPatch f n+  showPatch f (RebaseP i s) = showPatchInfo f i <> showPatch f s +instance ( ShowContextPatch p, PatchListFormat p, Apply p+         , PrimPatchBase p, IsHunk p+         )+  => ShowContextPatch (WrappedNamed rt p) where++  showContextPatch f (NormalP n) = showContextPatch f n+  showContextPatch f@ForDisplay (RebaseP i s) =+    fmap (showPatchInfo f i $$) $ return (showPatch f s)+  showContextPatch f@ForStorage (RebaseP i s) =+    fmap (showPatchInfo f i <>) $ return (showPatch f s)+ instance ( ShowPatch p, PatchListFormat p, Apply p          , PrimPatchBase p, IsHunk p, Conflict p, CommuteNoConflicts p          )   => ShowPatch (WrappedNamed rt p) where -  showContextPatch (NormalP n) = showContextPatch n-  showContextPatch (RebaseP i s) = fmap (showPatchInfo i <>) $ showContextPatch s-   description (NormalP n) = description n-  description (RebaseP i _) = showPatchInfoUI i+  description (RebaseP i _) = displayPatchInfo i    summary (NormalP n) = summary n-  summary (RebaseP i _) = showPatchInfoUI i+  summary (RebaseP i _) = displayPatchInfo i    summaryFL = vcat . mapFL summary    showNicely (NormalP n) = showNicely n-  showNicely (RebaseP i s) = showPatchInfoUI i $$+  showNicely (RebaseP i s) = displayPatchInfo i $$                              prefix "    " (showNicely s)  instance PatchInspect p => PatchInspect (WrappedNamed rt p) where@@ -277,7 +286,7 @@       _ -> fmap (mapSeal NormalP) readPatch'  instance PatchListFormat p => PatchListFormat (ReadRebasing p) where-  patchListFormat = copyListFormat (patchListFormat :: ListFormat p)+  patchListFormat = coerce (patchListFormat :: ListFormat p)  instance (ReadPatch p, PatchListFormat p, PrimPatchBase p) => ReadPatch (ReadRebasing p) where   readPatch' =
− src/Darcs/Patch/OldDate.hs
@@ -1,351 +0,0 @@--- Copyright (C) 2003 Peter Simons--- Copyright (C) 2003,2008 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.---- This module is intended to provide backwards-compatibility in the parsing--- of darcs patches.  In other words: don't change it, new features don't get--- added here.  The only user should be Darcs.Patch.Info.--module Darcs.Patch.OldDate ( readUTCDate, showIsoDateTime ) where--import Prelude ( (^) )-import Darcs.Prelude--import Text.ParserCombinators.Parsec-import System.Time-import Data.Char ( toUpper, isDigit )-import Control.Monad ( liftM, liftM2 )-import qualified Data.ByteString.Char8 as B-import Data.Maybe ( fromMaybe )---- | Read/interpret a date string, assuming UTC if timezone---   is not specified in the string-readUTCDate :: String -> CalendarTime-readUTCDate = readDate 0--readDate :: Int -> String -> CalendarTime-readDate tz d =-             case parseDate tz d of-             Left e -> error e-             Right ct -> ct--parseDate :: Int -> String -> Either String CalendarTime-parseDate tz d =-              if length d >= 14 && B.all isDigit bd-              then Right $-                   CalendarTime (readI $ B.take 4 bd)-                                (toEnum $ (+ (-1)) $ readI $ B.take 2 $ B.drop 4 bd)-                                (readI $ B.take 2 $ B.drop 6 bd) -- Day-                                (readI $ B.take 2 $ B.drop 8 bd) -- Hour-                                (readI $ B.take 2 $ B.drop 10 bd) -- Minute-                                (readI $ B.take 2 $ B.drop 12 bd) -- Second-                                0 Sunday 0 -- Picosecond, weekday and day of year unknown-                                "GMT" 0 False-              else let dt = do { x <- dateTime tz; eof; return x }-                   in case parse dt "" d of-                      Left e -> Left $ "bad date: "++d++" - "++show e-                      Right ct -> Right ct-  where bd = B.pack (take 14 d)-        readI s = fst $ fromMaybe (error "parseDate: invalid date") (B.readInt s)--showIsoDateTime :: CalendarTime -> String-showIsoDateTime ct = concat [ show $ ctYear ct-                            , twoDigit . show . (+1) . fromEnum $ ctMonth ct-                            , twoDigit . show $ ctDay ct-                            , twoDigit . show $ ctHour ct-                            , twoDigit . show $ ctMin ct-                            , twoDigit . show $ ctSec ct-                            ]-    where twoDigit []          = undefined-          twoDigit x@(_:[])    = '0' : x-          twoDigit x@(_:_:[])  = x-          twoDigit _           = undefined------- Parser Combinators ------------------------------------------------- |Case-insensitive variant of Parsec's 'char' function.--caseChar        :: Char -> GenParser Char a Char-caseChar c       = satisfy (\x -> toUpper x == toUpper c)---- |Case-insensitive variant of Parsec's 'string' function.--caseString      :: String -> GenParser Char a ()-caseString cs    = mapM_ caseChar cs <?> cs---- |Match a parser at least @n@ times.--manyN           :: Int -> GenParser a b c -> GenParser a b [c]-manyN n p-    | n <= 0     = return []-    | otherwise  = liftM2 (++) (count n p) (many p)---- |Match a parser at least @n@ times, but no more than @m@ times.--manyNtoM        :: Int -> Int -> GenParser a b c -> GenParser a b [c]-manyNtoM n m p-    | n < 0      = return []-    | n > m      = return []-    | n == m     = count n p-    | n == 0     = foldr ((<|>) . (\x -> try $ count x p)) (return []) $ reverse [1..m]-    | otherwise  = liftM2 (++) (count n p) (manyNtoM 0 (m-n) p)-------- Date/Time Parser -------------------------------------------------dateTime :: Int -> CharParser a CalendarTime-dateTime tz =-            choice [try $ cvsDateTime tz,-                    try $ iso8601DateTime tz,-                    oldDateTime]--dayAndHMSTime :: CharParser a (Int, Int, Int, Int)-dayAndHMSTime  = do d <- day-                    _ <- mySpaces-                    h <- hour-                    _ <- char ':'-                    m <- minute-                    _ <- char ':'-                    s <- second-                    return (d, h, m, s)--cvsDateTime :: Int -> CharParser a CalendarTime-cvsDateTime tz =-                do y <- year-                   _ <- char '/'-                   mon <- monthNum-                   _ <- char '/'-                   (d, h, m, s) <- dayAndHMSTime-                   z <- option tz $ mySpaces >> zone-                   return (CalendarTime y mon d h m s 0 Monday 0 "" z False)--oldDateTime   :: CharParser a CalendarTime-oldDateTime    =   do wd <- dayName-                      _ <- mySpaces-                      mon <- monthName-                      _ <- mySpaces-                      (d, h, m, s) <- dayAndHMSTime-                      _ <- mySpaces-                      z <- zone-                      _ <- mySpaces-                      y <- year-                      return (CalendarTime y mon d h m s 0 wd 0 "" z False)--{- FIXME: In case you ever want to use this outside of darcs, you should note-   that this implementation of ISO 8601 is not complete.--   reluctant to implement (ambiguous!):-     * years > 9999-     * truncated representations with implied century (89 for 1989)-   unimplemented:-     * repeated durations (not relevant)-     * lowest order component fractions in intervals-     * negative dates (BC)-   unverified or too relaxed:-     * the difference between 24h and 0h-     * allows stuff like 2005-1212; either you use the hyphen all the way-       (2005-12-12) or you don't use it at all (20051212), but you don't use-       it halfway, likewise with time-     * No bounds checking whatsoever on intervals!-       (next action: read iso doc to see if bounds-checking required?) -}-iso8601DateTime   :: Int -> CharParser a CalendarTime-iso8601DateTime localTz = try $-  do d <- iso8601Date-     t <- option id $ try $ do optional $ oneOf " T"-                               iso8601Time-     return $ t $ d { ctTZ = localTz }--iso8601Date :: CharParser a CalendarTime-iso8601Date =-  do d <- calendar_date <|> week_date <|> ordinal_date-     return $ foldr ($) nullCalendar d-  where-    calendar_date = -- yyyy-mm-dd-      try $ do d <- optchain year_ [ (dash, month_), (dash, day_) ]-               -- allow other variants to be parsed correctly-               notFollowedBy (digit <|> char 'W')-               return d-    week_date = --yyyy-Www-dd-      try $ do yfn <- year_-               optional dash-               _ <- char 'W'-               -- offset human 'week 1' -> computer 'week 0'-               w'  <- (\x -> x-1) `liftM` twoDigits-               wd  <- option 1 $ do { optional dash; nDigits 1 }-               let y = yfn nullCalendar-                   firstDay = ctWDay y-               -- things that make this complicated-               -- 1. iso8601 weeks start from Monday; Haskell weeks start from Sunday-               -- 2. the first week is the one that contains at least Thursday-               --    if the year starts after Thursday, then some days of the year-               --    will have already passed before the first week-               let afterThursday = firstDay == Sunday || firstDay > Thursday-                   w  = if afterThursday then w'+1 else w'-                   diff c = c { ctDay = (7 * w) + wd - fromEnum firstDay }-               return [toUTCTime.toClockTime.diff.yfn]-    ordinal_date = -- yyyy-ddd-      try $ optchain year_ [ (dash, yearDay_) ]-    ---    year_  = try $ do y <- fourDigits <?> "year (0000-9999)"-                      return $ \c -> c { ctYear = y }-    month_ = try $ do m <- twoDigits <?> "month (1 to 12)"-                      -- we (artificially) use ctPicosec to indicate-                      -- whether the month has been specified.-                      return $ \c -> c { ctMonth = intToMonth m, ctPicosec = 0 }-    day_   = try $ do d <- twoDigits <?> "day in month (1 to 31)"-                      return $ \c -> c { ctDay = d }-    yearDay_ = try $ do d <- nDigits 3 <?> "day in year (1 to 366)"-                        return $ \c -> c { ctYDay = d }-    dash = char '-'---- we return a function which sets the time on another calendar-iso8601Time :: CharParser a (CalendarTime -> CalendarTime)-iso8601Time = try $-  do ts <- optchain hour_ [ (colon     , min_)-                          , (colon     , sec_)-                          , (oneOf ",.", pico_) ]-     z  <- option id $ choice [ zulu , offset ]-     return $ foldr (.) id (z:ts)-  where-    hour_ = do h <- twoDigits-               return $ \c -> c { ctHour = h }-    min_  = do m <- twoDigits-               return $ \c -> c { ctMin = m }-    sec_  = do s <- twoDigits-               return $ \c -> c { ctSec = s }-    pico_ = do digs <- many digit-               let picoExp = 12-                   digsExp = length digs-               let frac | null digs = 0-                        | digsExp > picoExp = read $ take picoExp digs-                        | otherwise = 10 ^ (picoExp - digsExp) * read digs-               return $ \c -> c { ctPicosec = frac }-    zulu   = do { _ <- char 'Z'; return (\c -> c { ctTZ = 0 }) }-    offset = do sign <- choice [ char '+' >> return   1-                               , char '-' >> return (-1) ]-                h <- twoDigits-                m <- option 0 $ do { optional colon; twoDigits }-                return $ \c -> c { ctTZ = sign * 60 * ((h*60)+m) }-    colon = char ':'--optchain :: CharParser a b -> [(CharParser a c, CharParser a b)] -> CharParser a [b]-optchain p next = try $-  do r1 <- p-     r2 <- case next of-           [] -> return []-           ((sep,p2):next2) -> option [] $ do { optional sep; optchain p2 next2 }-     return (r1:r2)--nDigits :: Int -> CharParser a Int-nDigits n = read `liftM` count n digit--twoDigits, fourDigits :: CharParser a Int-twoDigits = nDigits 2-fourDigits = nDigits 4--mySpaces :: CharParser a String-mySpaces = manyN 1 $ char ' '--dayName        :: CharParser a Day-dayName         = choice-                       [ caseString "Mon"       >> return Monday-                       , try (caseString "Tue") >> return Tuesday-                       , caseString "Wed"       >> return Wednesday-                       , caseString "Thu"       >> return Thursday-                       , caseString "Fri"       >> return Friday-                       , try (caseString "Sat") >> return Saturday-                       , caseString "Sun"       >> return Sunday-                       ]--year            :: CharParser a Int-year             = fourDigits--monthNum       :: CharParser a Month-monthNum = do mn <- manyNtoM 1 2 digit-              return $ intToMonth (read mn :: Int)--intToMonth :: Int -> Month-intToMonth 1 = January-intToMonth 2 = February-intToMonth 3 = March-intToMonth 4 = April-intToMonth 5 = May-intToMonth 6 = June-intToMonth 7 = July-intToMonth 8 = August-intToMonth 9 = September-intToMonth 10 = October-intToMonth 11 = November-intToMonth 12 = December-intToMonth _  = error "invalid month!"--monthName      :: CharParser a Month-monthName       = choice-                       [ try (caseString "Jan") >> return January-                       , caseString "Feb"       >> return February-                       , try (caseString "Mar") >> return March-                       , try (caseString "Apr") >> return April-                       , caseString "May"       >> return May-                       , try (caseString "Jun") >> return June-                       , caseString "Jul"       >> return July-                       , caseString "Aug"       >> return August-                       , caseString "Sep"       >> return September-                       , caseString "Oct"       >> return October-                       , caseString "Nov"       >> return November-                       , caseString "Dec"       >> return December-                       ]--day             :: CharParser a Int-day              = do d <- manyNtoM 1 2 digit-                      return (read d :: Int)--hour            :: CharParser a Int-hour             = twoDigits--minute          :: CharParser a Int-minute           = twoDigits--second          :: CharParser a Int-second           = twoDigits--zone            :: CharParser a Int-zone             = choice-                       [ do { _ <- char '+'; h <- hour; m <- minute; return (((h*60)+m)*60) }-                       , do { _ <- char '-'; h <- hour; m <- minute; return (-((h*60)+m)*60) }-                       , mkZone "UTC"  0-                       , mkZone "UT"  0-                       , mkZone "GMT" 0-                       , mkZone "EST" (-5)-                       , mkZone "EDT" (-4)-                       , mkZone "CST" (-6)-                       , mkZone "CDT" (-5)-                       , mkZone "MST" (-7)-                       , mkZone "MDT" (-6)-                       , mkZone "PST" (-8)-                       , mkZone "PDT" (-7)-                       , mkZone "CEST" 2-                       , mkZone "EEST" 3-                         -- if we don't understand it, just give a GMT answer...-                       , do { _ <- manyTill (oneOf $ ['a'..'z']++['A'..'Z']++" ")-                                       (lookAhead space_digit);-                              return 0 }-                       ]-     where mkZone n o  = try $ do { caseString n; return (o*60*60) }-           space_digit = try $ do { _ <- char ' '; oneOf ['0'..'9'] }--nullCalendar :: CalendarTime-nullCalendar = CalendarTime 0 January 0 0 0 0 1 Sunday 0 "" 0 False
src/Darcs/Patch/PatchInfoAnd.hs view
@@ -15,9 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}-- module Darcs.Patch.PatchInfoAnd ( Hopefully(..), SimpleHopefully(..), PatchInfoAnd(..),                          WPatchInfo, unWPatchInfo, compareWPatchInfo,                          piap, n2pia, patchInfoAndPatch,@@ -34,8 +31,8 @@ import Darcs.Util.SignalHandler ( catchNonSignal ) import Darcs.Util.Printer     ( Doc, renderString, errorDoc, text, ($$), vcat-    , RenderMode(..) )-import Darcs.Patch.Info ( PatchInfo, showPatchInfoUI, justName )+     )+import Darcs.Patch.Info ( PatchInfo, showPatchInfo, displayPatchInfo, justName ) import Darcs.Patch.Conflict ( Conflict, CommuteNoConflicts ) import Darcs.Patch.Debug ( PatchDebug(..) ) import Darcs.Patch.Effect ( Effect(..) )@@ -47,12 +44,16 @@     , generaliseRepoTypeWrapped     ) import Darcs.Patch.Prim ( PrimPatchBase(..), FromPrim )-import Darcs.Patch.Patchy ( Patchy, ReadPatch(..), Apply(..), Invert(..),-                            ShowPatch(..), Commute(..), PatchInspect(..) )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Invert ( Invert(..) )+import Darcs.Patch.Inspect ( PatchInspect(..) )+import Darcs.Patch.Read ( ReadPatch(..) )+import Darcs.Patch.Show ( ShowPatch(..) ) import Darcs.Patch.Repair ( Repair(..), RepairToFL ) import Darcs.Patch.RepoType ( RepoType(..), IsRepoType, RebaseTypeOf, RebaseType(..) )-import Darcs.Patch.Show ( ShowPatchBasic(..) )-import Darcs.Patch.Witnesses.Eq ( MyEq(..), EqCheck(..) )+import Darcs.Patch.Show ( ShowPatchBasic(..), ShowContextPatch(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP ) import Darcs.Patch.Witnesses.Ordered ( (:>)(..), (:\/:)(..), (:/\:)(..), FL, mapFL ) import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed), seal, mapSeal )@@ -67,7 +68,9 @@ -- 'SimpleHopefully' does the real work of emulating -- 'Either'. @Hopefully sh@ represents an expected unhashed patch, and -- @Hashed hash sh@ represents an expected hashed patch with its hash.-data Hopefully a wX wY = Hopefully (SimpleHopefully a wX wY) | Hashed String (SimpleHopefully a wX wY)+data Hopefully a wX wY+    = Hopefully (SimpleHopefully a wX wY)+    | Hashed String (SimpleHopefully a wX wY)     deriving Show  -- | @SimpleHopefully@ is a variant of @Either String@ adapted for@@ -101,7 +104,7 @@ compareWPatchInfo :: WPatchInfo wA wB -> WPatchInfo wC wD -> EqCheck (wA, wB) (wC, wD) compareWPatchInfo (WPatchInfo x) (WPatchInfo y) = if x == y then unsafeCoerceP IsEq else NotEq -instance MyEq WPatchInfo where+instance Eq2 WPatchInfo where    WPatchInfo x `unsafeCompare` WPatchInfo y = x == y  fmapH :: (a wX wY -> b wW wZ) -> Hopefully a wX wY -> Hopefully b wW wZ@@ -160,15 +163,15 @@ conscientiously er (PIAP pinf hp) =     case hopefully2either hp of       Right p -> p-      Left e -> errorDoc $ er (showPatchInfoUI pinf $$ text e)+      Left e -> errorDoc $ er (displayPatchInfo pinf $$ text e)  -- | @hopefullyM@ is a version of @hopefully@ which calls @fail@ in a -- monad instead of erroring. hopefullyM :: Monad m => PatchInfoAnd rt p wA wB -> m (WrappedNamed rt p wA wB) hopefullyM (PIAP pinf hp) = case hopefully2either hp of                               Right p -> return p-                              Left e -> fail $ renderString Encode-                                                     (showPatchInfoUI pinf $$ text e)+                              Left e -> fail $ renderString+                                                     (displayPatchInfo pinf $$ text e)  -- Any recommendations for a nice adverb to name the below? hopefully2either :: Hopefully a wX wY -> Either String (a wX wY)@@ -197,7 +200,7 @@ -- Equality on PatchInfoAnd is solely determined by the PatchInfo -- It is a global invariant of darcs that once a patch is recorded, -- it should always have the same representation in the same context.-instance MyEq (PatchInfoAnd rt p) where+instance Eq2 (PatchInfoAnd rt p) where     unsafeCompare (PIAP i _) (PIAP i2 _) = i == i2  instance Invert p => Invert (PatchInfoAnd rt p) where@@ -206,23 +209,27 @@ instance PatchListFormat (PatchInfoAnd rt p)  instance (PatchListFormat p, ShowPatchBasic p) => ShowPatchBasic (PatchInfoAnd rt p) where-    showPatch (PIAP n p) = case hopefully2either p of-                           Right x -> showPatch x-                           Left _ -> showPatchInfoUI n+    showPatch f (PIAP n p) =+      case hopefully2either p of+        Right x -> showPatch f x+        Left _ -> showPatchInfo f n +instance (Apply p, IsHunk p, PatchListFormat p, PrimPatchBase p,+          ShowContextPatch p) => ShowContextPatch (PatchInfoAnd rt p) where+    showContextPatch f (PIAP n p) = case hopefully2either p of+                                      Right x -> showContextPatch f x+                                      Left _ -> return $ showPatchInfo f n+ instance (Apply p, Conflict p, CommuteNoConflicts p, IsHunk p, PatchListFormat p, PrimPatchBase p,           ShowPatch p, ApplyState p ~ Tree) => ShowPatch (PatchInfoAnd rt p) where-    showContextPatch (PIAP n p) = case hopefully2either p of-                                    Right x -> showContextPatch x-                                    Left _ -> return $ showPatchInfoUI n-    description (PIAP n _) = showPatchInfoUI n+    description (PIAP n _) = displayPatchInfo n     summary (PIAP n p) = case hopefully2either p of                          Right x -> summary x-                         Left _ -> showPatchInfoUI n+                         Left _ -> displayPatchInfo n     summaryFL = vcat . mapFL summary     showNicely (PIAP n p) = case hopefully2either p of                             Right x -> showNicely x-                            Left _ -> showPatchInfoUI n+                            Left _ -> displayPatchInfo n  instance Commute p => Commute (PatchInfoAnd rt p) where     commute (x :> y) = do y' :> x' <- commute (hopefully x :> hopefully y)@@ -260,6 +267,3 @@     isHunk _ = Nothing  instance PatchDebug p => PatchDebug (PatchInfoAnd rt p)--instance (Patchy p, ApplyState p ~ Tree) => Patchy (PatchInfoAnd rt p)-
− src/Darcs/Patch/Patchy.hs
@@ -1,36 +0,0 @@--- Copyright (C) 2007 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.--{-# LANGUAGE CPP #-}---module Darcs.Patch.Patchy-     ( Patchy,-       Apply(..), Commute(..), Invert(..),-       PatchInspect(..), ReadPatch(..),-       showPatch, ShowPatch(..)-     ) where--import Darcs.Patch.Apply ( Apply(..) )-import Darcs.Patch.Commute ( Commute(..) )-import Darcs.Patch.Invert ( Invert(..) )-import Darcs.Patch.Inspect ( PatchInspect(..) )-import Darcs.Patch.Read ( ReadPatch(..) )-import Darcs.Patch.Show ( showPatch, ShowPatch(..) )--class (Apply p, Commute p, Invert p) => Patchy p-
− src/Darcs/Patch/Patchy/Instances.hs
@@ -1,13 +0,0 @@-{-# OPTIONS_GHC -fno-warn-orphans #-}--module Darcs.Patch.Patchy.Instances () where--import Darcs.Patch.Format ( PatchListFormat )-import Darcs.Patch.Patchy ( Patchy )-import Darcs.Patch.Permutations ()-import Darcs.Patch.FileHunk ( IsHunk )-import Darcs.Patch.Viewing ()-import Darcs.Patch.Witnesses.Ordered ( FL, RL )--instance (IsHunk p, PatchListFormat p, Patchy p) => Patchy (FL p)-instance (IsHunk p, PatchListFormat p, Patchy p) => Patchy (RL p)
src/Darcs/Patch/Permutations.hs view
@@ -17,9 +17,7 @@ -- Boston, MA 02110-1301, USA.  {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE CPP #-} - module Darcs.Patch.Permutations ( removeFL, removeRL, removeCommon,                                   commuteWhatWeCanFL, commuteWhatWeCanRL,                                   genCommuteWhatWeCanRL, genCommuteWhatWeCanFL,@@ -38,12 +36,11 @@ import Darcs.Patch.Commute ( Commute, commute, commuteFLorComplain, commuteRL ) import Darcs.Patch.CommuteFn ( CommuteFn ) import Darcs.Patch.Invert ( Invert(..) )-import Darcs.Patch.Witnesses.Eq ( MyEq(..), EqCheck(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) ) import Darcs.Patch.Witnesses.Ordered     ( FL(..), RL(..), (:>)(..), (+<+)     , reverseFL, (+>+), (:\/:)(..), lengthFL     , lengthRL, reverseRL )-#include "impossible.h"  -- |split an 'FL' into "left" and "right" lists according to a predicate @p@, using commutation as necessary. -- If a patch does satisfy the predicate but cannot be commuted past one that does not satisfy@@ -134,11 +131,11 @@ genCommuteWhatWeCanRL _ (NilRL :> y) = NilRL :> y :> NilRL  -removeCommon :: (MyEq p, Commute p) => (FL p :\/: FL p) wX wY -> (FL p :\/: FL p) wX wY+removeCommon :: (Eq2 p, Commute p) => (FL p :\/: FL p) wX wY -> (FL p :\/: FL p) wX wY removeCommon (xs :\/: NilFL) = xs :\/: NilFL removeCommon (NilFL :\/: xs) = NilFL :\/: xs removeCommon (xs :\/: ys) = rc xs (headPermutationsFL ys)-    where rc :: (MyEq p, Commute p) => FL p wX wY -> [(p:>FL p) wX wZ] -> (FL p :\/: FL p) wY wZ+    where rc :: (Eq2 p, Commute p) => FL p wX wY -> [(p:>FL p) wX wZ] -> (FL p :\/: FL p) wY wZ           rc nms ((n:>ns):_) | Just ms <- removeFL n nms = removeCommon (ms :\/: ns)           rc ms [n:>ns] = ms :\/: n:>:ns           rc ms (_:nss) = rc ms nss@@ -146,17 +143,17 @@  -- | 'removeFL' @x xs@ removes @x@ from @xs@ if @x@ can be commuted to its head. --   Otherwise it returns 'Nothing'-removeFL :: (MyEq p, Commute p) => p wX wY -> FL p wX wZ -> Maybe (FL p wY wZ)+removeFL :: (Eq2 p, Commute p) => p wX wY -> FL p wX wZ -> Maybe (FL p wY wZ) removeFL x xs = r x $ headPermutationsFL xs-    where r :: (MyEq p, Commute p) => p wX wY -> [(p:>FL p) wX wZ] -> Maybe (FL p wY wZ)+    where r :: (Eq2 p, Commute p) => p wX wY -> [(p:>FL p) wX wZ] -> Maybe (FL p wY wZ)           r _ [] = Nothing           r z ((z':>zs):zss) | IsEq <- z =\/= z' = Just zs                              | otherwise = r z zss  -- | 'removeRL' is like 'removeFL' except with 'RL'-removeRL :: (MyEq p, Commute p) => p wY wZ -> RL p wX wZ -> Maybe (RL p wX wY)+removeRL :: (Eq2 p, Commute p) => p wY wZ -> RL p wX wZ -> Maybe (RL p wX wY) removeRL x xs = r x $ headPermutationsRL xs-    where r :: (MyEq p, Commute p) => p wY wZ -> [RL p wX wZ] -> Maybe (RL p wX wY)+    where r :: (Eq2 p, Commute p) => p wY wZ -> [RL p wX wZ] -> Maybe (RL p wX wY)           r z ((zs:<:z'):zss) | IsEq <- z =/\= z' = Just zs                               | otherwise = r z zss           r _ _ = Nothing@@ -165,21 +162,21 @@ --   @ab@ have been commuted out of it, if possible.  If this is not possible --   for any reason (the set of patches @ab@ is not actually a subset of @abc@, --   or they can't be commuted out) we return 'Nothing'.-removeSubsequenceFL :: (MyEq p, Commute p) => FL p wA wB+removeSubsequenceFL :: (Eq2 p, Commute p) => FL p wA wB                      -> FL p wA wC -> Maybe (FL p wB wC) removeSubsequenceFL a b | lengthFL a > lengthFL b = Nothing                          | otherwise = rsFL a b-    where rsFL :: (MyEq p, Commute p) => FL p wA wB -> FL p wA wC -> Maybe (FL p wB wC)+    where rsFL :: (Eq2 p, Commute p) => FL p wA wB -> FL p wA wC -> Maybe (FL p wB wC)           rsFL NilFL ys = Just ys           rsFL (x:>:xs) yys = removeFL x yys >>= removeSubsequenceFL xs  -- | 'removeSubsequenceRL' is like @removeSubsequenceFL@ except that it works --   on 'RL'-removeSubsequenceRL :: (MyEq p, Commute p) => RL p wAb wAbc+removeSubsequenceRL :: (Eq2 p, Commute p) => RL p wAb wAbc                      -> RL p wA wAbc -> Maybe (RL p wA wAb) removeSubsequenceRL a b | lengthRL a > lengthRL b = Nothing                          | otherwise = rsRL a b-    where rsRL :: (MyEq p, Commute p) => RL p wAb wAbc -> RL p wA wAbc -> Maybe (RL p wA wAb)+    where rsRL :: (Eq2 p, Commute p) => RL p wAb wAbc -> RL p wA wAbc -> Maybe (RL p wA wAb)           rsRL NilRL ys = Just ys           rsRL (xs:<:x) yys = removeRL x yys >>= removeSubsequenceRL xs @@ -222,7 +219,7 @@                                               Just $ xs:<:p1':<:p2'               swapfirstRL _ = Nothing -instance (MyEq p, Commute p) => MyEq (FL p) where+instance (Eq2 p, Commute p) => Eq2 (FL p) where     a =\/= b | lengthFL a /= lengthFL b = NotEq              | otherwise = cmpSameLength a b              where cmpSameLength :: FL p wX wY -> FL p wX wZ -> EqCheck wY wZ@@ -231,7 +228,7 @@                    cmpSameLength _ _ = NotEq     xs =/\= ys = reverseFL xs =/\= reverseFL ys -instance (MyEq p, Commute p) => MyEq (RL p) where+instance (Eq2 p, Commute p) => Eq2 (RL p) where     unsafeCompare = bug "Buggy use of unsafeCompare on RL"     a =/\= b | lengthRL a /= lengthRL b = NotEq              | otherwise = cmpSameLength a b
src/Darcs/Patch/Prim.hs view
@@ -1,25 +1,24 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module Darcs.Patch.Prim-       ( showPrim, showPrimFL,-         primIsAddfile, primIsHunk, primIsBinary, primIsSetpref,-         primIsAdddir, is_filepatch,-         canonize, tryToShrink,-         sortCoalesceFL, coalesce, canonizeFL,-         tryShrinkingInverse,-         summarizePrim,-         applyPrimFL,-         readPrim,-         FromPrim(..), FromPrims(..), ToFromPrim(..),-         PrimPatch, PrimPatchBase(..), PrimConstruct(..)-       )-       where+    ( primIsAddfile, primIsHunk, primIsBinary, primIsSetpref+    , primIsAdddir, is_filepatch+    , summarizePrim+    , applyPrimFL+    , PrimRead(..)+    , PrimShow(..)+    , FromPrim(..), FromPrims(..), ToFromPrim(..)+    , PrimPatch, PrimPatchBase(..)+    , PrimConstruct(..)+    , PrimCanonize(..)+    , PrimPatchCommon+    ) where  import Darcs.Patch.Prim.Class     ( PrimConstruct(..), PrimCanonize(..)     , PrimClassify(..), PrimDetails(..)-    , PrimShow(..), showPrimFL, PrimRead(..)+    , PrimShow(..), PrimRead(..)     , PrimApply(..)     , FromPrim(..), FromPrims(..), ToFromPrim(..)     , PrimPatchBase(..), PrimPatch+    , PrimPatchCommon     )-
src/Darcs/Patch/Prim/Class.hs view
@@ -1,10 +1,11 @@ module Darcs.Patch.Prim.Class     ( PrimConstruct(..), PrimCanonize(..)     , PrimClassify(..), PrimDetails(..)-    , PrimShow(..), showPrimFL, PrimRead(..)+    , PrimShow(..), PrimRead(..)     , PrimApply(..)     , PrimPatch, PrimPatchBase(..)     , FromPrim(..), FromPrims(..), ToFromPrim(..)+    , PrimPatchCommon     )     where @@ -15,34 +16,52 @@ import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.FileHunk ( FileHunk, IsHunk ) import Darcs.Util.Path ( FileName )-import Darcs.Patch.Format ( PatchListFormat, FileNameFormat(..) )+import Darcs.Patch.Format ( FileNameFormat, PatchListFormat ) import Darcs.Patch.Inspect ( PatchInspect )-import Darcs.Patch.Patchy ( Patchy )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Invert ( Invert(..) ) import Darcs.Patch.Read ( ReadPatch ) import Darcs.Patch.ReadMonads ( ParserM ) import Darcs.Patch.Repair ( RepairToFL )-import Darcs.Patch.Show ( ShowPatch )+import Darcs.Patch.Show ( ShowPatch, ShowContextPatch ) import Darcs.Patch.SummaryData ( SummDetail )-import Darcs.Patch.Witnesses.Eq ( MyEq(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..) ) import Darcs.Patch.Witnesses.Ordered-    ( FL(..), RL, (:>), mapFL, mapFL_FL, reverseFL )+    ( FL(..), RL, (:>), mapFL_FL, reverseFL ) import Darcs.Patch.Witnesses.Show ( Show2 ) import Darcs.Patch.Witnesses.Sealed ( Sealed ) -import Darcs.Util.Printer ( Doc, vcat )+import Darcs.Util.Printer ( Doc ) import qualified Darcs.Util.Diff as D ( DiffAlgorithm )  import qualified Data.ByteString as B ( ByteString )  -class (Patchy prim, MyEq prim-      ,PatchListFormat prim, IsHunk prim, RepairToFL prim-      ,PatchInspect prim, ReadPatch prim, ShowPatch prim-      ,Show2 prim-      ,PrimConstruct prim, PrimCanonize prim-      ,PrimClassify prim, PrimDetails prim-      ,PrimShow prim, PrimRead prim, PrimApply prim+-- | This class describes the abstract interface to primitive patches+-- that is indepenent of the on-disk format.+class ( Apply prim+      , Commute prim+      , Invert prim+      , Eq2 prim+      , IsHunk prim+      , PatchInspect prim+      , RepairToFL prim+      , Show2 prim+      , PrimConstruct prim+      , PrimCanonize prim+      , PrimClassify prim+      , PrimDetails prim+      , PrimApply prim       )+    => PrimPatchCommon prim++class ( PrimPatchCommon prim+      , ReadPatch prim+      , ShowPatch prim+      , ShowContextPatch prim+      , PatchListFormat prim+      )     => PrimPatch prim  class PrimPatch (PrimOf p) => PrimPatchBase p where@@ -55,7 +74,7 @@     type PrimOf (RL p) = PrimOf p  class FromPrim p where-   fromPrim :: PrimOf p wX wY -> p wX wY+    fromPrim :: PrimOf p wX wY -> p wX wY  class FromPrim p => ToFromPrim p where     toPrim :: p wX wY -> Maybe (PrimOf p wX wY)@@ -143,9 +162,7 @@  class PrimShow prim where    showPrim :: FileNameFormat -> prim wA wB -> Doc--showPrimFL :: PrimShow prim => FileNameFormat -> FL prim wA wB -> Doc-showPrimFL f xs = vcat (mapFL (showPrim f) xs)+   showPrimCtx :: ApplyMonad  (ApplyState prim) m => FileNameFormat -> prim wA wB -> m Doc  class PrimRead prim where    readPrim :: ParserM m => FileNameFormat -> m (Sealed (prim wX))
src/Darcs/Patch/Prim/FileUUID.hs view
@@ -1,9 +1,6 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module Darcs.Patch.Prim.FileUUID ( Prim ) where -import Prelude ()-import Darcs.Prelude- import Darcs.Patch.Prim.FileUUID.Apply () import Darcs.Patch.Prim.FileUUID.Coalesce () import Darcs.Patch.Prim.FileUUID.Commute ()@@ -12,11 +9,10 @@ import Darcs.Patch.Prim.FileUUID.Read () import Darcs.Patch.Prim.FileUUID.Show () -import Darcs.Patch.Prim.Class ( PrimPatch, PrimPatchBase(..), FromPrim(..) )-import Darcs.Patch.Patchy ( Patchy )+import Darcs.Patch.Prim.Class ( PrimPatchCommon, PrimPatch, PrimPatchBase(..), FromPrim(..) ) +instance PrimPatchCommon Prim instance PrimPatch Prim-instance Patchy Prim  instance PrimPatchBase Prim where   type PrimOf Prim = Prim
src/Darcs/Patch/Prim/FileUUID/Apply.hs view
@@ -1,81 +1,98 @@-{-# LANGUAGE CPP, MultiParamTypeClasses, OverloadedStrings #-}+{-# LANGUAGE MultiParamTypeClasses, OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-orphans -fno-warn-missing-methods #-}-module Darcs.Patch.Prim.FileUUID.Apply ( ObjectMap(..) ) where+module Darcs.Patch.Prim.FileUUID.Apply ( hunkEdit, ObjectMap(..) ) where  import Prelude () import Darcs.Prelude -import Darcs.Patch.Apply ( Apply(..) )-import Darcs.Patch.ApplyMonad-  ( ApplyMonad(..), ApplyMonadTrans(..), ToTree(..), ApplyMonadState(..)-  )-import Darcs.Patch.Repair ( RepairToFL(..) )--import Darcs.Patch.Prim.Class ( PrimApply(..) )-import Darcs.Patch.Prim.FileUUID.Core ( Prim(..), hunkEdit )-import Darcs.Patch.Prim.FileUUID.ObjectMap- import Control.Monad.State( StateT, runStateT, gets, lift, put )+import qualified Data.ByteString as B import qualified Data.Map as M --- import Darcs.Patch.ApplyMonad ( ApplyMonad(..) )+import Debug.Trace ( trace )+-- import Text.Show.Pretty ( ppShow ) +import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.ApplyMonad+    ( ApplyMonad(..), ApplyMonadTrans(..)+    , ToTree(..), ApplyMonadState(..)+    )+import Darcs.Patch.Prim.Class ( PrimApply(..) )+import Darcs.Patch.Prim.FileUUID.Core ( Prim(..), Hunk(..), HunkMove(..) )+import Darcs.Patch.Prim.FileUUID.Show+import Darcs.Patch.Prim.FileUUID.ObjectMap+import Darcs.Patch.Repair ( RepairToFL(..) ) import Darcs.Patch.Witnesses.Ordered ( FL(..) )+ import Darcs.Util.Hash( Hash(..) )+import Darcs.Util.Printer( text, packedString, ($$), renderString ) -import qualified Data.ByteString      as B -#include "impossible.h"- instance Apply Prim where-    type ApplyState Prim = ObjectMap-    apply (Manifest i (dirid, name)) = editDirectory dirid (M.insert name i)-    apply (Demanifest _ (dirid, name)) = editDirectory dirid (M.delete name)-    apply (TextHunk i hunk) = editFile i (hunkEdit hunk)-    apply (BinaryHunk i hunk) = editFile i (hunkEdit hunk)-    apply Identity = return ()-    apply (Move{}) = bug "apply for move not implemented"+  type ApplyState Prim = ObjectMap+  apply (Manifest i (L dirid name)) = editDirectory dirid (M.insert name i)+  apply (Demanifest _ (L dirid name)) = editDirectory dirid (M.delete name)+  apply (Hunk i hunk) = editFile i (hunkEdit hunk)+  apply (HunkMove (HM fs ls ft lt c)) =+    editFile fs (hunkEdit (H ls c B.empty)) >> editFile ft (hunkEdit (H lt B.empty c))+  apply Identity = return ()  instance RepairToFL Prim where-    applyAndTryToFixFL p = apply p >> return Nothing+  applyAndTryToFixFL p = apply p >> return Nothing  instance PrimApply Prim where-    applyPrimFL NilFL = return ()-    applyPrimFL (p:>:ps) = apply p >> applyPrimFL ps+  applyPrimFL NilFL = return ()+  applyPrimFL (p :>: ps) = apply p >> applyPrimFL ps  instance ToTree ObjectMap -- TODO -editObject :: (Monad m) => UUID -> (Maybe (Object m) -> Object m) -> (StateT (ObjectMap m) m) ()-editObject i edit = do load <- gets getObject-                       store <- gets putObject-                       obj <- lift $ load i-                       new <- lift $ store i $ edit obj-                       put new-                       return ()+hunkEdit :: Hunk wX wY -> FileContent -> FileContent+hunkEdit h@(H off old new) c+  | old `B.isPrefixOf` (B.drop off c) =+      B.concat [B.take off c, new, B.drop (off + B.length old) c]+  | otherwise = error $ renderString $+      text "##error applying hunk:" $$ displayHunk Nothing h $$ "##to" $$+      packedString c+--       $$ text "##old=" <> text (ppShow old) $$+--       text "##new=" <> text (ppShow new) $$+--       text "##c=" <> text (ppShow c) +editObject :: Monad m+           => UUID+           -> (Maybe (Object m) -> Object m)+           -> (StateT (ObjectMap m) m) ()+editObject i edit = do+  load <- gets getObject+  store <- gets putObject+  obj <- lift $ load i+  new <- lift $ store i $ edit obj+  put new +-- a semantic, ObjectMap-based interface for patch application class ApplyMonadObjectMap m where-    -- a semantic, ObjectMap-based interface for patch application-    editFile :: UUID -> (B.ByteString -> B.ByteString) -> m ()-    editDirectory :: UUID -> (DirContent -> DirContent) -> m ()+  editFile :: UUID -> (FileContent -> FileContent) -> m ()+  editDirectory :: UUID -> (DirContent -> DirContent) -> m ()  instance ApplyMonadState ObjectMap where-    type ApplyMonadStateOperations ObjectMap = ApplyMonadObjectMap+  type ApplyMonadStateOperations ObjectMap = ApplyMonadObjectMap -instance (Functor m, Monad m) => ApplyMonad ObjectMap (StateT (ObjectMap m) m) where-    type ApplyMonadBase (StateT (ObjectMap m) m) = m+instance (Monad m) => ApplyMonad ObjectMap (StateT (ObjectMap m) m) where+  type ApplyMonadBase (StateT (ObjectMap m) m) = m -instance (Functor m, Monad m) => ApplyMonadObjectMap (StateT (ObjectMap m) m) where-    editFile i edit = editObject i edit'-      where edit' (Just (Blob x _)) = Blob (edit `fmap` x) NoHash-            edit' (Just (Directory x)) = Directory x -- error?-            edit' Nothing = Blob (return $ edit "") NoHash-    editDirectory i edit = editObject i edit'-      where edit' (Just (Directory x)) = Directory $ edit x-            edit' (Just (Blob x y)) = Blob x y -- error?-            edit' Nothing = Directory $ edit M.empty+instance (Monad m) => ApplyMonadObjectMap (StateT (ObjectMap m) m) where+  editFile i edit = editObject i edit'+    where+      edit' (Just (Blob x _)) = Blob (edit `fmap` x) NoHash+      edit' Nothing = Blob (return $ edit "") NoHash+      edit' (Just d@(Directory m)) =+        trace ("\neditFile called with Directory object: " ++ show (i,m) ++ "\n") d+  editDirectory i edit = editObject i edit'+    where+      edit' (Just (Directory x)) = Directory $ edit x+      edit' Nothing = Directory $ edit M.empty+      edit' (Just b@(Blob _ h)) =+        trace ("\neditDirectory called with File object: " ++ show (i,h) ++ "\n") b -instance (Functor m, Monad m) => ApplyMonadTrans ObjectMap m where+instance (Monad m) => ApplyMonadTrans ObjectMap m where   type ApplyMonadOver ObjectMap m = StateT (ObjectMap m) m   runApplyMonad = runStateT-
src/Darcs/Patch/Prim/FileUUID/Commute.hs view
@@ -1,73 +1,62 @@-{-# OPTIONS_GHC -fno-warn-orphans -fno-warn-overlapping-patterns #-}-{-# LANGUAGE CPP #-}-module Darcs.Patch.Prim.FileUUID.Commute-    ( CommuteMonad(..) )-    where+{-# OPTIONS_GHC -fno-warn-orphans #-}+module Darcs.Patch.Prim.FileUUID.Commute () where  import Prelude () import Darcs.Prelude -import Data.List ( intersect )--import qualified Data.ByteString as BS (length)+import qualified Data.ByteString as B (length)  import Darcs.Patch.Witnesses.Ordered ( (:>)(..) ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )-import Darcs.Patch.Prim.FileUUID.Core ( Prim(..), Hunk(..), touches )+import Darcs.Patch.Prim.FileUUID.Core ( Prim(..), Hunk(..) ) import Darcs.Patch.Commute ( Commute(..) ) import Darcs.Patch.Permutations () -- for Invert instance of FL -#include "impossible.h" -class Monad m => CommuteMonad m where-  commuteFail :: m a-  -- TODO we eventually have to get rid of runCommute with this signature,-  -- since m might involve IO at some point, which we can't "run";-  -- alternatively, for IO it could always yield Nothing, having a separate-  -- IO-specific function to "run" commutes in IO--instance CommuteMonad Maybe where-  commuteFail = Nothing+-- For FileUUID it is easier to list the cases that do /not/ commute+depends :: (Prim :> Prim) wX wY -> Bool+depends (Manifest i1 l1 :> Demanifest i2 l2)+  -- cannot commute add with remove of same object, regardless of location+  | i1 == i2 = True+  -- cannot commute add with remove of any two things at the same location+  | l1 == l2 = True+depends (Demanifest i1 l1 :> Manifest i2 l2)+  -- cannot commute remove with add of same object, regardless of location+  | i1 == i2 = True+  -- cannot commute remove with add of any two things at the same location+  | l1 == l2 = True+depends (_ :> _) = False  instance Commute Prim where-    commute = commute'--class Commute' p where-  commute' :: (CommuteMonad m) => (p :> p) wX wY -> m ((p :> p) wX wY)--typematch :: Prim wX wY -> Prim wY wZ -> Bool-typematch _ _ = True -- TODO--instance Commute' Prim where-  commute' (a :> b) | null (touches a `intersect` touches b) = return (unsafeCoerceP b :> unsafeCoerceP a)-                    | not (a `typematch` b) = commuteFail-                    | otherwise = commuteOverlapping (a :> b)---- Commute patches that have actual overlap in terms of touched objects, and their types allow-commuteOverlapping :: (CommuteMonad m) => (Prim :> Prim) wX wY -> m ((Prim :> Prim) wX wY)-commuteOverlapping (BinaryHunk a x :> BinaryHunk _ y) =-  do (y' :> x') <- commuteHunk (x :> y)-     return $ unsafeCoerceP (BinaryHunk a y' :> BinaryHunk a x')-commuteOverlapping (TextHunk a x :> TextHunk _ y) =-  do (y' :> x') <- commuteHunk (x :> y)-     return $ unsafeCoerceP (TextHunk a y' :> TextHunk a x')-commuteOverlapping _ = commuteFail+  commute pair+    | depends pair = Nothing+  commute (Hunk f1 h1 :> Hunk f2 h2)+    | f1 == f2 =+        case commuteHunk (h1 :> h2) of+          Just (h2' :> h1') -> Just (Hunk f2 h2' :> Hunk f1 h1')+          Nothing -> Nothing+  commute (a :> b) =+    Just (unsafeCoerceP b :> unsafeCoerceP a) -commuteHunk :: (CommuteMonad m) => (Hunk :> Hunk) wX wY -> m ((Hunk :> Hunk) wY wX)-commuteHunk (Hunk off1 old1 new1 :> Hunk off2 old2 new2)-  | off1 + lengthnew1 < off2 =-    return $ Hunk (off2 - lengthnew1 + lengthold1) old2 new2 :> Hunk off1 old1 new1-  | off2 + lengthold2 < off1 =-    return $ Hunk off2 old2 new2 :> Hunk (off1 + lengthnew2 - lengthold2) old1 new1-  | off1 + lengthnew1 == off2 &&-    lengthold2 /= 0 && lengthold1 /= 0 && lengthnew2 /= 0 && lengthnew1 /= 0 =-      return $ Hunk (off2 - lengthnew1 + lengthold1) old2 new2 :> Hunk off1 old1 new1-  | off2 + lengthold2 == off1 &&-    lengthold2 /= 0 && lengthold1 /= 0 && lengthnew2 /= 0 && lengthnew1 /= 0 =-      return $ Hunk off2 old2 new2 :> Hunk (off1 + lengthnew2 - lengthold2) old1 new1-  | otherwise = commuteFail-  where lengthnew1 = BS.length new1-        lengthnew2 = BS.length new2-        lengthold1 = BS.length old1-        lengthold2 = BS.length old2-commuteHunk _ = impossible+commuteHunk :: (Hunk :> Hunk) wX wY -> Maybe ((Hunk :> Hunk) wX wY)+commuteHunk (H off1 old1 new1 :> H off2 old2 new2)+  | off1 + len_new1 < off2  = yes (off2 - len_new1 + len_old1, off1)+  | off2 + len_old2 < off1  = yes (off2, off1 + len_new2 - len_old2)+  | len_old2 /= 0+  , len_old1 /= 0+  , len_new2 /= 0+  , len_new1 /= 0+  , off1 + len_new1 == off2 = yes (off2 - len_new1 + len_old1, off1)+  | len_old2 /= 0+  , len_old1 /= 0+  , len_new2 /= 0+  , len_new1 /= 0+  , off2 + len_old2 == off1 = yes (off2, off1 + len_new2 - len_old2)+  | otherwise               = no+  where+    len_old1 = B.length old1+    len_new1 = B.length new1+    len_old2 = B.length old2+    len_new2 = B.length new2+    yes (off2', off1') = Just (H off2' old2 new2 :> H off1' old1 new1)+    no = Nothing
src/Darcs/Patch/Prim/FileUUID/Core.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, OverloadedStrings, StandaloneDeriving #-}+{-# LANGUAGE OverloadedStrings, StandaloneDeriving #-}  -- Copyright (C) 2011 Petr Rockai --@@ -24,128 +24,127 @@   module Darcs.Patch.Prim.FileUUID.Core-       ( Prim(..), Hunk(..), UUID(..), Location, Object(..), touches, hunkEdit )-       where+    ( Prim(..)+    , Hunk(..)+    , HunkMove(..)+    -- re-exports+    , Object(..)+    , UUID(..)+    , Location(..)+    , Name+    , FileContent+    ) where  import Prelude () import Darcs.Prelude -import qualified Data.ByteString as BS--import Darcs.Patch.Witnesses.Eq ( MyEq(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..) ) import Darcs.Patch.Witnesses.Show ( Show1(..), Show2(..), ShowDict(ShowDictClass) )+import Darcs.Patch.Witnesses.Unsafe import Darcs.Patch.FileHunk( IsHunk(..) ) import Darcs.Patch.Invert ( Invert(..) ) import Darcs.Patch.Inspect ( PatchInspect(..) ) import Darcs.Patch.Prim.Class ( PrimConstruct(..), PrimClassify(..) ) import Darcs.Patch.Prim.FileUUID.ObjectMap --- TODO: elaborate+-- -----------------------------------------------------------------------------+-- Hunk -data Hunk wX wY where-  Hunk :: !Int -> BS.ByteString -> BS.ByteString -> Hunk wX wY-    deriving Show+data Hunk wX wY = H !Int !FileContent !FileContent+  deriving (Eq, Show)  instance Show1 (Hunk wX) where-    showDict1 = ShowDictClass+  showDict1 = ShowDictClass  instance Show2 Hunk where-    showDict2 = ShowDictClass+  showDict2 = ShowDictClass  invertHunk :: Hunk wX wY -> Hunk wY wX-invertHunk (Hunk off old new) = Hunk off new old+invertHunk (H off old new) = H off new old -hunkEdit :: Hunk wX wY -> BS.ByteString -> BS.ByteString-hunkEdit (Hunk off old new) bs = case splice bs (off) (off + BS.length old) of-  x | x == old -> BS.concat [ BS.take off bs, new, BS.drop (off + BS.length old) bs ]-    | otherwise -> error $ "error applying hunk: " ++ show off ++ " " ++ show old ++ " "-                        ++ show new ++ " to " ++ show bs-  where splice bs' x y = BS.drop x $ BS.take y bs'+instance Eq2 Hunk where+  unsafeCompare p q = unsafeCoerceP p == q -instance MyEq Hunk where-  unsafeCompare (Hunk i x y) (Hunk i' x' y') = i == i' && x == x' && y == y'+-- -----------------------------------------------------------------------------+-- HunkMove -data Prim wX wY where-    BinaryHunk :: !UUID -> Hunk wX wY -> Prim wX wY-    TextHunk :: !UUID -> Hunk wX wY -> Prim wX wY+data HunkMove wX wY = HM !UUID !Int !UUID !Int !FileContent+  deriving (Eq, Show) -    -- TODO: String is not the right type here. However, what it represents is-    -- a single file *name* (not a path). No slashes allowed, no "." and ".."-    -- allowed either.-    Manifest :: !UUID -> Location -> Prim wX wY-    Demanifest :: !UUID -> Location -> Prim wX wY-    Move :: !UUID -> Location -> Location -> Prim wX wY-    Identity :: Prim wX wX+invertHunkMove :: HunkMove wX wY -> HunkMove wY wX+invertHunkMove (HM sid soff tid toff content) = HM tid toff sid soff content +instance Eq2 HunkMove where+  unsafeCompare (HM sid1 soff1 tid1 toff1 c1) (HM sid2 soff2 tid2 toff2 c2) =+    sid1 == sid2 && soff1 == soff2 && tid1 == tid2 && toff1 == toff2 && c1 == c2++-- -----------------------------------------------------------------------------+-- Prim++data Prim wX wY where+  Hunk :: !UUID -> !(Hunk wX wY) -> Prim wX wY+  HunkMove :: !(HunkMove wX wY) -> Prim wX wY+  Manifest :: !UUID -> !Location -> Prim wX wY+  Demanifest :: !UUID -> !Location -> Prim wX wY+  Identity :: Prim wX wX++deriving instance Eq (Prim wX wY) deriving instance Show (Prim wX wY)  instance Show1 (Prim wX) where-    showDict1 = ShowDictClass+  showDict1 = ShowDictClass  instance Show2 Prim where-    showDict2 = ShowDictClass--touches :: Prim wX wY -> [UUID]-touches (BinaryHunk x _) = [x]-touches (TextHunk x _) = [x]-touches (Manifest _ (x, _)) = [x]-touches (Demanifest _ (x, _)) = [x]-touches (Move _ (x, _) (y, _)) = [x, y]-touches Identity = []+  showDict2 = ShowDictClass  -- TODO: PrimClassify doesn't make sense for FileUUID prims instance PrimClassify Prim where-   primIsAddfile _ = False-   primIsRmfile _ = False-   primIsAdddir _ = False-   primIsRmdir _ = False-   primIsHunk _ = False-   primIsMove _ = False-   primIsBinary _ = False-   primIsTokReplace _ = False-   primIsSetpref _ = False-   is_filepatch _ = Nothing+  primIsAddfile _ = False+  primIsRmfile _ = False+  primIsAdddir _ = False+  primIsRmdir _ = False+  primIsHunk _ = False+  primIsMove _ = False+  primIsBinary _ = False+  primIsTokReplace _ = False+  primIsSetpref _ = False+  is_filepatch _ = Nothing  -- TODO: PrimConstruct makes no sense for FileUUID prims instance PrimConstruct Prim where-   addfile _ = error "PrimConstruct addfile"-   rmfile _ = error "PrimConstruct rmfile"-   adddir _ = error "PrimConstruct adddir"-   rmdir _ = error "PrimConstruct rmdir"-   move _ _ = error "PrimConstruct move"-   changepref _ _ _ = error "PrimConstruct changepref"-   hunk _ _ _ _ = error "PrimConstruct hunk"-   tokreplace _ _ _ _ = error "PrimConstruct tokreplace"-   binary _ _ _ = error "PrimConstruct binary"-   primFromHunk _ = error "PrimConstruct primFromHunk"-   anIdentity = Identity+  addfile _ = error "PrimConstruct addfile"+  rmfile _ = error "PrimConstruct rmfile"+  adddir _ = error "PrimConstruct adddir"+  rmdir _ = error "PrimConstruct rmdir"+  move _ _ = error "PrimConstruct move"+  changepref _ _ _ = error "PrimConstruct changepref"+  hunk _ _ _ _ = error "PrimConstruct hunk"+  tokreplace _ _ _ _ = error "PrimConstruct tokreplace"+  binary _ _ _ = error "PrimConstruct binary"+  primFromHunk _ = error "PrimConstruct primFromHunk"+  anIdentity = Identity  instance IsHunk Prim where-   isHunk _ = Nothing+  isHunk _ = Nothing  instance Invert Prim where-   invert (BinaryHunk x h) = BinaryHunk x $ invertHunk h-   invert (TextHunk x h) = TextHunk x $ invertHunk h-   invert (Manifest x y) = Demanifest x y-   invert (Demanifest x y) = Manifest x y-   invert (Move x y z) = Move x z y-   invert Identity = Identity+  invert (Hunk x h) = Hunk x $ invertHunk h+  invert (HunkMove hm) = HunkMove $ invertHunkMove hm+  invert (Manifest x y) = Demanifest x y+  invert (Demanifest x y) = Manifest x y+  invert Identity = Identity  instance PatchInspect Prim where-    -- We don't need this for FileUUID. Slashes are not allowed in Manifest and-    -- Demanifest patches and nothing else uses working-copy paths.-    listTouchedFiles _ = []--    -- TODO (used for --match 'hunk ...', presumably)-    hunkMatches _ _ = False+  -- We don't need this for FileUUID. Slashes are not allowed in Manifest and+  -- Demanifest patches and nothing else uses working-copy paths.+  listTouchedFiles _ = [] -instance MyEq Prim where-    unsafeCompare (BinaryHunk a b) (BinaryHunk c d) = a == c && b `unsafeCompare` d-    unsafeCompare (TextHunk a b) (TextHunk c d) = a == c && b `unsafeCompare` d-    unsafeCompare (Manifest a b) (Manifest c d) = a == c && b == d-    unsafeCompare (Demanifest a b) (Demanifest c d) = a == c && b == d-    unsafeCompare Identity Identity = True-    unsafeCompare _ _ = False+  -- TODO (used for --match 'hunk ...', presumably)+  hunkMatches _ _ = False -instance Eq (Prim wX wY) where-    (==) = unsafeCompare+instance Eq2 Prim where+  unsafeCompare (Hunk a b) (Hunk c d) = a == c && b `unsafeCompare` d+  unsafeCompare (Manifest a b) (Manifest c d) = a == c && b == d+  unsafeCompare (Demanifest a b) (Demanifest c d) = a == c && b == d+  unsafeCompare Identity Identity = True+  unsafeCompare _ _ = False
src/Darcs/Patch/Prim/FileUUID/ObjectMap.hs view
@@ -20,24 +20,47 @@ -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. -module Darcs.Patch.Prim.FileUUID.ObjectMap( UUID(..), Location, Object(..),-                                      ObjectMap(..), DirContent ) where+module Darcs.Patch.Prim.FileUUID.ObjectMap+    ( UUID(..), Location(..), Object(..)+    , ObjectMap(..), DirContent, FileContent+    , isBlob, isDirectory+    , Name -- re-export+    ) where  import Prelude () import Darcs.Prelude -import Darcs.Util.Hash( Hash )-import qualified Data.ByteString as BS (ByteString)+import Darcs.Util.Hash ( Hash )+import Darcs.Util.Path ( Name )+import qualified Data.ByteString as B (ByteString) import qualified Data.Map as M +type FileContent = B.ByteString -newtype UUID = UUID BS.ByteString deriving (Eq, Ord, Show)-type Location = (UUID, BS.ByteString)-type DirContent = M.Map BS.ByteString UUID-data Object (m :: * -> *) = Directory DirContent-                          | Blob (m BS.ByteString) !Hash+newtype UUID = UUID B.ByteString deriving (Eq, Ord, Show) -data ObjectMap (m :: * -> *) = ObjectMap { getObject :: UUID -> m (Maybe (Object m))-                                         , putObject :: UUID -> Object m -> m (ObjectMap m)-                                         , listObjects :: m [UUID]-                                         }+-- | An object is located by giving the 'UUID' of the parent+-- 'Directory' and a 'Name'.+data Location = L !UUID !Name+  deriving (Eq, Show)++-- TODO use HashMap instead?+type DirContent = M.Map Name UUID++data Object (m :: * -> *)+  = Directory DirContent+  | Blob (m FileContent) !Hash++isBlob :: Object m -> Bool+isBlob Blob{} = True+isBlob Directory{} = False++isDirectory :: Object m -> Bool+isDirectory Directory{} = True+isDirectory Blob{} = False++data ObjectMap (m :: * -> *) = ObjectMap+  { getObject :: UUID -> m (Maybe (Object m))+  , putObject :: UUID -> Object m -> m (ObjectMap m)+  , listObjects :: m [UUID]+  }
src/Darcs/Patch/Prim/FileUUID/Read.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, ViewPatterns, OverloadedStrings #-}+{-# LANGUAGE ViewPatterns, OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Darcs.Patch.Prim.FileUUID.Read () where @@ -8,39 +8,43 @@ import Darcs.Patch.Read ( ReadPatch(..) ) import Darcs.Patch.ReadMonads import Darcs.Patch.Prim.Class( PrimRead(..) )-import Darcs.Patch.Prim.FileUUID.Core( Prim(..), Hunk(..) )+import Darcs.Patch.Prim.FileUUID.Core( Prim(..), Hunk(..), Location(..) ) import Darcs.Patch.Prim.FileUUID.ObjectMap import Darcs.Patch.Witnesses.Sealed( seal )+import Darcs.Util.Path ( unsafeMakeName )  import Control.Monad ( liftM, liftM2 ) import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC import Data.Char ( chr ) -#include "impossible.h"- instance PrimRead Prim where-  readPrim _ = do skipSpace-                  choice $ map (liftM seal) [-                    identity,-                    hunk "hunk" TextHunk,-                    hunk "binhunk" BinaryHunk,-                    manifest "manifest" Manifest,-                    manifest "demanifest" Demanifest ]--    where manifest kind ctor = liftM2 ctor (patch kind) location-          identity = lexString "identity" >> return Identity-          patch x = string x >> uuid-          uuid = UUID <$> myLex'-          filename = encoded-          encoded = decodeWhite <$> myLex'-          hunktext = skipSpace >> choice [ string "." >> encoded, string "!" >> return B.empty ]-          location = liftM2 (,) uuid filename-          hunk kind ctor = do uid <- patch kind-                              offset <- int-                              old <- hunktext-                              new <- hunktext-                              return $ ctor uid (Hunk offset old new)+  readPrim _ = do+    skipSpace+    choice $ map (liftM seal)+      [ identity+      , hunk "hunk" Hunk+      , manifest "manifest" Manifest+      , manifest "demanifest" Demanifest+      ]+    where+      manifest kind ctor = liftM2 ctor (patch kind) location+      identity = lexString "identity" >> return Identity+      patch x = string x >> uuid+      uuid = UUID <$> myLex'+      filename = unsafeMakeName . decodeWhite <$> myLex'+      content = do+        lexString "content"+        len <- int+        _ <- char '\n'+        Darcs.Patch.ReadMonads.take len+      location = liftM2 L uuid filename+      hunk kind ctor = do+        uid <- patch kind+        offset <- int+        old <- content+        new <- content+        return $ ctor uid (H offset old new)  instance ReadPatch Prim where  readPatch' = readPrim undefined
src/Darcs/Patch/Prim/FileUUID/Show.hs view
@@ -1,70 +1,118 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE CPP, OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings #-} module Darcs.Patch.Prim.FileUUID.Show-    ( showHunk )+    ( displayHunk )     where  import Prelude () import Darcs.Prelude -import Prelude hiding ( pi )--import Data.Char ( isSpace, ord ) import qualified Data.ByteString as B-import qualified Data.ByteString.Char8 as BC  import Darcs.Patch.Format ( PatchListFormat, FileNameFormat(..) )-import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatch(..) )-import Darcs.Patch.Summary ( plainSummaryPrim, plainSummaryPrims )+import Darcs.Patch.Show+    ( ShowPatchBasic(..), ShowPatch(..)+    , ShowContextPatch(..), ShowPatchFor(..) )+import Darcs.Patch.Summary ( plainSummaryPrim ) import Darcs.Patch.Prim.Class ( PrimShow(..) )-import Darcs.Patch.Prim.FileUUID.Core ( Prim(..), Hunk(..), UUID(..) )+import Darcs.Patch.Prim.FileUUID.Core+    ( Prim(..), Hunk(..), HunkMove(..), UUID(..), Location(..), FileContent ) import Darcs.Patch.Prim.FileUUID.Details ()-import Darcs.Util.Printer ( text, packedString, blueText, (<+>), (<>), Doc )--#include "impossible.h"+import Darcs.Util.ByteString ( linesPS )+import Darcs.Util.Path ( Name, encodeWhiteName )+import Darcs.Util.Printer+    ( text, packedString, blueText, prefix+    , (<+>), (<>), ($$), Doc, vcat+    )  -- TODO this instance shouldn't really be necessary, as Prims aren't used generically instance PatchListFormat Prim +fileNameFormat :: ShowPatchFor -> FileNameFormat+fileNameFormat ForDisplay = UserFormat+fileNameFormat ForStorage = NewFormat+ instance ShowPatchBasic Prim where-    showPatch = showPrim OldFormat+  showPatch fmt = showPrim (fileNameFormat fmt) +-- dummy instance, does not actually show any context+instance ShowContextPatch Prim where+  -- showContextPatch f = showPrimCtx (fileNameFormat f)+  showContextPatch f p = return $ showPatch f p+ instance ShowPatch Prim where-    showContextPatch p = return $ showPatch p-    summary = plainSummaryPrim-    summaryFL = plainSummaryPrims False []-    thing _ = "change"+  summary = plainSummaryPrim+  -- summaryFL = plainSummaryPrims False+  thing _ = "change"  instance PrimShow Prim where-  showPrim _ (TextHunk u h) = showHunk "hunk" u h-  showPrim _ (BinaryHunk u h) = showHunk "binhunk" u h-  showPrim _ (Manifest f (d,p)) = showManifest "manifest" d f p-  showPrim _ (Demanifest f (d,p)) = showManifest "demanifest" d f p+  showPrim UserFormat (Hunk u h) = displayHunk (Just u) h+  showPrim _ (Hunk u h) = storeHunk u h+  showPrim UserFormat (HunkMove hm) = displayHunkMove hm+  showPrim _ (HunkMove hm) = storeHunkMove hm+  showPrim _ (Manifest f (L d p)) = showManifest "manifest" d f p+  showPrim _ (Demanifest f (L d p)) = showManifest "demanifest" d f p   showPrim _ Identity = blueText "identity"-  showPrim _ (Move{}) = bug "show for move not implemented"+  showPrimCtx _ _ = bug "show with context not implemented" -showManifest :: String -> UUID -> UUID -> BC.ByteString -> Doc-showManifest txt dir file path = blueText txt <+>-                                 formatUUID file <+>-                                 formatUUID dir <+>-                                 packedString (encodeWhite path)+showManifest :: String -> UUID -> UUID -> Name -> Doc+showManifest txt dir file name =+  blueText txt <+>+  formatUUID file <+>+  formatUUID dir <+>+  packedString (encodeWhiteName name) -showHunk :: String -> UUID -> Hunk wX wY -> Doc-showHunk txt uid (Hunk off old new) = blueText txt <+>-                                      formatUUID uid <+>-                                      text (show off) <+>-                                      hunktext old <+>-                                      hunktext new-    where hunktext bit | B.null bit = text "!"-                       | otherwise = text "." <> packedString (encodeWhite bit)+displayHunk :: Maybe UUID -> Hunk wX wY -> Doc+displayHunk uid (H off old new) =+  blueText "hunk" <+>+  maybe (text "<nil>") formatUUID uid <+>+  text (show off) $$+  displayFileContent "-" old $$+  displayFileContent "+" new -formatUUID :: UUID -> Doc-formatUUID (UUID x) = packedString x+storeHunk :: UUID -> Hunk wX wY -> Doc+storeHunk uid (H off old new) =+  text "hunk" <+>+  formatUUID uid <+>+  text (show off) $$+  storeFileContent old $$+  storeFileContent new --- XXX a bytestring version of encodeWhite from Darcs.FileName-encodeWhite :: B.ByteString -> B.ByteString-encodeWhite = BC.concatMap encode-  where encode c-          | isSpace c || c == '\\' = B.concat [ "\\", BC.pack $ show $ ord c, "\\" ]-          | otherwise = BC.singleton c+displayHunkMove :: HunkMove wX wY -> Doc+displayHunkMove (HM sid soff tid toff c) =+  blueText "hunkmove" <+>+  formatUUID sid <+>+  text (show soff) <+>+  formatUUID tid <+>+  text (show toff) $$+  displayFileContent "|" c +storeHunkMove :: HunkMove wX wY -> Doc+storeHunkMove (HM sid soff tid toff c) =+  text "hunkmove" <+>+  formatUUID sid <+>+  text (show soff) <+>+  formatUUID tid <+>+  text (show toff) $$+  storeFileContent c++-- TODO add some heuristics to recognize binary content+displayFileContent :: String -> FileContent -> Doc+displayFileContent pre = vcat . map (prefix pre) . showLines . linesPS+  where+    context = blueText "[...]"+    showLines [] = []+    showLines [x]+      | B.null x = []+      | otherwise = [context <> packedString x <> context]+    showLines (x:xs) =+      [context <> packedString x] +++      map packedString (init xs) +++      [packedString (last xs) <> context]++storeFileContent :: FileContent -> Doc+storeFileContent c =+  text "content" <+> text (show (B.length c)) $$ packedString c++formatUUID :: UUID -> Doc+formatUUID (UUID x) = packedString x
src/Darcs/Patch/Prim/V1.hs view
@@ -1,9 +1,6 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module Darcs.Patch.Prim.V1 ( Prim ) where -import Prelude ()-import Darcs.Prelude- import Darcs.Patch.Prim.V1.Apply () import Darcs.Patch.Prim.V1.Coalesce () import Darcs.Patch.Prim.V1.Commute ()@@ -12,13 +9,6 @@ import Darcs.Patch.Prim.V1.Read () import Darcs.Patch.Prim.V1.Show () -import Darcs.Patch.Prim.Class ( PrimPatch, PrimPatchBase(..), FromPrim(..) )-import Darcs.Patch.Patchy ( Patchy )--instance PrimPatch Prim-instance Patchy Prim-instance PrimPatchBase Prim where-  type PrimOf Prim = Prim+import Darcs.Patch.Prim.Class ( PrimPatchCommon ) -instance FromPrim Prim where-  fromPrim = id+instance PrimPatchCommon Prim
src/Darcs/Patch/Prim/V1/Apply.hs view
@@ -1,5 +1,4 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE CPP #-} module Darcs.Patch.Prim.V1.Apply () where  import Prelude ()@@ -14,24 +13,23 @@       DirPatchType(..), FilePatchType(..) ) import Darcs.Patch.Prim.V1.Show ( showHunk ) -import Darcs.Util.Path ( fn2fp )-import Darcs.Patch.Format ( FileNameFormat(..) )-import Darcs.Patch.TokenReplace ( tryTokInternal )+import Darcs.Util.Path ( FileName, fn2fp )+import Darcs.Patch.Format ( FileNameFormat(UserFormat) )+import Darcs.Patch.TokenReplace ( tryTokReplace ) -import Darcs.Patch.ApplyMonad ( ApplyMonad(..), ApplyMonadTree(..) )+import Darcs.Patch.ApplyMonad ( ApplyMonadTree(..) ) import Darcs.Util.Tree( Tree )  import Darcs.Patch.Witnesses.Ordered ( FL(..), mapFL_FL, spanFL, (:>)(..) ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoercePStart ) -import Darcs.Util.ByteString ( unlinesPS, breakAfterNthNewline, breakBeforeNthNewline, )-import Darcs.Util.Printer( renderString, RenderMode(..) )+import Darcs.Util.ByteString ( unlinesPS )+import Darcs.Util.Printer( renderString ) +import qualified Data.ByteString            as B+import qualified Data.ByteString.Internal   as BI import qualified Data.ByteString as B ( ByteString, empty, null, concat )-import qualified Data.ByteString.Char8 as BC (pack, singleton, unpack)-import Data.List ( intersperse )--#include "impossible.h"+import qualified Data.ByteString.Char8 as BC (pack, unpack, unlines)  type FileContents = B.ByteString @@ -39,13 +37,13 @@     type ApplyState Prim = Tree     apply (FP f RmFile) = mRemoveFile f     apply (FP f AddFile) = mCreateFile f-    apply p@(FP _ (Hunk{})) = applyPrimFL (p :>: NilFL)-    apply (FP f (TokReplace t o n)) = mModifyFilePSs f doreplace-        where doreplace ls =-                  case mapM (tryTokInternal t (BC.pack o) (BC.pack n)) ls of+    apply (FP f (Hunk l o n)) = mModifyFilePS f $ applyHunk f (l, o, n)+    apply (FP f (TokReplace t o n)) = mModifyFilePS f doreplace+        where doreplace fc =+                  case tryTokReplace t (BC.pack o) (BC.pack n) fc of                   Nothing -> fail $ "replace patch to " ++ fn2fp f                              ++ " couldn't apply."-                  Just ls' -> return $ map B.concat ls'+                  Just fc' -> return fc'     apply (FP f (Binary o n)) = mModifyFilePS f doapply         where doapply oldf = if o == oldf                              then return n@@ -96,61 +94,129 @@                do let foo = h :>: mapFL_FL (\(FP _ h') -> h') xs                   mModifyFilePS f $ hunkmod foo                   applyPrimFL ps'-        where f_hunk (FP f' (Hunk{})) | f == f' = True+        where f_hunk (FP f' (Hunk{})) = f == f'               f_hunk _ = False-              hunkmod :: ApplyMonad Tree m => FL FilePatchType wX wY+              -- TODO there should be a HOF that abstracts+              -- over this recursion scheme+              hunkmod :: Monad m => FL FilePatchType wX wY                       -> B.ByteString -> m B.ByteString-              hunkmod NilFL ps = return ps-              hunkmod (Hunk line old new:>:hs) ps-               = case applyHunkLines [(line,old,new)] ps of-                     Just ps' -> hunkmod hs ps'-                     Nothing -> fail $ "### Error applying:\n" ++-                                       renderString Encode-                                             (showHunk NewFormat f line old new) ++-                                       "\n### to file " ++ fn2fp f ++ ":\n" ++ BC.unpack ps+              hunkmod NilFL content = return content+              hunkmod (Hunk line old new:>:hs) content =+                  applyHunk f (line, old, new) content >>= hunkmod hs               hunkmod _ _ = impossible-    applyPrimFL (p:>:ps) = do apply p-                              applyPrimFL ps+    applyPrimFL (p:>:ps) = apply p >> applyPrimFL ps -applyHunks :: [(Int, [B.ByteString], [B.ByteString])]-           -> B.ByteString -> Maybe [B.ByteString]-applyHunks [] ps = Just [ps]-applyHunks ((l, [], n):hs) ps-    = case breakBeforeNthNewline (l - 2) ps of-      (prfix, after_prefix) -> do rest <- applyHunks hs after_prefix-                                  return $ intersperse nl (prfix:n) ++ rest-                                       where nl = BC.singleton '\n'-applyHunks ((l, o, n):hs) ps-    = case breakBeforeNthNewline (l - 2) ps of-      (prfix, after_prefix) ->-          case breakBeforeNthNewline (length o) after_prefix of-          (oo, _) | oo /= unlinesPS (B.empty:o) -> fail "applyHunks error"-          (_, suffix) ->-              do rest <- applyHunks hs suffix-                 return $ intersperse nl (prfix:n) ++ rest-    where nl = BC.singleton '\n'+applyHunk :: Monad m+          => FileName+          -> (Int, [B.ByteString], [B.ByteString])+          -> FileContents+          -> m FileContents+applyHunk f h fc =+  case applyHunkLines h fc of+    Right fc' -> return fc'+    Left msg ->+      fail $+      "### Error applying:\n" ++ renderHunk h +++      "\n### to file " ++ fn2fp f ++ ":\n" ++ BC.unpack fc +++      "### Reason: " ++ msg+  where+    renderHunk (l, o, n) = renderString (showHunk UserFormat f l o n) -applyHunkLines :: [(Int, [B.ByteString], [B.ByteString])]-               -> FileContents -> Maybe FileContents-applyHunkLines [] c = Just c-applyHunkLines [(1, [], n)] ps | B.null ps = Just $ unlinesPS (n++[B.empty])-applyHunkLines hs@((l, o, n):hs') ps =- do pss <- case l of-           1 -> case breakAfterNthNewline (length o) ps of-                Nothing -> if ps == unlinesPS o-                           then return $ intersperse nl n-                           else fail "applyHunkLines: Unexpected hunks"-                Just (shouldbeo, suffix)-                    | shouldbeo /= unlinesPS (o++[B.empty]) ->-                        fail "applyHunkLines: Bad patch!"-                    | null n ->-                        do x <- applyHunkLines hs' suffix-                           return [x]-                    | otherwise ->-                        do rest <- applyHunks hs' suffix-                           return $ intersperse nl n ++ nl:rest-           _ | l < 0 -> bug "Prim.applyHunkLines: After -ve lines?"-             | otherwise -> applyHunks hs ps-    let result = B.concat pss-    return result-    where nl = BC.singleton '\n'+{- The way darcs handles newlines is not easy to understand.++Everything seems pretty logical and conventional as long as files end in a+newline. In this case, the lines in a hunk can be regarded as newline+terminated, too. However, this view breaks down if we consider files that+are not newline terminated.++Here is a different view that covers the general case and explains,+conceptually, the algorithm below.++* Ever line (in a hunk or file) is regarded as being /preceded/ by a newline+  character.++* Every file starts out containing a single newline character, that is, a+  single empty line. A first empty line at the start of a file (if present)+  is /invisible/.++* When lines are appended to a file by a hunk, they are inserted /before/ a+  final empty line, if there is one. This results in a file that remains+  being terminated by a newline.++* In particular, when we start with an empty file and add a line, we push+  the invisible newline back, making it visible, and the newline that+  initiates our new content becomes invisible instead. This results in a+  newline terminated file, as above.++* However, if there is a newline at the end of a file (remember that this+  includes the case of an empty file), a hunk can /remove/ it by removing an+  empty line before adding anything. This results in a file that is /not/+  newline terminated.++The invisible newline character at the front is, of course, not present+anywhere in the representation of files, it is just a conceptual tool.++The algorithm below is highly optimized to minimize allocation of+intermediate ByteStrings. -}++applyHunkLines :: (Int, [B.ByteString], [B.ByteString])+               -> FileContents+               -> Either String FileContents+applyHunkLines (line, old, new) content+  | line == 1 =+      {- This case is subtle because here we have to deal with any invisible+      newline at the front of a file without it actually being present. We+      first try to drop everything up to the (length old)'th newline. ++      If this fails, we know that the content was not newline terminated. So+      we replace everything with the new content, interspersing but not+      terminating the lines with newline characters.++      If it succeeds, we insert the new content, interspersing /and/+      terminating the lines with newline characters before appending the+      rest of the content. -}+      case breakAfterNthNewline (length old) content of+        Nothing+          -- old content is not newline terminated+          | content == unlinesPS old -> Right $ unlinesPS new+          | otherwise -> Left "Hunk wants to remove content that isn't there"+        Just (should_be_old, suffix)+          -- old content is newline terminated+          | should_be_old == BC.unlines old ->+              Right $ unlinesPS $ new ++ [suffix]+          | otherwise ->+              Left "Hunk wants to remove content that isn't there"+  | line >= 2 = do+      {- This is the simpler case. We can be sure that we have at least one+      newline character at the point where we modify the file. This means we+      can apply the conceptual view literally, i.e. replace old content with+      new content /before/ this newline, where the lines in the old and new+      content are /preceded/ by newline characters. -}+      (pre, start) <- breakBeforeNthNewline (line-2) content+      let hunkContent ls = unlinesPS (B.empty:ls)+      post <- dropPrefix (hunkContent old) start+      return $ B.concat [pre, hunkContent new, post]+  | otherwise = Left "Hunk has zero or negative line number"+  where+    dropPrefix x y+      | x `B.isPrefixOf` y = Right $ B.drop (B.length x) y+      | otherwise =+        Left $ "Hunk wants to remove content that isn't there"++breakAfterNthNewline :: Int -> B.ByteString -> Maybe (B.ByteString, B.ByteString)+breakAfterNthNewline 0 the_ps = Just (B.empty, the_ps)+breakAfterNthNewline n _ | n < 0 = error "precondition of breakAfterNthNewline"+breakAfterNthNewline n the_ps = go n (B.elemIndices (BI.c2w '\n') the_ps)+  where+    go _ [] = Nothing -- we have fewer than n newlines+    go 1 (i:_) = Just $ B.splitAt (i + 1) the_ps+    go !m (_:is) = go (m - 1) is++breakBeforeNthNewline :: Int -> B.ByteString -> Either String (B.ByteString, B.ByteString)+breakBeforeNthNewline n _ | n < 0 = error "precondition of breakBeforeNthNewline"+breakBeforeNthNewline n the_ps = go n (B.elemIndices (BI.c2w '\n') the_ps)+  where+    go 0 [] = Right (the_ps, B.empty)+    go 0 (i:_) = Right $ B.splitAt i the_ps+    go !m (_:is) = go (m - 1) is+    go _ [] = Left "Line number does not exist"
src/Darcs/Patch/Prim/V1/Coalesce.hs view
@@ -1,5 +1,4 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE CPP #-} module Darcs.Patch.Prim.V1.Coalesce     ()     where@@ -23,7 +22,7 @@     , comparePrim, isIdentity     ) import Darcs.Patch.Prim.V1.Show ()-import Darcs.Patch.Witnesses.Eq ( MyEq(..), EqCheck(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) ) import Darcs.Patch.Witnesses.Ordered     ( FL(..), RL(..), (:>)(..)     , reverseRL, mapFL, mapFL_FL@@ -41,8 +40,6 @@ import Darcs.Util.Global ( darcsdir ) import Darcs.Util.Path ( FileName, fp2fn ) -#include "impossible.h"- -- | 'coalesceFwd' @p1 :> p2@ tries to combine @p1@ and @p2@ into a single --   patch without intermediary changes.  For example, two hunk patches --   modifying adjacent lines can be coalesced into a bigger hunk patch.@@ -81,9 +78,11 @@   -data Simple wX wY = SFP !(FilePatchType wX wY) | SDP !(DirPatchType wX wY)-                   | SCP String String String-                   deriving ( Show )+data Simple wX wY+    = SFP !(FilePatchType wX wY)+    | SDP !(DirPatchType wX wY)+    | SCP String String String+    deriving ( Show )  toSimple :: Prim wX wY -> Maybe (FileName, Simple wX wY) toSimple (FP a b) = Just (a, SFP b)
src/Darcs/Patch/Prim/V1/Commute.hs view
@@ -1,10 +1,13 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE CPP #-} module Darcs.Patch.Prim.V1.Commute     ( Perhaps(..)-    , subcommutes, WrappedCommuteFunction(..)-    )-    where+    , toPerhaps+    , CommuteFunction+    , speedyCommute+    , cleverCommute+    , commuteFiledir+    , commuteFilepatches+    ) where  import Prelude () import Darcs.Prelude@@ -13,8 +16,8 @@ import Control.Monad ( MonadPlus, msum, mzero, mplus ) import Control.Applicative ( Alternative(..) ) -import qualified Data.ByteString as B (ByteString, concat)-import qualified Data.ByteString.Char8 as BC (pack)+import qualified Data.ByteString as B ( ByteString )+import qualified Data.ByteString.Char8 as BC ( pack )  import Darcs.Util.Path ( FileName, fn2fp, movedirfilename ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )@@ -24,9 +27,7 @@ import Darcs.Patch.Invert ( Invert(..) ) import Darcs.Patch.Commute ( Commute(..) ) import Darcs.Patch.Permutations () -- for Invert instance of FL-import Darcs.Patch.TokenReplace ( tryTokInternal )--#include "impossible.h"+import Darcs.Patch.TokenReplace ( tryTokReplace )  isInDirectory :: FileName -> FileName -> Bool isInDirectory d f = iid (fn2fp d) (fn2fp f)@@ -162,16 +163,7 @@ commuteFiledir _ = Unknown  type CommuteFunction = forall wX wY . (Prim :> Prim) wX wY -> Perhaps ((Prim :> Prim) wX wY)-newtype WrappedCommuteFunction = WrappedCommuteFunction { runWrappedCommuteFunction :: CommuteFunction } -subcommutes :: [(String, WrappedCommuteFunction)]-subcommutes =-    [("speedyCommute", WrappedCommuteFunction speedyCommute),-     ("commuteFiledir", WrappedCommuteFunction (cleverCommute commuteFiledir)),-     ("commuteFilepatches", WrappedCommuteFunction (cleverCommute commuteFilepatches)),-     ("commutex", WrappedCommuteFunction (toPerhaps . commute))-    ]- commuteFilepatches :: CommuteFunction commuteFilepatches (FP f1 p1 :> FP f2 p2) | f1 == f2 = commuteFP f1 (p1 :> p2) commuteFilepatches _ = Unknown@@ -179,21 +171,25 @@ commuteFP :: FileName -> (FilePatchType :> FilePatchType) wX wY           -> Perhaps ((Prim :> Prim) wX wY) commuteFP f (p1 :> Hunk line1 [] []) =-    seq f $ Succeeded (FP f (Hunk line1 [] []) :> FP f (unsafeCoerceP p1))+    Succeeded (FP f (Hunk line1 [] []) :> FP f (unsafeCoerceP p1)) commuteFP f (Hunk line1 [] [] :> p2) =-    seq f $ Succeeded (FP f (unsafeCoerceP p2) :> FP f (Hunk line1 [] []))-commuteFP f (Hunk line1 old1 new1 :> Hunk line2 old2 new2) = seq f $-  toPerhaps $ commuteHunk f (Hunk line1 old1 new1 :> Hunk line2 old2 new2)-commuteFP f (Hunk line1 old1 new1 :> TokReplace t o n) = seq f $-    case tryTokReplace t o n old1 of+    Succeeded (FP f (unsafeCoerceP p2) :> FP f (Hunk line1 [] []))+commuteFP f (Hunk line1 old1 new1 :> Hunk line2 old2 new2) =+    case commuteHunkLines line1 (length old1) (length new1) line2 (length old2) (length new2) of+      Just (line2', line1') ->+        Succeeded (FP f (Hunk line2' old2 new2) :> FP f (Hunk line1' old1 new1))+      Nothing -> Failed+commuteFP f (Hunk line1 old1 new1 :> TokReplace t o n) =+    let po = BC.pack o; pn = BC.pack n in+    case tryTokReplaces t po pn old1 of     Nothing -> Failed     Just old1' ->-      case tryTokReplace t o n new1 of+      case tryTokReplaces t po pn new1 of         Nothing -> Failed         Just new1' -> Succeeded (FP f (TokReplace t o n) :>                                  FP f (Hunk line1 old1' new1')) commuteFP f (TokReplace t1 o1 n1 :> TokReplace t2 o2 n2)-    | seq f $ t1 /= t2 = Failed+    | t1 /= t2 = Failed     | o1 == o2 = Failed     | n1 == o2 = Failed     | o1 == n2 = Failed@@ -202,31 +198,23 @@                              FP f (TokReplace t1 o1 n1)) commuteFP _ _ = Unknown -commuteHunk :: FileName -> (FilePatchType :> FilePatchType) wX wY-            -> Maybe ((Prim :> Prim) wX wY)-commuteHunk f (Hunk line1 old1 new1 :> Hunk line2 old2 new2)-  | seq f $ line1 + lengthnew1 < line2 =-      Just (FP f (Hunk (line2 - lengthnew1 + lengthold1) old2 new2) :>-            FP f (Hunk line1 old1 new1))-  | line2 + lengthold2 < line1 =-      Just (FP f (Hunk line2 old2 new2) :>-            FP f (Hunk (line1+ lengthnew2 - lengthold2) old1 new1))-  | line1 + lengthnew1 == line2 &&-    lengthold2 /= 0 && lengthold1 /= 0 && lengthnew2 /= 0 && lengthnew1 /= 0 =-      Just (FP f (Hunk (line2 - lengthnew1 + lengthold1) old2 new2) :>-            FP f (Hunk line1 old1 new1))-  | line2 + lengthold2 == line1 &&-    lengthold2 /= 0 && lengthold1 /= 0 && lengthnew2 /= 0 && lengthnew1 /= 0 =-      Just (FP f (Hunk line2 old2 new2) :>-            FP f (Hunk (line1 + lengthnew2 - lengthold2) old1 new1))-  | otherwise = seq f Nothing-  where lengthnew1 = length new1-        lengthnew2 = length new2-        lengthold1 = length old1-        lengthold2 = length old2-commuteHunk _ _ = impossible+commuteHunkLines :: Int -> Int -> Int -> Int -> Int -> Int+                 -> Maybe (Int, Int)+commuteHunkLines line1 len_old1 len_new1 line2 len_old2 len_new2+  | line1 + len_new1 < line2  = Just (line2 - len_new1 + len_old1, line1)+  | line2 + len_old2 < line1  = Just (line2, line1 + len_new2 - len_old2)+  | len_old2 /= 0+  , len_old1 /= 0+  , len_new2 /= 0+  , len_new1 /= 0+  , line1 + len_new1 == line2 = Just (line2 - len_new1 + len_old1, line1)+  | len_old2 /= 0+  , len_old1 /= 0+  , len_new2 /= 0+  , len_new1 /= 0+  , line2 + len_old2 == line1 = Just (line2, line1 + len_new2 - len_old2)+  | otherwise                 = Nothing -tryTokReplace :: String -> String -> String-                -> [B.ByteString] -> Maybe [B.ByteString]-tryTokReplace t o n =-  mapM (fmap B.concat . tryTokInternal t (BC.pack o) (BC.pack n))+tryTokReplaces :: String -> B.ByteString -> B.ByteString+               -> [B.ByteString] -> Maybe [B.ByteString]+tryTokReplaces t o n = mapM (tryTokReplace t o n)
src/Darcs/Patch/Prim/V1/Core.hs view
@@ -15,9 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}-- module Darcs.Patch.Prim.V1.Core        ( Prim(..),          DirPatchType(..), FilePatchType(..),@@ -29,12 +26,10 @@ import Prelude () import Darcs.Prelude -import Prelude hiding ( pi )- import qualified Data.ByteString as B (ByteString)  import Darcs.Util.Path ( FileName, fn2fp, fp2fn, normPath )-import Darcs.Patch.Witnesses.Eq ( MyEq(..), EqCheck(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP ) import Darcs.Patch.Debug ( PatchDebug(..) ) import Darcs.Patch.FileHunk ( FileHunk(..), IsHunk(..) )@@ -49,19 +44,21 @@     FP :: !FileName -> !(FilePatchType wX wY) -> Prim wX wY     ChangePref :: !String -> !String -> !String -> Prim wX wY -data FilePatchType wX wY = RmFile | AddFile-                          | Hunk !Int [B.ByteString] [B.ByteString]-                          | TokReplace !String !String !String-                          | Binary B.ByteString B.ByteString-                            deriving (Eq,Ord)+data FilePatchType wX wY+    = RmFile+    | AddFile+    | Hunk !Int [B.ByteString] [B.ByteString]+    | TokReplace !String !String !String+    | Binary B.ByteString B.ByteString+    deriving (Eq,Ord)  data DirPatchType wX wY = RmDir | AddDir                            deriving (Eq,Ord) -instance MyEq FilePatchType where+instance Eq2 FilePatchType where     unsafeCompare a b = a == unsafeCoerceP b -instance MyEq DirPatchType where+instance Eq2 DirPatchType where     unsafeCompare a b = a == unsafeCoerceP b  isIdentity :: Prim wX wY -> EqCheck wX wY@@ -153,7 +150,7 @@  instance PatchDebug Prim -instance MyEq Prim where+instance Eq2 Prim where     unsafeCompare (Move a b) (Move c d) = a == c && b == d     unsafeCompare (DP d1 p1) (DP d2 p2)         = d1 == d2 && p1 `unsafeCompare` p2
src/Darcs/Patch/Prim/V1/Read.hs view
@@ -6,17 +6,19 @@  import Darcs.Patch.Prim.Class ( PrimRead(..), hunk, binary ) import Darcs.Patch.Prim.V1.Core-    ( Prim(..),-      DirPatchType(..), FilePatchType(..) )+    ( Prim(..)+    , DirPatchType(..)+    , FilePatchType(..)+    )  import Darcs.Util.Path ( fn2fp )-import Darcs.Patch.Format ( FileNameFormat(..) )-import Darcs.Patch.Read ( ReadPatch(..), readFileName )-import Darcs.Patch.ReadMonads (ParserM, takeTillChar,-                               string, int,-                               option, choice,-                               anyChar, char, myLex',-                               skipSpace, skipWhile, linesStartingWith)+import Darcs.Patch.Format ( FileNameFormat )+import Darcs.Patch.Read ( readFileName )+import Darcs.Patch.ReadMonads+    ( ParserM, takeTillChar, string, int+    , option, choice, anyChar, char, myLex'+    , skipSpace, skipWhile, linesStartingWith+    )  import Darcs.Patch.Witnesses.Sealed ( seal ) @@ -27,20 +29,17 @@ import qualified Data.ByteString.Char8 as BC ( unpack, pack )  -instance ReadPatch Prim where- readPatch' = readPrim OldFormat- instance PrimRead Prim where-  readPrim x+  readPrim fmt      = skipSpace >> choice-       [ return' $ readHunk x-       , return' $ readAddFile x-       , return' $ readAddDir x-       , return' $ readMove x-       , return' $ readRmFile x-       , return' $ readRmDir x-       , return' $ readTok x-       , return' $ readBinary x+       [ return' $ readHunk fmt+       , return' $ readAddFile fmt+       , return' $ readAddDir fmt+       , return' $ readMove fmt+       , return' $ readRmFile fmt+       , return' $ readRmDir fmt+       , return' $ readTok fmt+       , return' $ readBinary fmt        , return' readChangePref        ]     where@@ -74,30 +73,31 @@ changepref = BC.pack "changepref"  readHunk :: ParserM m => FileNameFormat -> m (Prim wX wY)-readHunk x = do+readHunk fmt = do   string hunk'   fi <- myLex'   l <- int   have_nl <- skipNewline   if have_nl-     then do _ <- linesStartingWith ' ' -- skipping context-             old <- linesStartingWith '-'-             new <- linesStartingWith '+'-             _ <- linesStartingWith ' ' -- skipping context-             return $ hunk (fn2fp $ readFileName x fi) l old new-     else return $ hunk (fn2fp $ readFileName x fi) l [] []+    then do+      _ <- linesStartingWith ' ' -- skipping context+      old <- linesStartingWith '-'+      new <- linesStartingWith '+'+      _ <- linesStartingWith ' ' -- skipping context+      return $ hunk (fn2fp $ readFileName fmt fi) l old new+    else return $ hunk (fn2fp $ readFileName fmt fi) l [] []  skipNewline :: ParserM m => m Bool skipNewline = option False (char '\n' >> return True)  readTok :: ParserM m => FileNameFormat -> m (Prim wX wY)-readTok x = do+readTok fmt = do   string replace   f <- myLex'   regstr <- myLex'   o <- myLex'   n <- myLex'-  return $ FP (readFileName x f) $ TokReplace (BC.unpack (drop_brackets regstr))+  return $ FP (readFileName fmt f) $ TokReplace (BC.unpack (drop_brackets regstr))                           (BC.unpack o) (BC.unpack n)     where drop_brackets = B.init . B.tail @@ -114,7 +114,7 @@ -- > *HEXHEXHEX -- > ... readBinary :: ParserM m => FileNameFormat -> m (Prim wX wY)-readBinary x = do+readBinary fmt = do   string binary'   fi <- myLex'   _ <- myLex'@@ -123,44 +123,48 @@   _ <- myLex'   skipSpace   new <- linesStartingWith '*'-  return $ binary (fn2fp $ readFileName x fi)+  return $ binary (fn2fp $ readFileName fmt fi)                   (fromHex2PS $ B.concat old)                   (fromHex2PS $ B.concat new)  readAddFile :: ParserM m => FileNameFormat -> m (Prim wX wY)-readAddFile x = do string addfile-                   f <- myLex'-                   return $ FP (readFileName x f) AddFile+readAddFile fmt = do+  string addfile+  f <- myLex'+  return $ FP (readFileName fmt f) AddFile  readRmFile :: ParserM m => FileNameFormat -> m (Prim wX wY)-readRmFile x = do string rmfile-                  f <- myLex'-                  return $ FP (readFileName x f) RmFile+readRmFile fmt = do+  string rmfile+  f <- myLex'+  return $ FP (readFileName fmt f) RmFile  readMove :: ParserM m => FileNameFormat -> m (Prim wX wY)-readMove x = do string move-                d <- myLex'-                d' <- myLex'-                return $ Move (readFileName x d) (readFileName x d')+readMove fmt = do+  string move+  d <- myLex'+  d' <- myLex'+  return $ Move (readFileName fmt d) (readFileName fmt d')  readChangePref :: ParserM m => m (Prim wX wY)-readChangePref- = do string changepref-      p <- myLex'-      skipWhile (== ' ')-      _ <- anyChar -- skip newline-      f <- takeTillChar '\n'-      _ <- anyChar -- skip newline-      t <- takeTillChar '\n'-      return $ ChangePref (BC.unpack p) (BC.unpack f) (BC.unpack t)+readChangePref = do+  string changepref+  p <- myLex'+  skipWhile (== ' ')+  _ <- anyChar -- skip newline+  f <- takeTillChar '\n'+  _ <- anyChar -- skip newline+  t <- takeTillChar '\n'+  return $ ChangePref (BC.unpack p) (BC.unpack f) (BC.unpack t)  readAddDir :: ParserM m => FileNameFormat -> m (Prim wX wY)-readAddDir x = do string adddir-                  f <- myLex'-                  return $ DP (readFileName x f) AddDir+readAddDir fmt = do+  string adddir+  f <- myLex'+  return $ DP (readFileName fmt f) AddDir  readRmDir :: ParserM m => FileNameFormat -> m (Prim wX wY)-readRmDir x = do string rmdir-                 f <- myLex'-                 return $ DP (readFileName x f) RmDir-+readRmDir fmt = do+  string rmdir+  f <- myLex'+  return $ DP (readFileName fmt f) RmDir
src/Darcs/Patch/Prim/V1/Show.hs view
@@ -7,47 +7,31 @@ import Prelude () import Darcs.Prelude -import Prelude hiding ( pi )- import Darcs.Util.ByteString ( fromPS2Hex ) import qualified Data.ByteString as B (ByteString, length, take, drop) import qualified Data.ByteString.Char8 as BC (head) -import Darcs.Util.Tree( Tree )--import Darcs.Patch.FileHunk ( FileHunk(..), IsHunk(..), showFileHunk )-import Darcs.Util.Path ( FileName )-import Darcs.Patch.Format ( PatchListFormat, FileNameFormat(..) )-import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatch(..), formatFileName )-import Darcs.Patch.Apply( ApplyState )-import Darcs.Patch.Summary ( plainSummaryPrim, plainSummaryPrims )-import Darcs.Patch.Viewing ( showContextHunk )+import Darcs.Patch.Apply ( ApplyState )+import Darcs.Patch.FileHunk ( FileHunk(..), showFileHunk )+import Darcs.Patch.Format ( FileNameFormat )+import Darcs.Patch.Show ( formatFileName ) import Darcs.Patch.Permutations () -- for Invert instance of FL import Darcs.Patch.Prim.Class ( PrimShow(..) ) import Darcs.Patch.Prim.V1.Core      ( Prim(..), FilePatchType(..), DirPatchType(..) ) import Darcs.Patch.Prim.V1.Details ()+import Darcs.Patch.Viewing ( showContextHunk ) import Darcs.Patch.Witnesses.Show ( Show1(..), Show2(..), ShowDict(..) )++import Darcs.Util.Path ( FileName ) import Darcs.Util.Printer ( Doc, vcat,                  text, userchunk, invisibleText, invisiblePS, blueText,                  ($$), (<+>), (<>),                ) import Darcs.Util.Show ( appPrec, BSWrapper(..) )+import Darcs.Util.Tree ( Tree )  --- TODO this instance shouldn't really be necessary, as Prims aren't used generically-instance PatchListFormat Prim--instance ShowPatchBasic Prim where-    showPatch = showPrim OldFormat--instance (ApplyState Prim ~ Tree) => ShowPatch Prim where-    showContextPatch (isHunk -> Just fh) = showContextHunk fh-    showContextPatch p = return $ showPatch p-    summary = plainSummaryPrim-    summaryFL = plainSummaryPrims False []-    thing _ = "change"- instance Show (Prim wX wY) where     showsPrec d (Move fn1 fn2) = showParen (d > appPrec) $ showString "Move " .                                  showsPrec (appPrec + 1) fn1 . showString " " .@@ -96,25 +80,27 @@     showsPrec _ RmDir = showString "RmDir"     showsPrec _ AddDir = showString "AddDir" -instance PrimShow Prim where-  showPrim x (FP f AddFile) = showAddFile x f-  showPrim x (FP f RmFile)  = showRmFile x f-  showPrim x (FP f (Hunk line old new))  = showHunk x f line old new-  showPrim x (FP f (TokReplace t old new))  = showTok x f t old new-  showPrim x (FP f (Binary old new))  = showBinary x f old new-  showPrim x (DP d AddDir) = showAddDir x d-  showPrim x (DP d RmDir)  = showRmDir x d-  showPrim x (Move f f') = showMove x f f'+instance ApplyState Prim ~ Tree => PrimShow Prim where+  showPrim fmt (FP f AddFile) = showAddFile fmt f+  showPrim fmt (FP f RmFile)  = showRmFile fmt f+  showPrim fmt (FP f (Hunk line old new))  = showHunk fmt f line old new+  showPrim fmt (FP f (TokReplace t old new))  = showTok fmt f t old new+  showPrim fmt (FP f (Binary old new))  = showBinary fmt f old new+  showPrim fmt (DP d AddDir) = showAddDir fmt d+  showPrim fmt (DP d RmDir)  = showRmDir fmt d+  showPrim fmt (Move f f') = showMove fmt f f'   showPrim _ (ChangePref p f t) = showChangePref p f t+  showPrimCtx fmt (FP f (Hunk line old new)) = showContextHunk fmt (FileHunk f line old new)+  showPrimCtx fmt p = return $ showPrim fmt p  showAddFile :: FileNameFormat -> FileName -> Doc-showAddFile x f = blueText "addfile" <+> formatFileName x f+showAddFile fmt f = blueText "addfile" <+> formatFileName fmt f  showRmFile :: FileNameFormat -> FileName -> Doc-showRmFile x f = blueText "rmfile" <+> formatFileName x f+showRmFile fmt f = blueText "rmfile" <+> formatFileName fmt f  showMove :: FileNameFormat -> FileName -> FileName -> Doc-showMove x d d' = blueText "move" <+> formatFileName x d <+> formatFileName x d'+showMove fmt d d' = blueText "move" <+> formatFileName fmt d <+> formatFileName fmt d'  showChangePref :: String -> String -> String -> Doc showChangePref p f t = blueText "changepref" <+> text p@@ -122,23 +108,23 @@                     $$ userchunk t  showAddDir :: FileNameFormat -> FileName -> Doc-showAddDir x d = blueText "adddir" <+> formatFileName x d+showAddDir fmt d = blueText "adddir" <+> formatFileName fmt d  showRmDir :: FileNameFormat -> FileName -> Doc-showRmDir x d = blueText "rmdir" <+> formatFileName x d+showRmDir fmt d = blueText "rmdir" <+> formatFileName fmt d  showHunk :: FileNameFormat -> FileName -> Int -> [B.ByteString] -> [B.ByteString] -> Doc-showHunk x f line old new = showFileHunk x (FileHunk f line old new)+showHunk fmt f line old new = showFileHunk fmt (FileHunk f line old new)  showTok :: FileNameFormat -> FileName -> String -> String -> String -> Doc-showTok x f t o n = blueText "replace" <+> formatFileName x f+showTok fmt f t o n = blueText "replace" <+> formatFileName fmt f                                      <+> text "[" <> userchunk t <> text "]"                                      <+> userchunk o                                      <+> userchunk n  showBinary :: FileNameFormat -> FileName -> B.ByteString -> B.ByteString -> Doc-showBinary x f o n =-    blueText "binary" <+> formatFileName x f+showBinary fmt f o n =+    blueText "binary" <+> formatFileName fmt f  $$ invisibleText "oldhex"  $$ vcat (map makeprintable $ breakEvery 78 $ fromPS2Hex o)  $$ invisibleText "newhex"
src/Darcs/Patch/Progress.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE CPP, GADTs #-}- module Darcs.Patch.Progress     ( progressRL     , progressFL
src/Darcs/Patch/Read.hs view
@@ -15,8 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.Patch.Read ( ReadPatch(..),                           readPatch, readPatchPartial,                           bracketedFL, peekfor,@@ -26,11 +24,11 @@ import Prelude () import Darcs.Prelude -import Darcs.Util.ByteString ( dropSpace )+import Darcs.Util.ByteString ( dropSpace, unpackPSFromUTF8, decodeLocale ) import qualified Data.ByteString       as B  (ByteString, null)  import Darcs.Patch.Bracketed ( Bracketed(..), unBracketedFL )-import Darcs.Util.Path ( FileName, fp2fn, ps2fn, decodeWhite )+import Darcs.Util.Path ( FileName, fp2fn, decodeWhite ) import Darcs.Patch.Format ( PatchListFormat(..), ListFormat(..), FileNameFormat(..) ) import Darcs.Patch.ReadMonads (ParserM,                                parseStrictly,@@ -42,9 +40,9 @@  import Control.Applicative ( (<|>) ) import Control.Monad ( mzero )-import qualified Data.ByteString.Char8 as BC ( ByteString, unpack )-+import qualified Data.ByteString.Char8 as BC ( ByteString, pack ) +-- | This class is used to decode patches from their binary representation. class ReadPatch p where     readPatch'         :: ParserM m => m (Sealed (p wX))@@ -116,6 +114,8 @@                                 , ifnot ] {-# INLINE peekfor #-} +-- See also Darcs.Patch.Show.formatFileName. readFileName :: FileNameFormat -> B.ByteString -> FileName-readFileName OldFormat = ps2fn-readFileName NewFormat = fp2fn . decodeWhite . BC.unpack+readFileName OldFormat = fp2fn . decodeWhite . decodeLocale . BC.pack . unpackPSFromUTF8+readFileName NewFormat = fp2fn . decodeWhite . decodeLocale+readFileName UserFormat = error "readFileName called with UserFormat"
src/Darcs/Patch/Rebase.hs view
@@ -6,6 +6,7 @@     , takeHeadRebaseFL     , takeAnyRebase     , takeAnyRebaseAndTrailingPatches+    , dropAnyRebase     ) where  import Prelude ()@@ -14,7 +15,13 @@ import Darcs.Patch.Named.Wrapped ( WrappedNamed(RebaseP) ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, hopefully ) import Darcs.Patch.Rebase.Container ( Suspended(..) )-import Darcs.Patch.RepoType ( RepoType(..), RebaseType(..) )+import Darcs.Patch.RepoType+    ( RepoType(..)+    , RebaseType(..)+    , IsRepoType(..)+    , SRepoType(..)+    , SRebaseType(..)+    ) import Darcs.Patch.Set ( PatchSet(..) ) import Darcs.Patch.Witnesses.Ordered import Darcs.Patch.Witnesses.Sealed@@ -77,56 +84,76 @@  -} --- |given the repository contents, get the rebase container patch, and its contents--- The rebase patch can be anywhere in the repository and is returned without being--- commuted to the end.+-- | Given the repository contents, get the rebase container patch, and its+-- contents. The rebase patch can be anywhere in the repository and is returned+-- without being commuted to the end. takeAnyRebase ::  PatchSet ('RepoType 'IsRebase) p wA wB               -> (Sealed2 (PatchInfoAnd ('RepoType 'IsRebase) p),                   Sealed2 (Suspended p)) takeAnyRebase (PatchSet _ NilRL) =    -- it should never be behind a tag so we can stop now-   error "internal error: no suspended patch found"+   bug "internal error: no suspended patch found" takeAnyRebase (PatchSet pss (ps :<: p))     | RebaseP _ rs <- hopefully p = (Sealed2 p, Sealed2 rs)     | otherwise = takeAnyRebase (PatchSet pss ps) --- |given the repository contents, get the rebase container patch, its contents, and the--- rest of the repository contents. Commutes the patch to the end of the repository--- if necessary. The rebase patch must be at the head of the repository.+-- | Given the repository contents, get the rebase container patch, its+-- contents, and the rest of the repository contents. The rebase patch can be+-- anywhere in the repository and is returned without being commuted to the end. takeAnyRebaseAndTrailingPatches                :: PatchSet ('RepoType 'IsRebase) p wA wB-               -> FlippedSeal (PatchInfoAnd ('RepoType 'IsRebase) p :> RL (PatchInfoAnd ('RepoType 'IsRebase) p)) wB+               -> FlippedSeal (PatchInfoAnd ('RepoType 'IsRebase) p :>+                               RL (PatchInfoAnd ('RepoType 'IsRebase) p)) wB takeAnyRebaseAndTrailingPatches (PatchSet _ NilRL) =    -- it should never be behind a tag so we can stop now-   error "internal error: no suspended patch found"+   bug "internal error: no suspended patch found" takeAnyRebaseAndTrailingPatches (PatchSet pss (ps :<: p))     | RebaseP _ _ <- hopefully p = FlippedSeal (p :> NilRL)     | otherwise = case takeAnyRebaseAndTrailingPatches (PatchSet pss ps) of                      FlippedSeal (r :> ps') -> FlippedSeal (r :> (ps' :<: p)) --- |given the repository contents, get the rebase container patch, its contents, and the--- rest of the repository contents. The rebase patch must be at the head of the repository.+-- | Remove the rebase patch from a 'PatchSet'.+dropAnyRebase :: forall rt p wA wB. IsRepoType rt+              => PatchSet rt p wA wB -> PatchSet rt p wA wB+dropAnyRebase ps@(PatchSet tags patches) =+  case singletonRepoType::SRepoType rt of+    SRepoType SNoRebase -> ps+    SRepoType SIsRebase -> PatchSet tags (dropRebaseRL patches)++-- | Remove the rebase patch from an 'RL' of patches.+dropRebaseRL :: RL (PatchInfoAnd ('RepoType 'IsRebase) p) wA wB+             -> RL (PatchInfoAnd ('RepoType 'IsRebase) p) wA wB+dropRebaseRL NilRL = bug "internal error: no suspended patch found"+dropRebaseRL (ps :<: p)+  | RebaseP _ _ <- hopefully p = ps+  | otherwise = dropRebaseRL ps :<: p++-- | Given the repository contents, get the rebase container patch, its+-- contents, and the rest of the repository contents. The rebase patch must be+-- at the head of the repository. takeHeadRebase :: PatchSet ('RepoType 'IsRebase) p wA wB                -> (PatchInfoAnd ('RepoType 'IsRebase) p wB wB,                    Suspended p wB wB,                    PatchSet ('RepoType 'IsRebase) p wA wB)-takeHeadRebase (PatchSet _ NilRL) = error "internal error: must have a rebase container patch at end of repository" takeHeadRebase (PatchSet pss (ps :<: p))     | RebaseP _ rs <- hopefully p = (p, rs, PatchSet pss ps)-    | otherwise = error "internal error: must have a rebase container patch at end of repository"+takeHeadRebase _ =+    bug "internal error: must have a rebase container patch at end of repository" +-- | Same as 'takeHeadRebase' but for an 'RL' of patches. takeHeadRebaseRL :: RL (PatchInfoAnd ('RepoType 'IsRebase) p) wA wB                  -> (PatchInfoAnd ('RepoType 'IsRebase) p wB wB,                      Suspended p wB wB,                      RL (PatchInfoAnd ('RepoType 'IsRebase) p) wA wB)-takeHeadRebaseRL NilRL = error "internal error: must have a suspended patch at end of repository" takeHeadRebaseRL (ps :<: p)     | RebaseP _ rs <- hopefully p = (p, rs, ps)-    | otherwise = error "internal error: must have a suspended patch at end of repository"+takeHeadRebaseRL _ =+    bug "internal error: must have a suspended patch at end of repository" +-- | Same as 'takeHeadRebase' but for an 'FL' of patches. takeHeadRebaseFL :: FL (PatchInfoAnd ('RepoType 'IsRebase) p) wA wB                  -> (PatchInfoAnd ('RepoType 'IsRebase) p wB wB,                      Suspended p wB wB,                      FL (PatchInfoAnd ('RepoType 'IsRebase) p) wA wB)-takeHeadRebaseFL ps = let (a, b, c) = takeHeadRebaseRL (reverseFL ps) in (a, b, reverseRL c)-+takeHeadRebaseFL ps =+  let (a, b, c) = takeHeadRebaseRL (reverseFL ps) in (a, b, reverseRL c)
src/Darcs/Patch/Rebase/Container.hs view
@@ -14,11 +14,12 @@ import Darcs.Patch.Format ( PatchListFormat(..) ) import Darcs.Patch.Invert ( invert ) import Darcs.Patch.Named ( Named )-import Darcs.Patch.Patchy ( Commute(..), Apply(..),-                            ShowPatch(..), ReadPatch(..),-                            PatchInspect(..)-                          )-import Darcs.Patch.Prim ( PrimPatchBase, PrimOf, FromPrim(..), FromPrim(..) )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Inspect ( PatchInspect(..) )+import Darcs.Patch.Read ( ReadPatch(..) )+import Darcs.Patch.Show ( ShowPatch(..) )+import Darcs.Patch.Prim ( PrimPatchBase(..), FromPrim(..), FromPrim(..) ) import Darcs.Patch.Read ( bracketedFL ) import Darcs.Patch.Rebase.Fixup ( RebaseFixup(..), namedToFixups ) import Darcs.Patch.Rebase.Item ( RebaseItem(..) )@@ -91,24 +92,18 @@    resolveConflicts _ = []    conflictedEffect _ = [] -instance Apply p => Apply (Suspended p) where+instance Apply (Suspended p) where    type ApplyState (Suspended p) = ApplyState p    apply _ = return ()  instance (PrimPatchBase p, PatchListFormat p, ShowPatchBasic p) => ShowPatchBasic (Suspended p) where-   showPatch (Items ps)+   showPatch f (Items ps)        = blueText "rebase" <+> text "0.0" <+> blueText "{"-         $$ vcat (mapFL showPatch ps)+         $$ vcat (mapFL (showPatch f) ps)          $$ blueText "}"  instance (PrimPatchBase p, PatchListFormat p, Apply p, CommuteNoConflicts p, Conflict p, IsHunk p, ShowPatch p) => ShowPatch (Suspended p) where--   showContextPatch s = return $ showPatch s--   description s = showPatch s-    summary (Items ps) = summaryFL ps-    summaryFL ps = vcat (mapFL summary ps)  instance PrimPatchBase p => PrimPatchBase (Suspended p) where@@ -129,13 +124,13 @@          [] -> Nothing          xs -> Just (vcat xs) -instance Apply p => Repair (Suspended p) where+instance Repair (Suspended p) where    applyAndTryToFix (Items ps) =    -- TODO: ideally we would apply ps in a sandbox to check the individual patches    -- are consistent with each other.        return . fmap (unlines *** Items) $ repairInternal ps -instance Apply p => RepairToFL (Suspended p) where+instance RepairToFL (Suspended p) where    applyAndTryToFixFL s = fmap (second $ (:>: NilFL)) <$> applyAndTryToFix s  -- Just repair the internals of the patch, without applying it to anything
src/Darcs/Patch/Rebase/Fixup.hs view
@@ -20,13 +20,13 @@ import Darcs.Patch.Inspect ( PatchInspect(..) ) import Darcs.Patch.Invert ( Invert(..) ) import Darcs.Patch.Named ( Named(..), commuterNamedId, commuterIdNamed )-import Darcs.Patch.Prim ( PrimPatchBase, PrimOf )+import Darcs.Patch.Prim ( PrimPatchBase(..), PrimPatch ) import Darcs.Patch.Rebase.Name     ( RebaseName(..)     , commuteNamedName, commuteNameNamed     , commutePrimName, commuteNamePrim     )-import Darcs.Patch.Witnesses.Eq ( MyEq(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..) ) import Darcs.Patch.Witnesses.Ordered     ( FL(..), mapFL_FL, (:>)(..), (+>+) ) import Darcs.Patch.Witnesses.Show@@ -37,10 +37,10 @@ -- |A single rebase fixup, needed to ensure that the actual patches -- being stored in the rebase state have the correct context. data RebaseFixup p wX wY where-  PrimFixup :: PrimOf p wX wY -> RebaseFixup p wX wY+  PrimFixup :: PrimPatch (PrimOf p) => PrimOf p wX wY -> RebaseFixup p wX wY   NameFixup :: RebaseName p wX wY -> RebaseFixup p wX wY -namedToFixups :: Effect p => Named p wX wY -> FL (RebaseFixup p) wX wY+namedToFixups :: (PrimPatch (PrimOf p), Effect p) => Named p wX wY -> FL (RebaseFixup p) wX wY namedToFixups (NamedP p _ contents) = NameFixup (AddName p) :>: mapFL_FL PrimFixup (effect contents)  instance Show2 (PrimOf p) => Show (RebaseFixup p wX wY) where@@ -58,7 +58,7 @@ instance PrimPatchBase p => PrimPatchBase (RebaseFixup p) where     type PrimOf (RebaseFixup p) = PrimOf p -instance (PrimPatchBase p, Apply p, ApplyState p ~ ApplyState (PrimOf p)) => Apply (RebaseFixup p) where+instance (PrimPatchBase p, ApplyState p ~ ApplyState (PrimOf p)) => Apply (RebaseFixup p) where     type ApplyState (RebaseFixup p) = ApplyState p     apply (PrimFixup p) = apply p     apply (NameFixup p) = apply p@@ -67,7 +67,7 @@     effect (PrimFixup p) = p :>: NilFL     effect (NameFixup p) = effect p -instance MyEq (PrimOf p) => MyEq (RebaseFixup p) where+instance Eq2 (PrimOf p) => Eq2 (RebaseFixup p) where     PrimFixup p1 `unsafeCompare` PrimFixup p2 = p1 `unsafeCompare` p2     PrimFixup _ `unsafeCompare` _ = False     _ `unsafeCompare` PrimFixup _ = False
src/Darcs/Patch/Rebase/Item.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, UndecidableInstances #-}+{-# LANGUAGE UndecidableInstances #-} module Darcs.Patch.Rebase.Item     ( RebaseItem(..)     , simplifyPush, simplifyPushes@@ -14,11 +14,14 @@ import Darcs.Patch.FileHunk ( IsHunk(..) ) import Darcs.Patch.Format ( PatchListFormat(..) ) import Darcs.Patch.Named ( Named(..), commuterIdNamed )-import Darcs.Patch.Patchy ( Invert(..), Commute(..), Apply(..)-                          , ShowPatch(..), ReadPatch(..)-                          , PatchInspect(..)-                          )-import Darcs.Patch.Prim ( PrimPatchBase, PrimOf, FromPrim(..), FromPrim(..), canonizeFL )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Invert ( Invert(..) )+import Darcs.Patch.Inspect ( PatchInspect(..) )+import Darcs.Patch.Read ( ReadPatch(..) )+import Darcs.Patch.Show ( ShowPatch(..) )+import Darcs.Patch.Prim+    ( PrimPatchBase, PrimOf, FromPrim(..), FromPrim(..), canonizeFL ) import Darcs.Patch.Rebase.Fixup ( RebaseFixup(..) ) import Darcs.Patch.Rebase.Name     ( RebaseName(..)@@ -27,6 +30,7 @@     ) import Darcs.Patch.Repair ( Check(..) ) import Darcs.Patch.Show ( ShowPatchBasic(..) )+import Darcs.Patch.Summary ( plainSummaryPrim ) import Darcs.Patch.ReadMonads ( ParserM, lexString ) import Darcs.Patch.Witnesses.Eq import Darcs.Patch.Witnesses.Ordered@@ -43,8 +47,6 @@ import qualified Data.ByteString as B ( ByteString ) import qualified Data.ByteString.Char8 as BC ( pack ) -#include "impossible.h"- -- |A single item in the rebase state consists of either -- a patch that is being edited, or a fixup that adjusts -- the context so that a subsequent patch that is being edited@@ -145,17 +147,16 @@ simplifyPushes _ NilFL ps = Sealed ps simplifyPushes da (f :>: fs) ps = unseal (simplifyPush da f) (simplifyPushes da fs ps) - instance (PrimPatchBase p, PatchListFormat p, ShowPatchBasic p) => ShowPatchBasic (RebaseItem p) where-   showPatch (ToEdit p) = blueText "rebase-toedit" <+> blueText "(" $$ showPatch p $$ blueText ")"-   showPatch (Fixup (PrimFixup p)) = blueText "rebase-fixup" <+> blueText "(" $$ showPatch p $$ blueText ")"-   showPatch (Fixup (NameFixup p)) = blueText "rebase-name" <+> blueText "(" $$ showPatch p $$ blueText ")"+   showPatch f (ToEdit p) = blueText "rebase-toedit" <+> blueText "(" $$ showPatch f p $$ blueText ")"+   showPatch f (Fixup (PrimFixup p)) = blueText "rebase-fixup" <+> blueText "(" $$ showPatch f p $$ blueText ")" where+   showPatch f (Fixup (NameFixup p)) = blueText "rebase-name" <+> blueText "(" $$ showPatch f p $$ blueText ")"  instance (PrimPatchBase p, PatchListFormat p, Apply p, CommuteNoConflicts p, Conflict p, IsHunk p, ShowPatch p)     => ShowPatch (RebaseItem p) where     summary (ToEdit p) = summary p-   summary (Fixup (PrimFixup p)) = summary p+   summary (Fixup (PrimFixup p)) = plainSummaryPrim p    summary (Fixup (NameFixup n)) = summary n    summaryFL ps = vcat (mapFL summary ps) -- TODO sort out summaries properly, considering expected conflicts 
src/Darcs/Patch/Rebase/Name.hs view
@@ -2,7 +2,6 @@ -- --  BSD3 -{-# LANGUAGE CPP #-} module Darcs.Patch.Rebase.Name     ( RebaseName(..)     , commuteNamePrim, commutePrimName@@ -18,15 +17,16 @@ import Darcs.Patch.Info ( PatchInfo, isInverted, showPatchInfo, readPatchInfo ) import Darcs.Patch.Inspect ( PatchInspect(..) ) import Darcs.Patch.Named ( Named(..) )-import Darcs.Patch.Patchy-    ( Invert(..), Commute(..), Patchy, Apply(..)-    , ShowPatch(..), ReadPatch(..)-    )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Invert ( Invert(..) )+import Darcs.Patch.Read ( ReadPatch(..) )+import Darcs.Patch.Show ( ShowPatch(..) ) import Darcs.Patch.Permutations ( inverseCommuter )-import Darcs.Patch.Prim ( PrimPatchBase, PrimOf )+import Darcs.Patch.Prim ( PrimPatchBase(..) ) import Darcs.Patch.ReadMonads ( lexString ) import Darcs.Patch.Show ( ShowPatchBasic(..) )-import Darcs.Patch.Witnesses.Eq ( MyEq(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..) ) import Darcs.Patch.Witnesses.Ordered ( (:>)(..), FL(..) ) import Darcs.Patch.Witnesses.Sealed ( Sealed(..) ) import Darcs.Patch.Witnesses.Show@@ -40,8 +40,6 @@ import Control.Applicative ( (<|>) ) import qualified Data.ByteString.Char8 as BC ( pack ) -#include "impossible.h"- -- Note: in principle this is a general concept not limited to -- rebase, and we might be able to generalise this type and -- refactor named patches to use it too.@@ -63,9 +61,9 @@     showDict2 = ShowDictClass  instance ShowPatchBasic (RebaseName p) where-   showPatch (AddName n) = blueText "addname" $$ showPatchInfo n-   showPatch (DelName n) = blueText "delname" $$ showPatchInfo n-   showPatch (Rename old new) = blueText "rename" $$ showPatchInfo old $$ showPatchInfo new+   showPatch f (AddName n) = blueText "addname" $$ showPatchInfo f n+   showPatch f (DelName n) = blueText "delname" $$ showPatchInfo f n+   showPatch f (Rename old new) = blueText "rename" $$ showPatchInfo f old $$ showPatchInfo f new  instance ShowPatch (RebaseName p) where    summary _ = empty -- TODO improve this?@@ -130,19 +128,17 @@     listTouchedFiles _ = []     hunkMatches _ _ = False -instance Apply p => Apply (RebaseName p) where+instance Apply (RebaseName p) where    type ApplyState (RebaseName p) = ApplyState p    apply _ = return () -instance Apply p => Patchy (RebaseName p)- instance PrimPatchBase p => PrimPatchBase (RebaseName p) where    type PrimOf (RebaseName p) = PrimOf p  instance Effect (RebaseName p) where    effect _ = unsafeCoerceP NilFL -instance MyEq (RebaseName p) where+instance Eq2 (RebaseName p) where    AddName n1 `unsafeCompare` AddName n2 = n1 == n2    AddName _ `unsafeCompare` _ = False    _ `unsafeCompare` AddName _ = False@@ -158,12 +154,12 @@  -- |Commute a name patch and a primitive patch. They trivially -- commute so this just involves changing the witnesses.-commuteNamePrim :: PrimPatchBase p => (RebaseName p :> PrimOf p) wX wY -> (PrimOf p :> RebaseName p) wX wY+commuteNamePrim :: (RebaseName p :> PrimOf p) wX wY -> (PrimOf p :> RebaseName p) wX wY commuteNamePrim (n :> f) = unsafeCoerceP f :> unsafeCoerceP n  -- |Commute a primitive patch and a name patch. They trivially -- commute so this just involves changing the witnesses.-commutePrimName :: PrimPatchBase p => (PrimOf p :> RebaseName p) wX wY -> (RebaseName p :> PrimOf p) wX wY+commutePrimName :: (PrimOf p :> RebaseName p) wX wY -> (RebaseName p :> PrimOf p) wX wY commutePrimName (f :> n) = unsafeCoerceP n :> unsafeCoerceP f  -- |Commute a name patch and a named patch. In most cases this is
src/Darcs/Patch/Rebase/Viewing.hs view
@@ -1,7 +1,7 @@ --  Copyright (C) 2009 Ganesh Sittampalam -- --  BSD3-{-# LANGUAGE CPP, GADTs, UndecidableInstances #-}+{-# LANGUAGE UndecidableInstances #-} module Darcs.Patch.Rebase.Viewing     ( RebaseSelect(..)     , toRebaseSelect, fromRebaseSelect, extractRebaseSelect, reifyRebaseSelect@@ -44,12 +44,14 @@     )  import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, n2pia )-import Darcs.Patch.Patchy ( Invert(..), Commute(..), Patchy, Apply(..),-                            ShowPatch(..), ReadPatch(..),-                            PatchInspect(..)-                          )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Invert ( Invert(..) )+import Darcs.Patch.Inspect ( PatchInspect(..) )+import Darcs.Patch.Read ( ReadPatch(..) )+import Darcs.Patch.Show ( ShowPatch(..) ) import Darcs.Patch.Prim-    ( PrimPatch, PrimPatchBase, PrimOf, FromPrim(..), FromPrims(..)+    ( PrimPatch, PrimPatchBase(..), FromPrim(..), FromPrims(..)     ) import Darcs.Patch.Rebase.Container ( Suspended(..) ) import Darcs.Patch.Rebase.Fixup@@ -60,7 +62,7 @@ import Darcs.Patch.Rebase.Item ( RebaseItem(..) ) import Darcs.Patch.Rebase.Name ( RebaseName(..) ) import Darcs.Patch.RepoType ( RepoType(..), RebaseType(..) )-import Darcs.Patch.Show ( ShowPatchBasic(..) )+import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatchFor(..), ShowContextPatch(..) ) import Darcs.Patch.Summary ( plainSummary ) import Darcs.Patch.Witnesses.Eq import Darcs.Patch.Witnesses.Ordered@@ -77,8 +79,6 @@ import Data.List ( nub, (\\) ) import Data.Maybe ( fromMaybe ) -#include "impossible.h"- -- |Encapsulate a single patch in the rebase state together with its fixups. -- Used during interactive selection to make sure that each item presented -- to the user corresponds to a patch.@@ -142,14 +142,6 @@ instance PrimPatchBase p => PrimPatchBase (RebaseSelect p) where    type PrimOf (RebaseSelect p) = PrimOf p -instance (PrimPatchBase p, PatchListFormat p, Conflict p, FromPrim p, Effect p, CommuteNoConflicts p, IsHunk p, Patchy p, ApplyState p ~ ApplyState (PrimOf p))-    => Patchy (RebaseSelect p)--instance ( PrimPatchBase p, Apply p, ApplyState p ~ ApplyState (PrimOf p)-         , Invert p-         )-        => Patchy (RebaseChange p)- instance PatchDebug p => PatchDebug (RebaseSelect p)  instance PatchDebug p => PatchDebug (RebaseChange p)@@ -168,7 +160,7 @@     apply (RCFwd fixups contents) = apply fixups >> apply contents     apply (RCRev fixups contents) = apply (invert contents) >> apply (invertFL fixups) -instance (PrimPatchBase p, FromPrim p, Conflict p, CommuteNoConflicts p, Invert p) => Conflict (RebaseSelect p) where+instance (PrimPatchBase p, Conflict p, CommuteNoConflicts p, Invert p) => Conflict (RebaseSelect p) where    resolveConflicts (RSFwd _ toedit) = resolveConflicts toedit    resolveConflicts (RSRev{}) = impossible @@ -227,14 +219,19 @@         invertRL . reverseFL . effect $ RCFwd fixups changes  instance (PrimPatchBase p, PatchListFormat p, ShowPatchBasic p) => ShowPatchBasic (RebaseSelect p) where-   showPatch (RSFwd fixups toedit) =-         showPatch (Items (mapFL_FL Fixup fixups +>+ ToEdit toedit :>: NilFL))-   showPatch (RSRev {}) = impossible+   showPatch f (RSFwd fixups toedit) =+         showPatch f (Items (mapFL_FL Fixup fixups +>+ ToEdit toedit :>: NilFL))+   showPatch _ (RSRev {}) = impossible -instance (PrimPatchBase p, PatchListFormat p, ShowPatchBasic p)+-- TODO this is a dummy instance that does not actually show context+instance (PrimPatchBase p, PatchListFormat p, ShowPatchBasic p) => ShowContextPatch (RebaseSelect p) where+   showContextPatch f p = return $ showPatch f p++instance (PrimPatchBase p, ShowPatchBasic p)       => ShowPatchBasic (RebaseChange p) where-    showPatch (RCFwd fixups contents) =-        vcat (mapFL showPatch contents) $$+    showPatch ForStorage _ = impossible+    showPatch ForDisplay (RCFwd fixups contents) =+        vcat (mapFL (showPatch ForDisplay) contents) $$         (if nullFL fixups             then empty             else@@ -244,9 +241,9 @@                 vcat (mapRL showFixup (invertFL fixups))         )         where-            showFixup (PrimFixup p) = showPatch p-            showFixup (NameFixup n) = showPatch n-    showPatch (RCRev {}) = impossible+            showFixup (PrimFixup p) = showPatch ForDisplay p+            showFixup (NameFixup n) = showPatch ForDisplay n+    showPatch _ (RCRev {}) = impossible  instance (PrimPatchBase p, PatchListFormat p, Apply p, CommuteNoConflicts p, Conflict p, IsHunk p, ShowPatch p)     => ShowPatch (RebaseSelect p) where@@ -267,8 +264,14 @@     summary = plainSummary     summaryFL = plainSummary +-- TODO this is a dummy instance that does not actually show context+instance+    ( PrimPatchBase p, ShowPatchBasic p)+   => ShowContextPatch (RebaseChange p) where -instance ReadPatch p => ReadPatch (RebaseSelect p) where+    showContextPatch f p = return $ showPatch f p++instance ReadPatch (RebaseSelect p) where    readPatch' = error "can't read RebaseSelect patches"  instance ReadPatch (RebaseChange p) where@@ -320,7 +323,7 @@     type PrimOf (RebaseChange p) = PrimOf p  -instance Invert p => Invert (RebaseSelect p) where+instance Invert (RebaseSelect p) where    invert (RSFwd fixups edit) = RSRev fixups edit    invert (RSRev fixups edit) = RSFwd fixups edit @@ -328,7 +331,7 @@    invert (RCFwd fixups contents) = RCRev fixups contents    invert (RCRev fixups contents) = RCFwd fixups contents -instance (PrimPatchBase p, Commute p, MyEq p) => MyEq (RebaseSelect p) where+instance (PrimPatchBase p, Commute p, Eq2 p) => Eq2 (RebaseSelect p) where    RSFwd fixups1 edit1 =\/= RSFwd fixups2 edit2       | IsEq <- fixups1 =\/= fixups2, IsEq <- edit1 =\/= edit2 = IsEq    RSRev fixups1 edit1 =\/= RSRev fixups2 edit2@@ -460,7 +463,7 @@       let newdeps = map (\dep -> if new == dep then old else dep) deps       in WithDroppedDeps (NamedP pn newdeps (unsafeCoerceP body)) ddeps :> Rename old new -forceCommutePrim :: (Commute p, Merge p, Invert p, Effect p, FromPrim p)+forceCommutePrim :: (Merge p, Invert p, Effect p, FromPrim p)                  => (PrimOf p :> WDDNamed p) wX wY                  -> (WDDNamed p :> FL (PrimOf p)) wX wY forceCommutePrim (p :> q) =@@ -468,7 +471,7 @@         q' :/\: invp' -> q' :> effect (invert invp')  -forceCommutesPrim :: (Commute p, Merge p, Invert p, Effect p, FromPrim p)+forceCommutesPrim :: (Merge p, Invert p, Effect p, FromPrim p)                   => (PrimOf p :> FL (WDDNamed p)) wX wY                   -> (FL (WDDNamed p) :> FL (PrimOf p)) wX wY forceCommutesPrim (p :> NilFL) = NilFL :> (p :>: NilFL)@@ -477,7 +480,7 @@         q' :> p' -> case forceCommutessPrim ( p' :> qs) of             qs' :> p'' -> (q' :>: qs') :> p'' -forceCommutessPrim :: (Commute p, Merge p, Invert p, Effect p, FromPrim p)+forceCommutessPrim :: (Merge p, Invert p, Effect p, FromPrim p)                    => (FL (PrimOf p) :> FL (WDDNamed p)) wX wY                    -> (FL (WDDNamed p) :> FL (PrimOf p)) wX wY forceCommutessPrim (NilFL :> qs) = qs :> NilFL@@ -487,7 +490,7 @@             case forceCommutesPrim (p :> qs') of                 qs'' :> p' -> qs'' :> (p' +>+ ps') -forceCommutess :: (Commute p, Merge p, Invert p, Effect p, FromPrim p)+forceCommutess :: (Merge p, Invert p, Effect p, FromPrim p)                => (FL (RebaseFixup p) :> FL (WDDNamed p)) wX wY                -> (FL (WDDNamed p) :> FL (RebaseFixup p)) wX wY forceCommutess (NilFL :> qs) = qs :> NilFL@@ -506,7 +509,7 @@ -- the main repository, together with residual fixups that need -- to go back into the rebase state (unless the rebase is now finished). -- Any fixups associated with the patch will turn into conflicts.-extractRebaseSelect :: (Commute p, Merge p, Invert p, Effect p, FromPrim p, PrimPatchBase p)+extractRebaseSelect :: (Merge p, Invert p, Effect p, FromPrim p, PrimPatchBase p)                     => FL (RebaseSelect p) wX wY                     -> (FL (WDDNamed p) :> FL (RebaseFixup p)) wX wY extractRebaseSelect NilFL = NilFL :> NilFL@@ -522,7 +525,7 @@ -- signature to be compatible with extractRebaseSelect -- | Like 'extractRebaseSelect', but any fixups are "reified" into a separate patch. reifyRebaseSelect :: forall p wX wY-                   . (PrimPatchBase p, Commute p, Merge p, Invert p, Effect p, FromPrim p)+                   . (PrimPatchBase p, FromPrim p)                   => FL (RebaseSelect p) wX wY                   -> IO ((FL (WDDNamed p) :> FL (RebaseFixup p)) wX wY) reifyRebaseSelect rs = do res <- concatFL <$> mapFL_FL_M reifyOne rs@@ -553,7 +556,7 @@ instance CommuteNoConflicts (RebaseChange p) where     commuteNoConflicts _ = impossible -instance IsHunk p => IsHunk (RebaseChange p) where+instance IsHunk (RebaseChange p) where     -- RebaseChange is a compound patch, so it doesn't really make sense to     -- ask whether it's a hunk. TODO: get rid of the need for this.     isHunk _ = Nothing
src/Darcs/Patch/RepoPatch.hs view
@@ -1,25 +1,27 @@ module Darcs.Patch.RepoPatch ( RepoPatch )     where +import Darcs.Patch.Annotate ( Annotate )+import Darcs.Patch.Apply ( Apply, ApplyState )+import Darcs.Patch.Commute ( Commute ) import Darcs.Patch.Conflict ( Conflict, CommuteNoConflicts ) import Darcs.Patch.Effect ( Effect ) import Darcs.Patch.FileHunk ( IsHunk ) import Darcs.Patch.Format ( PatchListFormat ) import Darcs.Patch.Inspect ( PatchInspect )+import Darcs.Patch.Invert ( Invert ) import Darcs.Patch.Matchable ( Matchable ) import Darcs.Patch.Merge ( Merge )-import Darcs.Patch.Patchy ( Patchy )-import Darcs.Patch.Patchy.Instances () import Darcs.Patch.Prim ( PrimPatchBase, PrimOf, FromPrim ) import Darcs.Patch.Read ( ReadPatch ) import Darcs.Patch.Repair ( RepairToFL, Check )-import Darcs.Patch.Show ( ShowPatch )+import Darcs.Patch.Show ( ShowPatch, ShowContextPatch ) -class (Patchy p, Merge p, Effect p, IsHunk p,-       PatchInspect p, ReadPatch p, ShowPatch p,+class (Apply p, Commute p, Invert p, Merge p, Effect p, IsHunk p,+       PatchInspect p, ReadPatch p, ShowPatch p, ShowContextPatch p,        FromPrim p, Conflict p, CommuteNoConflicts p,        Check p, RepairToFL p, PatchListFormat p,-       PrimPatchBase p, Patchy (PrimOf p), IsHunk (PrimOf p),-       Matchable p+       PrimPatchBase p, IsHunk (PrimOf p),+       Matchable p, Annotate p, ApplyState p ~ ApplyState (PrimOf p)       )     => RepoPatch p
src/Darcs/Patch/Set.hs view
@@ -15,7 +15,7 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, EmptyDataDecls, StandaloneDeriving #-}+{-# LANGUAGE EmptyDataDecls, StandaloneDeriving #-}  module Darcs.Patch.Set     ( PatchSet(..)@@ -26,8 +26,8 @@     , tags     , emptyPatchSet     , appendPSFL-    , newset2RL-    , newset2FL+    , patchSet2RL+    , patchSet2FL     , patchSetfMap     ) where @@ -89,18 +89,18 @@     showDict2 = ShowDictClass  --- |'newset2RL' takes a 'PatchSet' and returns an equivalent, linear 'RL' of+-- |'patchSet2RL' takes a 'PatchSet' and returns an equivalent, linear 'RL' of -- patches.-newset2RL :: PatchSet rt p wStart wX -> RL (PatchInfoAnd rt p) wStart wX-newset2RL (PatchSet ts ps) = concatRL (mapRL_RL ts2rl ts) +<+ ps+patchSet2RL :: PatchSet rt p wStart wX -> RL (PatchInfoAnd rt p) wStart wX+patchSet2RL (PatchSet ts ps) = concatRL (mapRL_RL ts2rl ts) +<+ ps   where     ts2rl :: Tagged rt p wY wZ -> RL (PatchInfoAnd rt p) wY wZ     ts2rl (Tagged t _ ps2) = ps2 :<: t --- |'newset2FL' takes a 'PatchSet' and returns an equivalent, linear 'FL' of+-- |'patchSet2FL' takes a 'PatchSet' and returns an equivalent, linear 'FL' of -- patches.-newset2FL :: PatchSet rt p wStart wX -> FL (PatchInfoAnd rt p) wStart wX-newset2FL = reverseRL . newset2RL+patchSet2FL :: PatchSet rt p wStart wX -> FL (PatchInfoAnd rt p) wStart wX+patchSet2FL = reverseRL . patchSet2RL  -- |'appendPSFL' takes a 'PatchSet' and a 'FL' of patches that "follow" the -- PatchSet, and concatenates the patches into the PatchSet.@@ -128,4 +128,4 @@     taggedTagInfo (Tagged t _ _) = info t  patchSetfMap:: (forall wW wZ . PatchInfoAnd rt p wW wZ -> IO a) -> PatchSet rt p wW' wZ' -> IO [a]-patchSetfMap f = sequence . mapRL f . newset2RL+patchSetfMap f = sequence . mapRL f . patchSet2RL
src/Darcs/Patch/Show.hs view
@@ -15,59 +15,59 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.Patch.Show      ( ShowPatchBasic(..)+     , displayPatch+     , ShowPatchFor(..)      , ShowPatch(..)-     , showNamedPrefix+     , ShowContextPatch(..)      , formatFileName      ) where  import Prelude () import Darcs.Prelude -import Prelude hiding ( pi )+import qualified Data.ByteString.Char8 as BC ( unpack )  import Darcs.Patch.Apply ( ApplyState ) import Darcs.Patch.ApplyMonad ( ApplyMonad ) import Darcs.Patch.Format ( FileNameFormat(..) )-import Darcs.Patch.Info ( PatchInfo, showPatchInfo )-import Darcs.Patch.Witnesses.Ordered ( FL )+import Darcs.Patch.Witnesses.Ordered ( FL, mapFL ) +import Darcs.Util.ByteString ( packStringToUTF8, encodeLocale ) import Darcs.Util.English ( plural, Noun(Noun) )-import Darcs.Util.Path ( FileName, fn2ps, encodeWhite, fn2fp )-import Darcs.Util.Printer ( Doc, vcat, blueText, ($$), text, packedString )+import Darcs.Util.Path ( FileName, encodeWhite, fn2fp )+import Darcs.Util.Printer ( Doc, vcat, text, packedString ) -showNamedPrefix :: PatchInfo -> [PatchInfo] -> Doc-showNamedPrefix n d = showPatchInfo n-                      $$ blueText "<"-                      $$ vcat (map showPatchInfo d)-                      $$ blueText ">"+data ShowPatchFor = ForDisplay | ForStorage -class ShowPatchBasic p where-    showPatch :: p wX wY -> Doc+displayPatch :: ShowPatchBasic p => p wX wY -> Doc+displayPatch p = showPatch ForDisplay p -class ShowPatchBasic p => ShowPatch p where-    showNicely :: p wX wY -> Doc-    showNicely = showPatch+class ShowPatchBasic p where+    showPatch :: ShowPatchFor -> p wX wY -> Doc +class ShowPatchBasic p => ShowContextPatch p where     -- | showContextPatch is used to add context to a patch, as diff     -- -u does. Thus, it differs from showPatch only for hunks. It is     -- used for instance before putting it into a bundle. As this     -- unified context is not included in patch representation, this     -- requires access to the tree.-    showContextPatch :: (Monad m,-                         ApplyMonad (ApplyState p) m)-                     => p wX wY -> m Doc-    showContextPatch p = return $ showPatch p+    showContextPatch :: (ApplyMonad (ApplyState p) m)+                     => ShowPatchFor -> p wX wY -> m Doc +-- This class is used only for user interaction, not for storage+class ShowPatchBasic p => ShowPatch p where+    showNicely :: p wX wY -> Doc+    showNicely = showPatch ForDisplay+     description :: p wX wY -> Doc-    description = showPatch+    description = showPatch ForDisplay      summary :: p wX wY -> Doc      summaryFL :: FL p wX wY -> Doc+    summaryFL = vcat . mapFL summary      thing :: p wX wY -> String     thing _ = "patch"@@ -75,6 +75,19 @@     things :: p wX wY -> String     things x = plural (Noun $ thing x) "" +-- | Format a 'FileName' to a 'Doc' according to the given 'FileNameFormat'.+--+-- NOTE: This is not only used for display but also to format patch files. This is+--       why we have to do the white space encoding here.+--       See 'Darcs.Repository.Hashed.writePatchIfNecessary'.+--+-- Besides white space encoding, for 'NewFormat' we just pack it into a 'Doc'. For+-- 'OldFormat' we must emulate the non-standard darcs-1 encoding of file paths: it+-- is an UTF8 encoding of the raw byte stream, interpreted as code points.+--+-- See also 'Darcs.Patch.Show.readFileName'. formatFileName :: FileNameFormat -> FileName -> Doc-formatFileName OldFormat = packedString . fn2ps+formatFileName OldFormat = packedString . packStringToUTF8 . BC.unpack .+                            encodeLocale . encodeWhite . fn2fp formatFileName NewFormat = text . encodeWhite . fn2fp+formatFileName UserFormat = text . fn2fp
src/Darcs/Patch/Split.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP, RankNTypes, GADTs, ViewPatterns #-}+{-# LANGUAGE ViewPatterns #-} {-# OPTIONS_GHC -fno-warn-unused-imports #-} -- Copyright (C) 2009 Ganesh Sittampalam --@@ -22,7 +22,13 @@ -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. -module Darcs.Patch.Split ( Splitter(..), rawSplitter, noSplitter, primSplitter, reversePrimSplitter ) where+module Darcs.Patch.Split+    ( Splitter(..)+    , rawSplitter+    , noSplitter+    , primSplitter+    , reversePrimSplitter+    ) where  import Prelude () import Darcs.Prelude@@ -33,14 +39,16 @@ import Darcs.Patch.Witnesses.Sealed  import Darcs.Patch.FileHunk ( FileHunk(..), IsHunk(..) )-import Darcs.Patch.Patchy ( ReadPatch(..), showPatch, ShowPatch(..), Invert(..) )-import Darcs.Patch.Invert (invertFL)+import Darcs.Patch.Read ( ReadPatch(..) )+import Darcs.Patch.Show ( showPatch, ShowPatch(..) )+import Darcs.Patch.Invert( Invert(..), invertFL ) import Darcs.Patch.Prim ( PrimPatch, canonize, canonizeFL, primFromHunk ) import Darcs.Patch.ReadMonads ( parseStrictly ) import Darcs.Patch.Read ()+import Darcs.Patch.Show ( ShowPatchFor(ForDisplay) ) import Darcs.Patch.Viewing () -import Darcs.Util.Printer ( renderPS, RenderMode(..) )+import Darcs.Util.Printer ( renderPS ) import qualified Darcs.Util.Diff as D ( DiffAlgorithm )  import qualified Data.ByteString as B@@ -63,23 +71,20 @@ -- Prim (you shouldn't go editing named patches, you'll break them!) -- However you might want to compose splitters for FilePatchType to make -- splitters for Prim etc, and the generality doesn't cost anything.-data Splitter p-  = Splitter {-              applySplitter :: forall wX wY . p wX wY-                              -> Maybe (B.ByteString,-                                        B.ByteString -> Maybe (FL p wX wY))-              -- canonization is needed to undo the effects of splitting-              -- Typically, the list returned by applySplitter will not-              -- be in the simplest possible form (since the user will have-              -- deliberately added extra stuff). Once the user has selected-              -- the pieces they want, we need to make sure that we eliminate-              -- any remaining redundancy in the selected pieces, otherwise-              -- we might record (or whatever) a rather strange looking patch.-              -- This hook allows the splitter to provide an appropriate-              -- function for doing this.-             ,canonizeSplit :: forall wX wY . FL p wX wY-                              -> FL p wX wY-             }+data Splitter p = Splitter+    { applySplitter :: forall wX wY. p wX wY+                    -> Maybe (B.ByteString, B.ByteString -> Maybe (FL p wX wY))+      -- canonization is needed to undo the effects of splitting+      -- Typically, the list returned by applySplitter will not+      -- be in the simplest possible form (since the user will have+      -- deliberately added extra stuff). Once the user has selected+      -- the pieces they want, we need to make sure that we eliminate+      -- any remaining redundancy in the selected pieces, otherwise+      -- we might record (or whatever) a rather strange looking patch.+      -- This hook allows the splitter to provide an appropriate+      -- function for doing this.+    , canonizeSplit :: forall wX wY. FL p wX wY -> FL p wX wY+    }  {- Some facts that probably ought to be true about splitters: should make some QC properties@@ -94,22 +99,21 @@ withEditedHead :: Invert p => p wX wY -> p wX wZ -> FL p wX wY withEditedHead p res = res :>: invert res :>: p :>: NilFL --- |This generic splitter just lets the user edit the printed representation of the patch--- Should not be used expect for testing and experimentation.+-- |This generic splitter just lets the user edit the printed representation of the+-- patch. Should not be used expect for testing and experimentation. rawSplitter :: (ShowPatch p, ReadPatch p, Invert p) => Splitter p-rawSplitter = Splitter {-                  applySplitter =-                     \p -> Just (renderPS Standard . showPatch $ p,-                                 \str -> case parseStrictly readPatch' str of-                                          Just (Sealed res, _) -> Just (withEditedHead p res)-                                          _ -> Nothing-                                )-                 ,canonizeSplit = id-                }+rawSplitter = Splitter+    { applySplitter = \p ->+        Just (renderPS . showPatch ForDisplay $ p+             ,\str -> case parseStrictly readPatch' str of+                        Just (Sealed res, _) -> Just (withEditedHead p res)+                        _                    -> Nothing)+    , canonizeSplit = id+    } --- |Never splits. In other code we normally pass around Maybe Splitter instead of using this--- as the default, because it saves clients that don't care about splitting from having to--- import this module just to get noSplitter.+-- |Never splits. In other code we normally pass around Maybe Splitter instead+-- of using this as the default, because it saves clients that don't care about+-- splitting from having to import this module just to get noSplitter. noSplitter :: Splitter p noSplitter = Splitter { applySplitter = const Nothing, canonizeSplit = id } @@ -118,16 +122,17 @@             -> Maybe (B.ByteString, B.ByteString -> Maybe (FL prim wX wY)) doPrimSplit da = doPrimSplit_ da True explanation   where-    explanation = map BC.pack-                   [ "Interactive hunk edit:"-                   , " - Edit the section marked 'AFTER'"-                   , " - Arbitrary editing is supported"-                   , " - This will only affect the patch, not your working tree"-                   , " - Hints:"-                   , "   - To split added text, delete the part you want to postpone"-                   , "   - To split removed text, copy back the part you want to retain"-                   , ""-                   ]+    explanation =+      map BC.pack+        [ "Interactive hunk edit:"+        , " - Edit the section marked 'AFTER'"+        , " - Arbitrary editing is supported"+        , " - This will only affect the patch, not your working tree"+        , " - Hints:"+        , "   - To split added text, delete the part you want to postpone"+        , "   - To split removed text, copy back the part you want to retain"+        , ""+        ]  doPrimSplit_ :: (PrimPatch prim, IsHunk p)              => D.DiffAlgorithm@@ -161,9 +166,8 @@                            (ys, _:zs) -> Just (ys, zs) doPrimSplit_ _ _ _ _ = Nothing --- |Split a primitive hunk patch up--- by allowing the user to edit both the before and after lines, then insert fixup patches--- to clean up the mess.+-- |Split a primitive hunk patch up by allowing the user to edit both the+-- before and after lines, then insert fixup patches to clean up the mess. primSplitter :: PrimPatch p => D.DiffAlgorithm -> Splitter p primSplitter da = Splitter { applySplitter = doPrimSplit da                            , canonizeSplit = canonizeFL da }@@ -178,16 +182,17 @@   return (text, parser')   where     reverseExplanation =-      map BC.pack [ "Interactive hunk edit:"-                  , " - Edit the section marked 'AFTER' (representing the state to which you'll revert)"-                  , " - Arbitrary editing is supported"-                  , " - Your working tree will be returned to the 'AFTER' state"-                  , " - Do not touch the 'BEFORE' section"-                  , " - Hints:"-                  , "   - To revert only a part of a text addition, delete the part you want to get rid of"-                  , "   - To revert only a part of a removal, copy back the part you want to retain"-                  , ""-                                 ]+      map BC.pack+        [ "Interactive hunk edit:"+        , " - Edit the section marked 'AFTER' (representing the state to which you'll revert)"+        , " - Arbitrary editing is supported"+        , " - Your working tree will be returned to the 'AFTER' state"+        , " - Do not touch the 'BEFORE' section"+        , " - Hints:"+        , "   - To revert only a part of a text addition, delete the part you want to get rid of"+        , "   - To revert only a part of a removal, copy back the part you want to retain"+        , ""+        ]  reversePrimSplitter :: PrimPatch prim => D.DiffAlgorithm -> Splitter prim reversePrimSplitter da = Splitter { applySplitter = doReversePrimSplit da
src/Darcs/Patch/Summary.hs view
@@ -6,10 +6,11 @@ import Prelude () import Darcs.Prelude -import Darcs.Util.Path ( fn2fp, FileName )+import Darcs.Util.Path ( fn2fp ) import Darcs.Patch.Conflict ( Conflict(..), IsConflictedPrim(IsC), ConflictState(..) )-import Darcs.Patch.Effect ( Effect )+import Darcs.Patch.Format ( FileNameFormat(UserFormat) ) import Darcs.Patch.Prim.Class ( PrimDetails(..), PrimPatchBase )+import Darcs.Patch.Show ( formatFileName ) import Darcs.Patch.SummaryData ( SummDetail(..), SummOp(..) ) import Darcs.Patch.Witnesses.Ordered ( FL, mapFL ) @@ -22,18 +23,14 @@ plainSummaryPrim :: PrimDetails prim => prim wX wY -> Doc plainSummaryPrim = vcat . map (summChunkToLine False) . genSummary . (:[]) . IsC Okay -plainSummaryPrims :: PrimDetails prim => Bool -> [FileName] -> FL prim wX wY -> Doc-plainSummaryPrims machineReadable conflicting =- vcat . map (summChunkToLine machineReadable . markConflict) . genSummary . mapFL (IsC Okay)- where-    markConflict (SummChunk sf@(SummFile _ sfFn _ _ _) _)-      | sfFn `elem` conflicting = SummChunk sf Conflicted-    markConflict sc = sc+plainSummaryPrims :: PrimDetails prim => Bool -> FL prim wX wY -> Doc+plainSummaryPrims machineReadable =+ vcat . map (summChunkToLine machineReadable) . genSummary . mapFL (IsC Okay) -plainSummary :: (Conflict e, Effect e, PrimPatchBase e) => e wX wY -> Doc+plainSummary :: (Conflict e, PrimPatchBase e) => e wX wY -> Doc plainSummary = vcat . map (summChunkToLine False) . genSummary . conflictedEffect -xmlSummary :: (Effect p, Conflict p, PrimPatchBase p) => p wX wY -> Doc+xmlSummary :: (Conflict p, PrimPatchBase p) => p wX wY -> Doc xmlSummary p = text "<summary>"              $$ (vcat . map summChunkToXML . genSummary . conflictedEffect $ p)              $$ text "</summary>"@@ -62,7 +59,7 @@           combine (x1@(SummChunk d1 c1) : x2@(SummChunk d2 c2) : ss)               = case combineDetail d1 d2 of                   Nothing -> x1 : combine (x2:ss)-                  Just d3 -> combine $ SummChunk d3 (combineConflitStates c1 c2) : ss+                  Just d3 -> combine $ SummChunk d3 (combineConflictStates c1 c2) : ss           combine (x:ss) = x  : combine ss           combine [] = []           --@@ -71,11 +68,11 @@                return $ SummFile o3 f1 (r1 + r2) (a1 + a2) (x1 + x2)           combineDetail _ _ = Nothing           ---          combineConflitStates Conflicted _ = Conflicted-          combineConflitStates _ Conflicted = Conflicted-          combineConflitStates Duplicated _ = Duplicated-          combineConflitStates _ Duplicated = Duplicated-          combineConflitStates Okay Okay = Okay+          combineConflictStates Conflicted _ = Conflicted+          combineConflictStates _ Conflicted = Conflicted+          combineConflictStates Duplicated _ = Duplicated+          combineConflictStates _ Duplicated = Duplicated+          combineConflictStates Okay Okay = Okay           -- Don't combine AddFile and RmFile: (maybe an old revision of) darcs           -- allows a single patch to add and remove the same file, see issue 185           combineOp SummAdd SummRm  = Nothing@@ -101,7 +98,7 @@    xconf Okay t x       = text ('<':t++">") $$ x $$ text ("</"++t++">")    xconf Conflicted t x = text ('<':t++" conflict='true'>") $$ x $$ text ("</"++t++">")    xconf Duplicated t x = text ('<':t++" duplicate='true'>") $$ x $$ text ("</"++t++">")-   xfn = escapeXML . dropDotSlash .fn2fp+   xfn = escapeXML . dropDotSlash . fn2fp    --    xad 0 = empty    xad a = text "<added_lines num='" <> text (show a) <> text "'/>"@@ -113,18 +110,18 @@ summChunkToLine :: Bool -> SummChunk -> Doc summChunkToLine machineReadable (SummChunk detail c) =   case detail of-   SummRmDir f   -> lconf c "R" $ text (fn2fp f) <> text "/"-   SummAddDir f  -> lconf c "A" $ text (fn2fp f) <> text "/"-   SummFile SummRm  f _ _ _ -> lconf c "R" $ text (fn2fp f)-   SummFile SummAdd f _ _ _ -> lconf c "A" $ text (fn2fp f)+   SummRmDir f   -> lconf c "R" $ formatFileName UserFormat f <> text "/"+   SummAddDir f  -> lconf c "A" $ formatFileName UserFormat f <> text "/"+   SummFile SummRm  f _ _ _ -> lconf c "R" $ formatFileName UserFormat f+   SummFile SummAdd f _ _ _ -> lconf c "A" $ formatFileName UserFormat f    SummFile SummMod f r a x-     | machineReadable -> lconf c "M" $ text (fn2fp f)-     | otherwise       -> lconf c "M" $ text (fn2fp f) <+> rm r <+> ad a <+> rp x+     | machineReadable -> lconf c "M" $ formatFileName UserFormat f+     | otherwise       -> lconf c "M" $ formatFileName UserFormat f <+> rm r <+> ad a <+> rp x    SummMv f1 f2-     | machineReadable -> text "F " <> text (fn2fp f1)-                       $$ text "T " <> text (fn2fp f2)-     | otherwise       -> text " "    <> text (fn2fp f1)-                       <> text " -> " <> text (fn2fp f2)+     | machineReadable -> text "F " <> formatFileName UserFormat f1+                       $$ text "T " <> formatFileName UserFormat f2+     | otherwise       -> text " "    <> formatFileName UserFormat f1+                       <> text " -> " <> formatFileName UserFormat f2    SummNone -> case c of                Okay -> empty                _    -> lconf c ""  empty
src/Darcs/Patch/TokenReplace.hs view
@@ -1,8 +1,7 @@ module Darcs.Patch.TokenReplace-    (-      tryTokInternal+    ( tryTokReplace     , forceTokReplace-    , breakOutToken+    , annotateReplace     , breakToTokens     , defaultToks     ) where@@ -12,61 +11,91 @@  import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as BC-import Data.Maybe ( isNothing ) -import Darcs.Util.ByteString ( substrPS, linesPS, unlinesPS ) import Darcs.Patch.RegChars ( regChars ) --- | breakOutToken takes a String of token chars and an input ByteString, and--- returns the ByteString triple of (beforeToken, token, afterToken).+-- | @breakOutToken tokChars input@ splits the @input@ 'ByteString' into+-- @'Just' (before, token, after)@, where @token@ is the first non-empty+-- substring consisting only of 'Char's in @tokChars@, or 'Nothing' if no token+-- was found. The 'Char's in @tokChars@ should not have code points larger than+-- 255 (0xff). breakOutToken :: String -> BC.ByteString-              -> (BC.ByteString, BC.ByteString, BC.ByteString)-breakOutToken tokChars input =-    let isTokChar = regChars tokChars-        (before, tokAndRest) = BC.break isTokChar input-        (tok, remaining) = BC.break (not . isTokChar) tokAndRest in-    (before, tok, remaining)---- | tryTokInternal takes a String of token chars, an oldToken ByteString, a--- newToken ByteString and returns the list of token-delimited ByteStrings,--- with any tokens matching oldToken being replaced by newToken. If newToken is--- already in the input, we return Nothing.-tryTokInternal :: String -> B.ByteString -> B.ByteString -> B.ByteString-               -> Maybe [B.ByteString]-tryTokInternal _ oldToken newToken input-  | isNothing (substrPS oldToken input) &&-    isNothing (substrPS newToken input) = Just [ input ]-tryTokInternal tokChars oldToken newToken input =-    let (before, tok, remaining) = breakOutToken tokChars input in-    case tryTokInternal tokChars oldToken newToken remaining of-        Nothing -> Nothing-        Just rest | tok == oldToken -> Just $ before : newToken : rest-                  | tok == newToken -> Nothing-                  | otherwise -> Just $ before : tok : rest---- | forceTokReplace replaces all occurrences of the old token with the new--- token, throughout the input ByteString.-forceTokReplace :: String -> B.ByteString -> B.ByteString -> B.ByteString-                -> B.ByteString-forceTokReplace tokChars oldToken newToken = forceReplaceLines+              -> Maybe (BC.ByteString, BC.ByteString, BC.ByteString)+breakOutToken tokChars input+  | not (B.null tok) = Just (before, tok, remaining)+  | otherwise = Nothing   where-    forceReplaceLines = unlinesPS . map forceReplace . linesPS-    breakOutAllTokens input | B.null input = []-    breakOutAllTokens input =-        let (before, tok, remaining) = breakOutToken tokChars input in-        before : tok : breakOutAllTokens remaining+    isTokChar = regChars tokChars+    (before, tokAndRest) = BC.break isTokChar input+    (tok, remaining) = BC.break (not . isTokChar) tokAndRest -    forceReplace = B.concat . map replaceMatchingToken . breakOutAllTokens+-- | @tryTokReplace tokChars old new input@ tries to find the token @old@ and+-- replace it with the token @new@ everywhere in the @input@, returning 'Just'+-- the modified @input@, unless the token @new@ is already in the @input@ in+-- which case 'Nothing' is returned. A token is a sequence of bytes that match+-- the class defined by @tokChars@. This function is supposed to work+-- efficiently with large @input@s i.e. whole files.+tryTokReplace :: String -> B.ByteString -> B.ByteString+              -> B.ByteString -> Maybe B.ByteString+tryTokReplace tokChars old new+  | B.null old = bug "tryTokInternal called with empty old token"+  | BC.any (not . isTokChar) old = bug "tryTokInternal called with old non-token"+  | BC.any (not . isTokChar) new = bug "tryTokInternal called with new non-token"+  | otherwise = fmap B.concat . loop 0+    where+      isTokChar = regChars tokChars+      loop !from input =+        case BC.findIndex isTokChar (B.drop from input) of+          Nothing -> Just [input]+          Just start ->+            case BC.span isTokChar (B.drop (from + start) input) of+              (tok, rest)+                | tok == old ->+                    (B.take (from + start) input :).(new :) <$> loop 0 rest+                | tok == new -> Nothing+                | otherwise ->+                    loop (from + start + B.length tok) input -    replaceMatchingToken input | input == oldToken = newToken-                               | otherwise = input+-- | @forceTokReplace tokChars old new input@ replaces all occurrences of+-- the @old@ token with the @new@ one, throughout the @input@.+forceTokReplace :: String -> B.ByteString -> B.ByteString+                -> B.ByteString -> B.ByteString+forceTokReplace tokChars old new+  | B.null old = bug "tryTokInternal called with empty old token"+  | BC.any (not . isTokChar) old = bug "tryTokInternal called with old non-token"+  | BC.any (not . isTokChar) new = bug "tryTokInternal called with new non-token"+  | otherwise = B.concat . loop 0+    where+      isTokChar = regChars tokChars+      len = B.length old+      loop !from input =+        case B.breakSubstring old (B.drop from input) of+          (before, match)+            | B.null match -> [input] -- not found+            | B.null before || not (isTokChar (BC.last before))+            , B.length match == len || not (isTokChar (BC.index match len)) ->+                -- found and is token+                B.take (from + B.length before) input : new :+                  loop 0 (B.drop len match)+            | otherwise ->+                -- found but not a token+                loop (from + B.length before + len) input --- break a single bytestring into tokens+-- | Check if a token replace operation touches the given line.+annotateReplace :: String -> B.ByteString -> B.ByteString -> B.ByteString -> Bool+annotateReplace tokChars old new input =+  case breakOutToken tokChars input of+    Just (_, tok, remaining) ->+      (tok == old || annotateReplace tokChars old new remaining)+    Nothing -> False++-- | Break a 'Bytestring' into tokens, according to 'defaultToks',+-- discarding non-tokens. breakToTokens :: BC.ByteString -> [BC.ByteString]-breakToTokens input | B.null input = [] breakToTokens input =-  let (_, tok, remaining) = breakOutToken defaultToks input in-    tok : breakToTokens remaining+  case breakOutToken defaultToks input of+    Nothing -> []+    Just (_, tok, remaining) -> tok : breakToTokens remaining  defaultToks :: String defaultToks = "A-Za-z_0-9"
src/Darcs/Patch/TouchesFiles.hs view
@@ -15,98 +15,122 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}---module Darcs.Patch.TouchesFiles ( lookTouch, chooseTouching, choosePreTouching,-                      selectTouching,-                      deselectNotTouching, selectNotTouching,-                    ) where+module Darcs.Patch.TouchesFiles+    ( lookTouch+    , chooseTouching+    , choosePreTouching+    , selectTouching+    , deselectNotTouching+    , selectNotTouching+    ) where -import Prelude () import Darcs.Prelude+import Prelude () -import Data.List ( isSuffixOf, nub )+import Data.List (isSuffixOf, nub) -import Darcs.Patch.Choices ( PatchChoices, Label, LabelledPatch,-                             patchChoices, label, getChoices,-                      forceFirsts, forceLasts, lpPatch,-                    )-import Darcs.Patch ( Patchy, invert )-import Darcs.Patch.Apply ( ApplyState, applyToFilePaths, effectOnFilePaths )-import Darcs.Patch.Inspect ( PatchInspect )-import Darcs.Patch.Witnesses.Ordered ( FL(..), (:>)(..), mapFL_FL, (+>+) )-import Darcs.Patch.Witnesses.Sealed ( Sealed, seal )-import Darcs.Util.Tree( Tree )+import Darcs.Patch.Apply+       (Apply, ApplyState, applyToFilePaths, effectOnFilePaths)+import Darcs.Patch.Choices+       (PatchChoices, Label, LabelledPatch, patchChoices, label,+        getChoices, forceFirsts, forceLasts, unLabel)+import Darcs.Patch.Commute (Commute)+import Darcs.Patch.Inspect (PatchInspect)+import Darcs.Patch.Invert (invert, Invert)+import Darcs.Patch.Witnesses.Ordered+       (FL(..), (:>)(..), mapFL_FL, (+>+))+import Darcs.Patch.Witnesses.Sealed (Sealed, seal)+import Darcs.Util.Tree (Tree) -labelTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree) => Bool-            -> [FilePath] -> FL (LabelledPatch p) wX wY -> [Label]+labelTouching+  :: (Apply p, PatchInspect p, ApplyState p ~ Tree)+  => Bool -> [FilePath] -> FL (LabelledPatch p) wX wY -> [Label] labelTouching _ _ NilFL = [] labelTouching wantTouching fs (lp :>: lps) =-    case lookTouchOnlyEffect fs (lpPatch lp) of-        (doesTouch, fs') ->-            let rest = labelTouching wantTouching fs' lps-            in (if doesTouch == wantTouching then (label lp :) else id) rest+  case lookTouchOnlyEffect fs (unLabel lp) of+    (doesTouch, fs') ->+      let rest = labelTouching wantTouching fs' lps+      in (if doesTouch == wantTouching+            then (label lp :)+            else id)+           rest -labelNotTouchingFM :: (PatchInspect p, Patchy p, ApplyState p ~ Tree)-                 => [FilePath] -> PatchChoices p wX wY -> [Label]-labelNotTouchingFM files pc = case getChoices pc of+labelNotTouchingFM+  :: (Apply p, Commute p, PatchInspect p, ApplyState p ~ Tree)+  => [FilePath] -> PatchChoices p wX wY -> [Label]+labelNotTouchingFM files pc =+  case getChoices pc of     fc :> mc :> _ -> labelTouching False (map fix files) (fc +>+ mc) -selectTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree)-               => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY+selectTouching+  :: (Apply p, Commute p, PatchInspect p, ApplyState p ~ Tree)+  => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY selectTouching Nothing pc = pc selectTouching (Just files) pc = forceFirsts xs pc-    where xs = case getChoices pc of-               _ :> mc :> lc -> labelTouching True (map fix files) (mc +>+ lc)+  where+    xs =+      case getChoices pc of+        _ :> mc :> lc -> labelTouching True (map fix files) (mc +>+ lc) -deselectNotTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree)-                    => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY+deselectNotTouching+  :: (Apply p, Commute p, PatchInspect p, ApplyState p ~ Tree)+  => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY deselectNotTouching Nothing pc = pc-deselectNotTouching (Just files) pc = forceLasts (labelNotTouchingFM files pc) pc+deselectNotTouching (Just files) pc =+  forceLasts (labelNotTouchingFM files pc) pc -selectNotTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree)-                  => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY+selectNotTouching+  :: (Apply p, Commute p, PatchInspect p, ApplyState p ~ Tree)+  => Maybe [FilePath] -> PatchChoices p wX wY -> PatchChoices p wX wY selectNotTouching Nothing pc = pc selectNotTouching (Just files) pc = forceFirsts (labelNotTouchingFM files pc) pc  fix :: FilePath -> FilePath-fix f | "/" `isSuffixOf` f = fix $ init f+fix f+  | "/" `isSuffixOf` f = fix $ init f fix "" = "." fix "." = "." fix f = "./" ++ f -chooseTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree)-               => Maybe [FilePath] -> FL p wX wY -> Sealed (FL p wX)+chooseTouching+  :: (Apply p, Commute p, PatchInspect p, ApplyState p ~ Tree)+  => Maybe [FilePath] -> FL p wX wY -> Sealed (FL p wX) chooseTouching Nothing p = seal p-chooseTouching files p = case getChoices $ selectTouching files $ patchChoices p of-                          fc :> _ :> _ -> seal $ mapFL_FL lpPatch fc+chooseTouching files p =+  case getChoices $ selectTouching files $ patchChoices p of+    fc :> _ :> _ -> seal $ mapFL_FL unLabel fc -choosePreTouching :: (Patchy p, PatchInspect p, ApplyState p ~ Tree)-                  => Maybe [FilePath] -> FL p wX wY -> Sealed (FL p wX)-choosePreTouching files patch = chooseTouching filesBeforePatch patch where+choosePreTouching+  :: (Apply p, Commute p, Invert p, PatchInspect p, ApplyState p ~ Tree)+  => Maybe [FilePath] -> FL p wX wY -> Sealed (FL p wX)+choosePreTouching files patch = chooseTouching filesBeforePatch patch+  where     filesBeforePatch = effectOnFilePaths (invert patch) <$> files -lookTouchOnlyEffect :: (Patchy p, PatchInspect p, ApplyState p ~ Tree) => [FilePath] -> p wX wY-    -> (Bool, [FilePath])-lookTouchOnlyEffect fs p = (wasTouched, fs') where+lookTouchOnlyEffect+  :: (Apply p, ApplyState p ~ Tree)+  => [FilePath] -> p wX wY -> (Bool, [FilePath])+lookTouchOnlyEffect fs p = (wasTouched, fs')+  where     (wasTouched, _, fs', _) = lookTouch Nothing fs p --lookTouch :: (Patchy p, PatchInspect p, ApplyState p ~ Tree) => Maybe [(FilePath, FilePath)]-    -> [FilePath] -> p wX wY-    -> (Bool, [FilePath], [FilePath], [(FilePath, FilePath)])+lookTouch+  :: (Apply p, ApplyState p ~ Tree)+  => Maybe [(FilePath, FilePath)]+  -> [FilePath]+  -> p wX wY+  -> (Bool, [FilePath], [FilePath], [(FilePath, FilePath)]) lookTouch renames fs p = (anyTouched, touchedFs, fs', renames')-    where-          touchedFs = nub . concatMap fsAffectedBy $ affected-          fsAffectedBy af = filter (affectedBy af) fs-          anyTouched = length touchedFs > 0-          affectedBy :: FilePath -> FilePath -> Bool-          touched `affectedBy` f =  touched == f-                                 || touched `isSubPathOf` f-                                 || f `isSubPathOf` touched-          isSubPathOf :: FilePath -> FilePath -> Bool-          path `isSubPathOf` parent = case splitAt (length parent) path of-                                 (path', '/':_) -> path' == parent-                                 _ -> False-          (affected, fs', renames') = applyToFilePaths p renames fs+  where+    touchedFs = nub . concatMap fsAffectedBy $ affected+    fsAffectedBy af = filter (affectedBy af) fs+    anyTouched = length touchedFs > 0+    affectedBy :: FilePath -> FilePath -> Bool+    touched `affectedBy` f =+      touched == f || touched `isSubPathOf` f || f `isSubPathOf` touched+    isSubPathOf :: FilePath -> FilePath -> Bool+    path `isSubPathOf` parent =+      case splitAt (length parent) path of+        (path', '/':_) -> path' == parent+        _ -> False+    (affected, fs', renames') = applyToFilePaths p renames fs
src/Darcs/Patch/V1.hs view
@@ -1,8 +1,8 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module Darcs.Patch.V1 ( RepoPatchV1 ) where +import Darcs.Patch.Annotate ( Annotate ) import Darcs.Patch.Matchable ( Matchable )-import Darcs.Patch.Patchy ( Patchy ) import Darcs.Patch.Prim ( PrimPatch ) import Darcs.Patch.RepoPatch ( RepoPatch ) @@ -13,6 +13,5 @@ import Darcs.Patch.V1.Show () import Darcs.Patch.V1.Viewing () -instance PrimPatch prim => Patchy    (RepoPatchV1 prim) instance PrimPatch prim => Matchable (RepoPatchV1 prim)-instance PrimPatch prim => RepoPatch (RepoPatchV1 prim)+instance (PrimPatch prim, Annotate prim) => RepoPatch (RepoPatchV1 prim)
src/Darcs/Patch/V1/Apply.hs view
@@ -4,6 +4,7 @@ import Prelude () import Darcs.Prelude +import Darcs.Patch.Annotate ( Annotate(..) ) import Darcs.Patch.Apply ( ApplyState, Apply, apply ) import Darcs.Patch.Prim ( PrimPatch, applyPrimFL ) import Darcs.Patch.Repair ( RepairToFL, applyAndTryToFixFL,@@ -12,7 +13,6 @@  import Darcs.Patch.V1.Commute () import Darcs.Patch.V1.Core ( RepoPatchV1(..) )- import Darcs.Patch.Witnesses.Ordered ( mapFL_FL )  @@ -23,3 +23,6 @@ instance PrimPatch prim => RepairToFL (RepoPatchV1 prim) where     applyAndTryToFixFL (PP x) = mapMaybeSnd (mapFL_FL PP) `fmap` applyAndTryToFixFL x     applyAndTryToFixFL x = do apply x; return Nothing++instance (PrimPatch prim, Annotate prim) => Annotate (RepoPatchV1 prim) where+    annotate = annotate . effect
src/Darcs/Patch/V1/Commute.hs view
@@ -16,9 +16,7 @@ --  Boston, MA 02110-1301, USA.  {-# OPTIONS_GHC -fno-warn-orphans #-}-{-# LANGUAGE CPP #-} - module Darcs.Patch.V1.Commute     (       merge,@@ -36,9 +34,12 @@ import Darcs.Patch.Commute ( selfCommuter ) import Darcs.Patch.CommuteFn ( commuterIdFL, commuterFLId ) import Darcs.Util.Path ( FileName )+import Darcs.Util.Printer ( errorDoc ) import Darcs.Patch.Invert ( invertRL )-import Darcs.Patch.Merge ( Merge(..) )-import Darcs.Patch.Patchy ( Commute(..), PatchInspect(..), Invert(..) )+import Darcs.Patch.Merge ( Merge(..), naturalMerge )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Invert ( Invert(..) )+import Darcs.Patch.Inspect ( PatchInspect(..) ) import Darcs.Patch.V1.Core ( RepoPatchV1(..),                              isMerger,                              mergerUndo )@@ -57,11 +58,10 @@ import Darcs.Patch.V1.Show ( showPatch_ ) import Data.List ( nub, nubBy ) import Data.List.Ordered ( nubSort )-#include "impossible.h" import Darcs.Patch.Witnesses.Sealed     ( Sealed(..) , mapSeal, unseal, FlippedSeal(..), mapFlipped     , unsafeUnseal, unsafeUnsealFlipped )-import Darcs.Patch.Witnesses.Eq ( EqCheck(..), MyEq(..) )+import Darcs.Patch.Witnesses.Eq ( EqCheck(..), Eq2(..) ) import Darcs.Patch.Witnesses.Unsafe     ( unsafeCoerceP, unsafeCoercePStart     , unsafeCoercePEnd )@@ -182,7 +182,7 @@         -- "after" @z@), but we need to return both arms. We therefore commute         -- @z@ and @y'@, to obtain a @z'@, which applies "after" @y'' == y@.         Sealed y' -> case commute (z :> y') of-                         Nothing -> bugDoc $ text "merge_patches bug"+                         Nothing -> errorDoc $ text "merge_patches bug"                                     $$ showPatch_ y                                    $$ showPatch_ z                                    $$ showPatch_ y'@@ -272,17 +272,6 @@    qs' :> p'' <- commuteFLId commuter (p' :> qs)    return ((q' :>: qs') :> p'') --- | elegantMerge attempts to perform the "intuitive" merge of two patches,--- from a common starting context @wX@.-elegantMerge :: PrimPatch prim-             => (RepoPatchV1 prim :\/: RepoPatchV1 prim) wX wY-             -> Maybe ((RepoPatchV1 prim :/\: RepoPatchV1 prim) wX wY)-elegantMerge (p1 :\/: p2) = do-  p1' :> ip2' <- commute (invert p2 :> p1)-  p1o :> _    <- commute (p2 :> p1')-  guard $ unsafeCompare p1o p1 -- should be a redundant check-  return $ invert ip2' :/\: p1'- {- A note about mergers and type witnesses ---------------------------------------@@ -313,7 +302,7 @@ -- rebuild it? actualMerge :: PrimPatch prim     => (RepoPatchV1 prim :\/: RepoPatchV1 prim) wX wY -> Sealed (RepoPatchV1 prim wY)-actualMerge (p1 :\/: p2) = case elegantMerge (p1:\/:p2) of+actualMerge (p1 :\/: p2) = case naturalMerge (p1:\/:p2) of                              Just (_ :/\: p1') -> Sealed p1'                              Nothing -> merger "0.0" p2 p1 @@ -352,7 +341,7 @@               Just p1s' -> mapFlipped (:<:p2) $                            reconcileUnwindings p p1s' tp2s               Nothing ->-                  bugDoc $ text "in function reconcileUnwindings"+                errorDoc $ text "in function reconcileUnwindings"                         $$ text "Original patch:"                         $$ showPatch_ p     _ -> bug "in reconcileUnwindings"@@ -381,7 +370,8 @@               case commuteFLId commuteNoMerger (p :> passedby) of               Just (_ :> p'@(Merger _ _ p1 p2)) ->                   map Sealed (nubBy unsafeCompare $-                        effect (unsafeCoercePStart $ unsafeUnseal (glump09 p1 p2)) : map (unsafeCoercePStart . unsafeUnseal) (unravel p'))+                        effect (unsafeCoercePStart $ unsafeUnseal (glump09 p1 p2)) :+                          map (unsafeCoercePStart . unsafeUnseal) (unravel p'))                   : rcs (p :>: passedby) ps               Nothing -> rcs (p :>: passedby) ps               _ -> impossible@@ -395,7 +385,7 @@   -- This type seems wrong - the most natural type for the result would seem to be--- [Sealed (FL Prim wX)], given the type of unwind.+-- [Sealed (FL prim wX)], given the type of unwind. -- However downstream code in darcs convert assumes the wY type, and I was unable -- to figure out whether this could/should reasonably be changed -- Ganesh 13/4/10 publicUnravel :: PrimPatch prim => RepoPatchV1 prim wX wY -> [Sealed (FL prim wY)]@@ -463,11 +453,11 @@ newUr p (ps :<: Merger _ _ p1 p2) =    case filter (\(_:<:pp) -> pp `unsafeCompare` p1) $ headPermutationsRL ps of    ((ps':<:_):_) -> newUr p (ps':<:unsafeCoercePStart p1) ++ newUr p (ps':<:unsafeCoercePStart p2)-   _ -> bugDoc $ text "in function newUr"-              $$ text "Original patch:"-              $$ showPatch_ p-              $$ text "Unwound:"-              $$ vcat (unseal (mapRL showPatch_) $ unwind p)+   _ -> errorDoc $ text "in function newUr"+                 $$ text "Original patch:"+                 $$ showPatch_ p+                 $$ text "Unwound:"+                 $$ vcat (unseal (mapRL showPatch_) $ unwind p)  newUr op ps =     case filter (\(_:<:p) -> isMerger p) $ headPermutationsRL ps of@@ -481,13 +471,13 @@         = Merger undo unwindings p1 p2     invert (PP p) = PP (invert p) -instance MyEq prim => MyEq (RepoPatchV1 prim) where+instance Eq2 prim => Eq2 (RepoPatchV1 prim) where     unsafeCompare = eqPatches -instance MyEq prim => Eq (RepoPatchV1 prim wX wY) where+instance Eq2 prim => Eq (RepoPatchV1 prim wX wY) where     (==) = unsafeCompare -eqPatches :: MyEq prim => RepoPatchV1 prim wX wY -> RepoPatchV1 prim wW wZ -> Bool+eqPatches :: Eq2 prim => RepoPatchV1 prim wX wY -> RepoPatchV1 prim wW wZ -> Bool eqPatches (PP p1) (PP p2) = unsafeCompare p1 p2 eqPatches (Merger _ _ p1a p1b) (Merger _ _ p2a p2b)  = eqPatches p1a p2a &&
src/Darcs/Patch/V1/Core.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE GeneralizedNewtypeDeriving, StandaloneDeriving #-} module Darcs.Patch.V1.Core     ( RepoPatchV1(..),       isMerger, mergerUndo@@ -7,9 +7,14 @@ import Prelude () import Darcs.Prelude -import Darcs.Patch.Format ( PatchListFormat(..), ListFormat(ListFormatV1) )+import Darcs.Patch.Format+    ( PatchListFormat(..)+    , ListFormat(ListFormatV1)+    ) import Darcs.Patch.Debug ( PatchDebug(..) )-import Darcs.Patch.Prim ( FromPrim(..), PrimOf, PrimPatchBase, PrimPatch )+import Darcs.Patch.Prim+    ( FromPrim(..), PrimPatchBase(..), PrimPatch+    ) import Darcs.Patch.Repair ( Check )  import Darcs.Patch.Witnesses.Ordered ( FL(..), RL )@@ -19,8 +24,6 @@     , appPrec, showsPrec2     ) -#include "impossible.h"- -- This haddock could be put on the individual bits of Merger instead -- once haddock supports doc comments on GADT constructors {- |@@ -95,3 +98,4 @@    -- no checks  instance PatchDebug prim => PatchDebug (RepoPatchV1 prim)+
+ src/Darcs/Patch/V1/Prim.hs view
@@ -0,0 +1,116 @@+-- it is stupid that we need UndecidableInstances just to call another+-- type function (see instance Apply below which requires this)+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Darcs.Patch.V1.Prim ( Prim(..) ) where++import Prelude ()+import Darcs.Prelude++import Data.Coerce ( coerce )++import Darcs.Patch.Annotate ( Annotate(..) )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute )+import Darcs.Patch.FileHunk ( IsHunk(..) )+import Darcs.Patch.Format+    ( PatchListFormat(..)+    , ListFormat(ListFormatV1)+    , FileNameFormat(OldFormat,UserFormat) )+import Darcs.Patch.Inspect ( PatchInspect )+import Darcs.Patch.Invert ( Invert )+import Darcs.Patch.Read ( ReadPatch(..) )+import Darcs.Patch.Repair ( RepairToFL(..) )+import Darcs.Patch.Show+    ( ShowPatchBasic(..)+    , ShowPatchFor(..)+    , ShowPatch(..)+    , ShowContextPatch(..)+    )+import Darcs.Patch.Summary ( plainSummaryPrim, plainSummaryPrims )++import Darcs.Patch.Witnesses.Eq ( Eq2 )+import Darcs.Patch.Witnesses.Show+    ( Show1(..), Show2(..)+    , ShowDict(ShowDictClass)+    , appPrec, showsPrec2+    )+import Darcs.Patch.Witnesses.Sealed ( Sealed(..) )++import Darcs.Patch.Prim.Class+    ( PrimConstruct(..), PrimCanonize(..)+    , PrimClassify(..), PrimDetails(..)+    , PrimShow(..), PrimRead(..)+    , PrimApply(..)+    , PrimPatch, PrimPatchBase(..)+    , FromPrim(..), ToFromPrim(..)+    , PrimPatchCommon+    )+import qualified Darcs.Patch.Prim.V1 as Base ( Prim )++newtype Prim x y = Prim { unPrim :: Base.Prim x y } deriving+    ( Annotate+    , Commute+    , Invert+    , IsHunk+    , Eq2+    , PatchInspect+    , PrimApply+    , PrimCanonize+    , PrimClassify+    , PrimConstruct+    , PrimDetails+    , PrimPatchCommon+    )++instance PrimPatch Prim++instance Show (Prim wX wY)  where+  showsPrec d (Prim p) =+    showParen (d > appPrec) $ showString "Prim " . showsPrec2 (appPrec + 1) p++instance Show1 (Prim wX) where+  showDict1 = ShowDictClass++instance Show2 Prim where+  showDict2 = ShowDictClass++instance PrimPatchBase Prim where+  type PrimOf Prim = Prim++instance FromPrim Prim where+  fromPrim = id++instance ToFromPrim Prim where+  toPrim = Just++instance ReadPatch Prim where+  readPatch' = do+    Sealed p <- readPrim OldFormat+    return (Sealed (Prim p))++fileNameFormat :: ShowPatchFor -> FileNameFormat+fileNameFormat ForDisplay = UserFormat+fileNameFormat ForStorage = OldFormat++instance ShowPatchBasic Prim where+  showPatch fmt = showPrim (fileNameFormat fmt) . unPrim++instance ShowContextPatch Prim where+  showContextPatch f = showPrimCtx (fileNameFormat f) . unPrim++instance ShowPatch Prim where+  summary = plainSummaryPrim . unPrim+  summaryFL = plainSummaryPrims False+  thing _ = "change"++instance PatchListFormat Prim where+  patchListFormat = ListFormatV1++instance Apply Prim where+  type ApplyState Prim = ApplyState Base.Prim+  apply = apply . unPrim++instance RepairToFL Prim where+  applyAndTryToFixFL = fmap coerce . applyAndTryToFixFL . unPrim
src/Darcs/Patch/V1/Show.hs view
@@ -4,23 +4,28 @@ import Prelude () import Darcs.Prelude -import Darcs.Patch.Format ( FileNameFormat(..) )-import Darcs.Patch.Prim ( showPrim, PrimPatch )-+import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatchFor(..) ) import Darcs.Patch.V1.Core ( RepoPatchV1(..) ) -import Darcs.Util.Printer ( Doc,-                 text, blueText,-                 ($$), (<+>) )+import Darcs.Util.Printer ( Doc, text, blueText, ($$), (<+>) ) -showPatch_ :: PrimPatch prim => RepoPatchV1 prim wA wB -> Doc-showPatch_ (PP p) = showPrim OldFormat p-showPatch_ (Merger _ _ p1 p2) = showMerger "merger" p1 p2-showPatch_ (Regrem _ _ p1 p2) = showMerger "regrem" p1 p2 -showMerger :: PrimPatch prim => String -> RepoPatchV1 prim wA wB -> RepoPatchV1 prim wD wE -> Doc-showMerger merger_name p1 p2 =+showPatch_ :: ShowPatchBasic prim => prim wX wY -> Doc+showPatch_ = showPatch ForDisplay++showMerger :: ShowPatchBasic prim+           => ShowPatchFor+           -> String+           -> RepoPatchV1 prim wA wB+           -> RepoPatchV1 prim wD wE+           -> Doc+showMerger f merger_name p1 p2 =     blueText merger_name <+> text "0.0" <+> blueText "("-                           $$ showPatch_ p1-                           $$ showPatch_ p2+                           $$ showPatch f p1+                           $$ showPatch f p2                            $$ blueText ")"++instance ShowPatchBasic prim => ShowPatchBasic (RepoPatchV1 prim) where+    showPatch f (PP p) = showPatch f p+    showPatch f (Merger _ _ p1 p2) = showMerger f "merger" p1 p2+    showPatch f (Regrem _ _ p1 p2) = showMerger f "regrem" p1 p2
src/Darcs/Patch/V1/Viewing.hs view
@@ -1,25 +1,19 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} module Darcs.Patch.V1.Viewing () where -import Prelude ()-import Darcs.Prelude- import Darcs.Patch.Prim ( PrimPatch )-import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatch(..) )+import Darcs.Patch.Show ( ShowPatch(..), ShowContextPatch(..), showPatch ) import Darcs.Patch.Summary ( plainSummary )  import Darcs.Patch.V1.Apply () import Darcs.Patch.V1.Core ( RepoPatchV1(..) )-import Darcs.Patch.V1.Show ( showPatch_ )-+import Darcs.Patch.V1.Show () -instance PrimPatch prim => ShowPatchBasic (RepoPatchV1 prim) where-    showPatch = showPatch_+instance PrimPatch prim => ShowContextPatch (RepoPatchV1 prim) where+    showContextPatch f (PP p) = showContextPatch f p+    showContextPatch f p = return $ showPatch f p  instance PrimPatch prim => ShowPatch (RepoPatchV1 prim) where-    showContextPatch (PP p) = showContextPatch p-    showContextPatch p = return $ showPatch p     summary = plainSummary     summaryFL = plainSummary     thing _ = "change"-
src/Darcs/Patch/V2.hs view
@@ -1,11 +1,11 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}-module Darcs.Patch.V2 ( RepoPatchV2, prim2repopatchV2 ) where+module Darcs.Patch.V2 ( RepoPatchV2 ) where +import Darcs.Patch.Annotate ( Annotate ) import Darcs.Patch.Matchable ( Matchable ) import Darcs.Patch.Prim ( PrimPatch ) import Darcs.Patch.RepoPatch ( RepoPatch )--import Darcs.Patch.V2.RepoPatch ( RepoPatchV2, prim2repopatchV2 )+import Darcs.Patch.V2.RepoPatch ( RepoPatchV2 )  instance PrimPatch prim => Matchable (RepoPatchV2 prim)-instance PrimPatch prim => RepoPatch (RepoPatchV2 prim)+instance (PrimPatch prim, Annotate prim) => RepoPatch (RepoPatchV2 prim)
src/Darcs/Patch/V2/Non.hs view
@@ -16,7 +16,7 @@ -- Boston, MA 02110-1301, USA.  {-# OPTIONS_GHC -fno-warn-orphans -fno-warn-name-shadowing #-}-{-# LANGUAGE CPP, FlexibleContexts, UndecidableInstances #-}+{-# LANGUAGE FlexibleContexts, UndecidableInstances #-}   module Darcs.Patch.V2.Non@@ -44,18 +44,22 @@  import Data.List ( delete ) import Control.Monad ( liftM, mzero )+import Darcs.Patch.Apply ( Apply(..) ) import Darcs.Patch.Commute ( commuteFL ) import Darcs.Patch.Effect ( Effect(..) )-import Darcs.Patch.Format ( PatchListFormat, FileNameFormat(..) )+import Darcs.Patch.Format ( PatchListFormat ) import Darcs.Patch.Invert ( Invert, invertFL, invertRL )-import Darcs.Patch.Prim ( FromPrim(..), ToFromPrim(..),-                          PrimOf, PrimPatchBase,-                          showPrim, sortCoalesceFL,-                          readPrim )-import Darcs.Patch.Patchy ( Patchy, showPatch, ReadPatch(..),-                            Commute(..), invert )+import Darcs.Patch.Prim+    ( FromPrim(..), ToFromPrim(..)+    , PrimOf, PrimPatchBase+    , sortCoalesceFL+    )+import Darcs.Patch.Commute ( Commute(..) )+import Darcs.Patch.Invert ( Invert(invert) )+import Darcs.Patch.Read ( ReadPatch(..) )+import Darcs.Patch.Show ( showPatch ) import Darcs.Patch.ReadMonads ( ParserM, lexChar )-import Darcs.Patch.Witnesses.Eq ( MyEq(..), EqCheck(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) ) import Darcs.Patch.Witnesses.Ordered     ( FL(..), RL(..), (+>+), mapRL_RL     , (:>)(..), reverseFL, reverseRL )@@ -64,7 +68,7 @@     , showsPrec2 ) import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed) ) import Darcs.Patch.Read ( peekfor )-import Darcs.Patch.Show ( ShowPatchBasic )+import Darcs.Patch.Show ( ShowPatchBasic, ShowPatchFor ) import Darcs.Patch.Viewing () import Darcs.Patch.Permutations ( removeFL, commuteWhatWeCanFL ) import Darcs.Util.Printer ( Doc, empty, vcat, hiddenPrefix, blueText, ($$) )@@ -90,16 +94,18 @@  -- |showNons creates a Doc representing a list of Nons. showNons :: (ShowPatchBasic p, PatchListFormat p, PrimPatchBase p)-         => [Non p wX] -> Doc-showNons [] = empty-showNons xs = blueText "{{" $$ vcat (map showNon xs) $$ blueText "}}"+         => ShowPatchFor -> [Non p wX] -> Doc+showNons _ [] = empty+showNons f xs = blueText "{{" $$ vcat (map (showNon f) xs) $$ blueText "}}"  -- |showNon creates a Doc representing a Non.-showNon :: (ShowPatchBasic p, PatchListFormat p, PrimPatchBase p) => Non p wX+showNon :: (ShowPatchBasic p, PatchListFormat p, PrimPatchBase p)+        => ShowPatchFor+        -> Non p wX         -> Doc-showNon (Non c p) = hiddenPrefix "|" (showPatch c)-                    $$ hiddenPrefix "|" (blueText ":")-                    $$ showPrim NewFormat p+showNon f (Non c p) = hiddenPrefix "|" (showPatch f c)+                      $$ hiddenPrefix "|" (blueText ":")+                      $$ showPatch f p  -- |readNons is a parser that attempts to read a list of Nons. readNons :: (ReadPatch p, PatchListFormat p, PrimPatchBase p, ParserM m)@@ -108,20 +114,20 @@   where rns = peekfor (BC.pack "}}") (return []) $               do Sealed ps <- readPatch'                  lexChar ':'-                 Sealed p <- readPrim NewFormat+                 Sealed p <- readPatch'                  (Non ps p :) `liftM` rns  -- |readNon is a parser that attempts to read a single Non. readNon :: (ReadPatch p, PatchListFormat p, PrimPatchBase p, ParserM m)         => m (Non p wX) readNon = do Sealed ps <- readPatch'-             let doReadPrim = do Sealed p <- readPrim NewFormat+             let doReadPrim = do Sealed p <- readPatch'                                  return $ Non ps p              peekfor (BC.singleton ':') doReadPrim mzero  -- |Nons are equal if their context patches are equal, and they have an equal -- prim patch.-instance (Commute p, MyEq p, MyEq (PrimOf p)) => Eq (Non p wX) where+instance (Commute p, Eq2 p, Eq2 (PrimOf p)) => Eq (Non p wX) where     Non (cx :: FL p wX wY1) (x :: PrimOf p wY1 wZ1)      == Non (cy :: FL p wX wY2) (y :: PrimOf p wY2 wZ2) =       case cx =\/= cy of@@ -138,7 +144,7 @@ -- returns some variant @cy'@. If commutation suceeds, the variant is just -- straightforwardly the commuted version. If commutation fails, the variant -- consists of @x@ prepended to the context of @cy@.-commuteOrAddToCtx :: (Patchy p, ToFromPrim p) => p wX wY -> Non p wY+commuteOrAddToCtx :: (Commute p, ToFromPrim p) => p wX wY -> Non p wY                   -> Non p wX commuteOrAddToCtx p n | Just n' <- p >* n = n' commuteOrAddToCtx p (Non c x) = Non (p:>:c) x@@ -155,7 +161,7 @@ -- > x1 [c1'' c2'' y''] x2' x3' -- -- and return @[x1 c1'' c2'' y'']@-commuteOrAddToCtxRL :: (Patchy p, ToFromPrim p) => RL p wX wY -> Non p wY+commuteOrAddToCtxRL :: (Apply p, Commute p, Invert p, ToFromPrim p) => RL p wX wY -> Non p wY                     -> Non p wX commuteOrAddToCtxRL NilRL n = n commuteOrAddToCtxRL (ps:<:p) n = commuteOrAddToCtxRL ps $ commuteOrAddToCtx p n@@ -175,7 +181,7 @@  -- |commutePrimsOrAddToCtx takes a WL of prims and attempts to commute them -- past a Non.-commutePrimsOrAddToCtx :: (WL l, Patchy p, ToFromPrim p) => l (PrimOf p) wX wY+commutePrimsOrAddToCtx :: (WL l, Apply p, Commute p, Invert p, ToFromPrim p) => l (PrimOf p) wX wY          -> Non p wY -> Non p wX commutePrimsOrAddToCtx q = commuteOrAddToCtxRL (mapRL_RL fromPrim $ toRL q) @@ -194,14 +200,14 @@ -- modify p2, so that it doesn't have any of a1' in its context.  -- remNons really only works right if the relevant nons are conflicting...-remNons :: (Nonable p, Effect p, Patchy p, MyEq p, ToFromPrim p, PrimPatchBase p,-        MyEq (PrimOf p)) => [Non p wX] -> Non p wX -> Non p wX+remNons :: (Nonable p, Effect p, Apply p, Commute p, Invert p, Eq2 p, ToFromPrim p, PrimPatchBase p)+        => [Non p wX] -> Non p wX -> Non p wX remNons ns n@(Non c x) = case remNonHelper ns c of                              NilFL :> c' -> Non c' x                              _ -> n   where-    remNonHelper :: (Nonable p, Effect p, Patchy p, MyEq p, ToFromPrim p,-                 PrimPatchBase p, MyEq (PrimOf p)) => [Non p wX]+    remNonHelper :: (Nonable p, Effect p, Apply p, Commute p, Invert p, Eq2 p, ToFromPrim p,+                 PrimPatchBase p) => [Non p wX]                  -> FL p wX wY -> (FL (PrimOf p) :> FL p) wX wY     remNonHelper [] x = NilFL :> x     remNonHelper _ NilFL = NilFL :> NilFL@@ -223,26 +229,26 @@ -- -- TODO: understand if there is any case where p is equal to the prim patch of -- the Non, in which case, we return the original Non, is that right?-commuteOrRemFromCtx :: (Patchy p, MyEq p, ToFromPrim p) => p wX wY -> Non p wX+commuteOrRemFromCtx :: (Commute p, Invert p, Eq2 p, ToFromPrim p) => p wX wY -> Non p wX      -> Maybe (Non p wY) commuteOrRemFromCtx p n | n'@(Just _) <- n *> p = n' commuteOrRemFromCtx p (Non pc x) = removeFL p pc >>= \c -> return (Non c x)  -- |commuteOrRemFromCtxFL attempts to remove a FL of patches from a Non, -- returning Nothing if any of the individual removes fail.-commuteOrRemFromCtxFL :: (Patchy p, MyEq p, ToFromPrim p) => FL p wX wY -> Non p wX+commuteOrRemFromCtxFL :: (Apply p, Commute p, Invert p, Eq2 p, ToFromPrim p) => FL p wX wY -> Non p wX                       -> Maybe (Non p wY) commuteOrRemFromCtxFL NilFL n = Just n commuteOrRemFromCtxFL (p:>:ps) n = do n' <- commuteOrRemFromCtx p n                                       commuteOrRemFromCtxFL ps n'  -- |(*>) attemts to modify a Non by commuting it past a given patch.-(*>) :: (Patchy p, ToFromPrim p) => Non p wX -> p wX wY+(*>) :: (Commute p, Invert p, ToFromPrim p) => Non p wX -> p wX wY      -> Maybe (Non p wY) n *> p = invert p >* n  -- |(>*) attempts to modify a Non, by commuting a given patch past it.-(>*) :: (Patchy p, ToFromPrim p) => p wX wY -> Non p wY+(>*) :: (Commute p, ToFromPrim p) => p wX wY -> Non p wY      -> Maybe (Non p wX) y >* (Non c x) = do     c' :> y' <- commuteFL (y :> c)@@ -251,16 +257,16 @@     return (Non c' x')  -- |(*>>) attempts to modify a Non by commuting it past a given WL of patches.-(*>>) :: (WL l, Patchy p, ToFromPrim p, PrimPatchBase p) => Non p wX+(*>>) :: (WL l, Apply p, Commute p, Invert p, ToFromPrim p, PrimPatchBase p) => Non p wX       -> l (PrimOf p) wX wY -> Maybe (Non p wY) n *>> p = invertWL p >>* n  -- |(>>*) attempts to modify a Non by commuting a given WL of patches past it.-(>>*) :: (WL l, Patchy p, ToFromPrim p) => l (PrimOf p) wX wY -> Non p wY+(>>*) :: (WL l, Apply p, Commute p, Invert p, ToFromPrim p) => l (PrimOf p) wX wY -> Non p wY       -> Maybe (Non p wX) ps >>* n = commuteRLPastNon (toRL ps) n   where-    commuteRLPastNon :: (Patchy p, ToFromPrim p) => RL (PrimOf p) wX wY+    commuteRLPastNon :: (Apply p, Commute p, Invert p, ToFromPrim p) => RL (PrimOf p) wX wY                      -> Non p wY -> Maybe (Non p wX)     commuteRLPastNon NilRL n = Just n     commuteRLPastNon (xs:<:x) n = fromPrim x >* n >>= commuteRLPastNon xs
+ src/Darcs/Patch/V2/Prim.hs view
@@ -0,0 +1,120 @@+-- it is stupid that we need UndecidableInstances just to call another+-- type function (see instance Apply below which requires this)+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Darcs.Patch.V2.Prim ( Prim(..) ) where++import Prelude ()+import Darcs.Prelude++import Data.Coerce (coerce )++import Darcs.Patch.Annotate ( Annotate )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Commute ( Commute )+import Darcs.Patch.FileHunk ( IsHunk )+import Darcs.Patch.Format+    ( PatchListFormat(..)+    , ListFormat(ListFormatV2)+    , FileNameFormat(NewFormat,UserFormat) )+import Darcs.Patch.Inspect ( PatchInspect )+import Darcs.Patch.Invert ( Invert )+import Darcs.Patch.Read ( ReadPatch(..) )+import Darcs.Patch.Repair ( RepairToFL(..) )+import Darcs.Patch.Show+    ( ShowPatchBasic(..)+    , ShowPatchFor(..)+    , ShowPatch(..)+    , ShowContextPatch(..)+    )+import Darcs.Patch.Summary ( plainSummaryPrim, plainSummaryPrims )++import Darcs.Patch.Witnesses.Eq ( Eq2 )+import Darcs.Patch.Witnesses.Show+    ( Show1(..), Show2(..)+    , ShowDict(ShowDictClass)+    , appPrec, showsPrec2+    )+import Darcs.Patch.Witnesses.Sealed ( mapSeal )++import Darcs.Patch.Prim.Class+    ( PrimConstruct(..), PrimCanonize(..)+    , PrimClassify(..), PrimDetails(..)+    , PrimShow(..), PrimRead(..)+    , PrimApply(..)+    , PrimPatch, PrimPatchBase(..)+    , FromPrim(..), ToFromPrim(..)+    , PrimPatchCommon+    )+import qualified Darcs.Patch.Prim.V1 as Base ( Prim )++newtype Prim x y = Prim { unPrim :: Base.Prim x y } deriving+    ( Annotate+    , Commute+    , Invert+    , IsHunk+    , Eq2+    , PatchInspect+    , PrimApply+    , PrimCanonize+    , PrimClassify+    , PrimConstruct+    , PrimDetails+    , PrimPatchCommon+    )++instance PrimPatch Prim++instance Show (Prim wX wY)  where+  showsPrec d (Prim p) =+    showParen (d > appPrec) $ showString "Prim " . showsPrec2 (appPrec + 1) p++instance Show1 (Prim wX) where+  showDict1 = ShowDictClass++instance Show2 Prim where+  showDict2 = ShowDictClass++instance PrimPatchBase Prim where+  type PrimOf Prim = Prim++instance FromPrim Prim where+  fromPrim = id++instance ToFromPrim Prim where+  toPrim = Just++instance ReadPatch Prim where+  readPatch' = fmap (mapSeal Prim) (readPrim NewFormat)++fileNameFormat :: ShowPatchFor -> FileNameFormat+fileNameFormat ForDisplay = UserFormat+fileNameFormat ForStorage = NewFormat++instance ShowPatchBasic Prim where+  showPatch f = showPrim (fileNameFormat f) . unPrim++instance ShowContextPatch Prim where+  showContextPatch f = showPrimCtx (fileNameFormat f) . unPrim++instance ShowPatch Prim where+  summary = plainSummaryPrim . unPrim+  summaryFL = plainSummaryPrims False+  thing _ = "change"++-- This instance is here so that FL Prim and RL Prim also get+-- ShowPatch instances, see Darcs.Patch.Viewing+instance PatchListFormat Prim where+  -- In principle we could use ListFormatDefault when prim /= V1 Prim patches,+  -- as those are the only case where we need to support a legacy on-disk+  -- format. In practice we don't expect RepoPatchV2 to be used with any other+  -- argument anyway, so it doesn't matter.+  patchListFormat = ListFormatV2++instance Apply Prim where+  type ApplyState Prim = ApplyState Base.Prim+  apply = apply . unPrim++instance RepairToFL Prim where+  applyAndTryToFixFL = fmap coerce . applyAndTryToFixFL . unPrim
src/Darcs/Patch/V2/RepoPatch.hs view
@@ -16,12 +16,9 @@ -- Boston, MA 02110-1301, USA.  {-# OPTIONS_GHC -fno-warn-orphans -fno-warn-name-shadowing #-}-{-# LANGUAGE CPP #-} - module Darcs.Patch.V2.RepoPatch     ( RepoPatchV2(..)-    , prim2repopatchV2     , isConsistent     , isForward     , isDuplicate@@ -35,43 +32,45 @@ import qualified Data.ByteString.Char8 as BC ( ByteString, pack ) import Data.Maybe ( fromMaybe ) import Data.List ( partition, nub )+import Data.List.Ordered ( nubSort ) +import Darcs.Patch.Annotate ( Annotate(..) ) import Darcs.Patch.Commute ( commuteFL, commuteFLorComplain, commuteRL-                           , commuteRLFL )+                           , commuteRLFL, Commute(..) ) import Darcs.Patch.Conflict ( Conflict(..), CommuteNoConflicts(..)                             , IsConflictedPrim(..), ConflictState(..)                             , mangleUnravelled ) import Darcs.Patch.Debug import Darcs.Patch.Effect ( Effect(..) ) import Darcs.Patch.FileHunk ( IsHunk(..) )-import Darcs.Patch.Format ( PatchListFormat(..), ListFormat(..)-                          , FileNameFormat(NewFormat) )-import Darcs.Patch.Invert ( invertFL, invertRL )-import Darcs.Patch.Merge ( Merge(..) )-import Darcs.Patch.Prim ( FromPrim(..), ToFromPrim(..), showPrim, showPrimFL-                        , readPrim, PrimOf, PrimPatchBase, PrimPatch )-import Darcs.Patch.Read ( bracketedFL )+import Darcs.Patch.Format ( PatchListFormat(..), ListFormat(ListFormatV2) )+import Darcs.Patch.Invert ( invertFL, invertRL, Invert(..) )+import Darcs.Patch.Merge ( Merge(..), naturalMerge )+import Darcs.Patch.Prim ( FromPrim(..), ToFromPrim(..)+                        , PrimPatchBase(..), PrimPatch )+import Darcs.Patch.Read ( bracketedFL, ReadPatch(..) ) import Darcs.Patch.ReadMonads ( skipSpace, string, choice ) import Darcs.Patch.Repair ( mapMaybeSnd, RepairToFL(..), Check(..) )-import Darcs.Patch.Patchy ( Patchy, Apply(..), Commute(..), PatchInspect(..)-                          , ReadPatch(..), ShowPatch(..), Invert(..) )+import Darcs.Patch.Apply ( Apply(..) )+import Darcs.Patch.Inspect ( PatchInspect(..) ) import Darcs.Patch.Permutations ( commuteWhatWeCanFL, commuteWhatWeCanRL                                 , genCommuteWhatWeCanRL, removeRL, removeFL                                 , removeSubsequenceFL )-import Darcs.Patch.Show ( ShowPatchBasic(..) )+import Darcs.Patch.Show+    ( ShowPatch(..), ShowPatchBasic(..), ShowContextPatch(..), ShowPatchFor(..)+    , displayPatch ) import Darcs.Patch.Summary ( plainSummary ) import Darcs.Patch.V2.Non ( Non(..), Nonable(..), unNon, showNons, showNon                           , readNons, readNon, commutePrimsOrAddToCtx                           , commuteOrAddToCtx, commuteOrAddToCtxRL                           , commuteOrRemFromCtx, commuteOrRemFromCtxFL                           , remNons, (*>), (>*), (*>>), (>>*) )-import Data.List.Ordered ( nubSort ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )-import Darcs.Patch.Witnesses.Eq ( MyEq(..), EqCheck(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) ) import Darcs.Patch.Witnesses.Ordered     ( FL(..), RL(..), (:>)(..), (+>+), (+<+)-    , mapFL_FL, reverseFL, (:\/:)(..), (:/\:)(..)-    , reverseRL, lengthFL, lengthRL, nullFL )+    , mapFL, mapFL_FL, reverseFL, (:\/:)(..), (:/\:)(..)+    , reverseRL, lengthFL, lengthRL, nullFL, initsFL ) import Darcs.Patch.Witnesses.Sealed     ( FlippedSeal(..), Sealed(Sealed), mapSeal     , unseal )@@ -79,11 +78,9 @@     ( Show1(..), Show2(..), ShowDict(..)     , showsPrec2, appPrec     )-import Darcs.Util.Printer.Color ( errorDoc, assertDoc ) -import Darcs.Util.Printer ( Doc, blueText, redText, (<+>), ($$) )--#include "impossible.h"+import Darcs.Util.Printer.Color ( errorDoc, assertDoc )+import Darcs.Util.Printer ( Doc, blueText, redText, (<+>), ($$), vcat )  -- |'RepoPatchV2' is used to represents prim patches that are duplicates of, or -- conflict with, another prim patch in the repository.@@ -141,7 +138,7 @@     p@(Etacilpud _) -> justRedP "An inverse duplicate" p     _ -> Nothing   where-    justRedP msg p = Just $ redText msg $$ showPatch p+    justRedP msg p = Just $ redText msg $$ displayPatch p  -- |'mergeUnravelled' is used when converting from Darcs V1 patches (Mergers) -- to Darcs V2 patches (Conflictors).@@ -155,7 +152,7 @@         Just NilRL -> bug "found no patches in mergeUnravelled"         Just (_ :<: z) -> Just $ FlippedSeal z   where-    notNullS :: PrimPatch prim => Sealed ((FL prim) wX) -> Bool+    notNullS :: Sealed ((FL prim) wX) -> Bool     notNullS (Sealed NilFL) = False     notNullS _ = True @@ -191,7 +188,7 @@                         qs' :/\: _ -> mcn (Sealed (c +>+ ps +>+ qs'):zs)  joinEffects :: forall p wX wY . (Effect p, Invert (PrimOf p),-            Commute (PrimOf p), MyEq (PrimOf p)) => p wX wY+            Commute (PrimOf p), Eq2 (PrimOf p)) => p wX wY             -> FL (PrimOf p) wX wY joinEffects = joinInverses . effect     where joinInverses :: FL (PrimOf p) wA wB -> FL (PrimOf p) wA wB@@ -204,7 +201,7 @@                  -> RepoPatchV2 prim wX wY assertConsistent x = flip assertDoc x $ do     e <- isConsistent x-    Just (redText "Inconsistent patch:" $$ showPatch x $$ e)+    Just (redText "Inconsistent patch:" $$ displayPatch x $$ e)  -- | @mergeAfterConflicting@ takes as input a sequence of conflicting patches -- @xxx@ (which therefore have no effect) and a sequence of primitive patches@@ -267,7 +264,7 @@     case mergeConflictingNons ix of         Nothing -> errorDoc $             redText "mergeConflictingNons failed in geteff: ix" $$-            showNons ix $$ redText "xx" $$ showPatch xx+            displayNons ix $$ redText "xx" $$ displayPatch xx         Just rix ->             case mergeAfterConflicting rix xx of                 Just (a, x) ->@@ -276,9 +273,9 @@                 Nothing ->                     errorDoc $                         redText "mergeAfterConflicting failed in geteff" $$-                        redText "where ix" $$ showNons ix $$-                        redText "and xx" $$ showPatch xx $$-                        redText "and rix" $$ showPatch rix+                        redText "where ix" $$ displayNons ix $$+                        redText "and xx" $$ displayPatch xx $$+                        redText "and rix" $$ displayPatch rix  xx2nons :: PrimPatch prim => [Non (RepoPatchV2 prim) wX] -> FL prim wX wY         -> [Non (RepoPatchV2 prim) wX]@@ -309,18 +306,18 @@         Just $ redText "m doesn't conflict with mm in isConsistent"     | any (\x -> any (x `conflictsWith`) nmm) im =         Just $ redText "mm conflicts with im in isConsistent where nmm is" $$-               showNons nmm+               displayNons nmm     | Nothing <- (nmm ++ im) `minus` toNons deps =         Just $ redText "dependencies not in conflict:" $$-               showNons (toNons deps) $$+               displayNons (toNons deps) $$                redText "compared with deps itself:" $$-               showPatch deps+               displayPatch deps     | otherwise =         case allConflictsWith m im of             (im1, []) | im1 `eqSet` im -> Nothing             (_, imnc) -> Just $ redText ("m doesn't conflict with im in "                                          ++ "isConsistent. unconflicting:") $$-                                showNons imnc+                                displayNons imnc     where (nmm, rmm) = geteff im mm  everyoneConflicts :: PrimPatch prim => [Non (RepoPatchV2 prim) wX] -> Bool@@ -329,10 +326,6 @@                                  ([], _) -> False                                  (_, xs') -> everyoneConflicts xs' -prim2repopatchV2 :: prim wX wY -> RepoPatchV2 prim wX wY-prim2repopatchV2 = Normal--instance PrimPatch prim => Patchy (RepoPatchV2 prim) instance PatchDebug prim => PatchDebug (RepoPatchV2 prim)  mergeWith :: PrimPatch prim => Non (RepoPatchV2 prim) wX@@ -470,13 +463,13 @@     isInconsistent = isConsistent  instance FromPrim (RepoPatchV2 prim) where-    fromPrim = prim2repopatchV2+    fromPrim = Normal  instance ToFromPrim (RepoPatchV2 prim) where     toPrim (Normal p) = Just p     toPrim _ = Nothing -instance PrimPatch prim => MyEq (RepoPatchV2 prim) where+instance PrimPatch prim => Eq2 (RepoPatchV2 prim) where     (Duplicate x) =\/= (Duplicate y) | x == y = IsEq     (Etacilpud x) =\/= (Etacilpud y) | x == y = IsEq     (Normal x) =\/= (Normal y) = x =\/= y@@ -519,8 +512,8 @@                -> Non (RepoPatchV2 prim) wX -> Bool nonHunkMatches f (Non c x) = hunkMatches f c || hunkMatches f x -toNons :: forall p wX wY . (Conflict p, Patchy p, PatchListFormat p,-       ToFromPrim p, Nonable p, ShowPatchBasic (PrimOf p), ShowPatchBasic p)+toNons :: forall p wX wY . (Commute p, PatchListFormat p,+       Nonable p, ShowPatchBasic (PrimOf p), ShowPatchBasic p)        => FL p wX wY -> [Non p wX] toNons xs = map lastNon $ initsFL xs     where lastNon :: Sealed ((p :> FL p) wX) -> Non p wX@@ -533,9 +526,9 @@                                errorDoc $ redText "Weird case in toNons" $$                                           redText "please report this bug!" $$                                           (case xxx of-                                           z :> zs -> showPatch (z :>: zs)) $$-                                          redText "ds are" $$ showPatch ds $$-                                          redText "pp is" $$ showPatch pp+                                           z :> zs -> displayPatch (z :>: zs)) $$+                                          redText "ds are" $$ displayPatch ds $$+                                          redText "pp is" $$ displayPatch pp            reverseFoo :: (p :> FL p) wX wZ -> (RL p :> p) wX wZ           reverseFoo (p :> ps) = rf NilRL p ps@@ -548,12 +541,6 @@           lastNon_aux :: (p :> FL p) wX wZ -> (RL p :> p :> RL p) wX wZ           lastNon_aux = commuteWhatWeCanRL . reverseFoo -initsFL :: Patchy p => FL p wX wY -> [Sealed ((p :> FL p) wX)]-initsFL NilFL = []-initsFL (x :>: xs) =-    Sealed (x :> NilFL) :-    map (\(Sealed (y :> xs')) -> Sealed (x :> y :>: xs')) (initsFL xs)- filterConflictsFL :: PrimPatch prim => Non (RepoPatchV2 prim) wX                   -> FL prim wX wY -> (FL prim :> FL prim) wX wY filterConflictsFL _ NilFL = NilFL :> NilFL@@ -651,17 +638,11 @@     -- Handle using the swap merge and the previous case.     merge m@(_ :\/: Duplicate _) = swapMerge m -    -- When merging x and y, we do a bunch of what look like "consistency"-    -- check merges. If the resulting y'' and y are equal, then we succeed.-    -- If the first case fails, we check for equal patches (which wouldn't-    -- commute) and return a Duplicate on both sides of the merge, in that-    -- case.     merge (x :\/: y)-        | Just (y' :> ix') <--            commute (invert (assertConsistent x) :> assertConsistent y)-        , Just (y'' :> _) <- commute (x :> y')-        , IsEq <- y'' =\/= y =-            assertConsistent y' :/\: invert (assertConsistent ix')+        -- First try the natural (non-conflicting) merge.+        | Just (y' :/\: x') <-+            naturalMerge ((assertConsistent x) :\/: (assertConsistent y))+              = assertConsistent y' :/\: assertConsistent x'         -- If we detect equal patches, we have a duplicate.         | IsEq <- x =\/= y         , n <- commuteOrAddToCtx (invert x) $ non x =@@ -768,12 +749,12 @@ (x:xs) +++ xys | Just ys <- remove1 x xys = x : (xs +++ ys)                | otherwise = x : (xs +++ xys) -swapMerge :: PrimPatch prim => (RepoPatchV2 prim :\/: RepoPatchV2 prim) wX wY-          -> (RepoPatchV2 prim :/\: RepoPatchV2 prim) wX wY+swapMerge :: Merge p => (p :\/: p) wX wY+          -> (p :/\: p) wX wY swapMerge (x :\/: y) = case merge (y :\/: x) of x' :/\: y' -> y' :/\: x' -invertCommute :: PrimPatch prim => (RepoPatchV2 prim :> RepoPatchV2 prim) wX wY-              -> Maybe ((RepoPatchV2 prim :> RepoPatchV2 prim) wX wY)+invertCommute :: (Invert p, Commute p) => (p :> p) wX wY+              -> Maybe ((p :> p) wX wY) invertCommute (x :> y) = do ix' :> iy' <- commute (invert y :> invert x)                             return (invert iy' :> invert ix') @@ -785,7 +766,7 @@  -- | 'pullCommon' @xs ys@ returns the set of patches that can be commuted out -- of both @xs@ and @ys@ along with the remnants of both lists-pullCommon :: (Patchy p, MyEq p) => FL p wO wX -> FL p wO wY -> Common p wO wX wY+pullCommon :: (Commute p, Eq2 p) => FL p wO wX -> FL p wO wY -> Common p wO wX wY pullCommon NilFL ys = Common NilFL NilFL ys pullCommon xs NilFL = Common NilFL xs NilFL pullCommon (x :>: xs) xys | Just ys <- removeFL x xys =@@ -803,7 +784,7 @@  -- | 'pullCommonRL' @xs ys@ returns the set of patches that can be commuted --   out of both @xs@ and @ys@ along with the remnants of both lists-pullCommonRL :: (Patchy p, MyEq p) => RL p wX wO -> RL p wY wO -> CommonRL p wX wY wO+pullCommonRL :: (Commute p, Eq2 p) => RL p wX wO -> RL p wY wO -> CommonRL p wX wY wO pullCommonRL NilRL ys = CommonRL NilRL ys NilRL pullCommonRL xs NilRL = CommonRL xs NilRL NilRL pullCommonRL (xs :<: x) xys | Just ys <- removeRL x xys =@@ -829,6 +810,9 @@         mapMaybeSnd (mapFL_FL Normal) `liftM` applyAndTryToFixFL p     applyAndTryToFixFL x = do apply x; return Nothing +instance (PrimPatch prim, Annotate prim) => Annotate (RepoPatchV2 prim) where+    annotate = annotate . effect+ instance PatchListFormat (RepoPatchV2 prim) where    -- In principle we could use ListFormatDefault when prim /= V1 Prim patches,    -- as those are the only case where we need to support a legacy on-disk@@ -843,27 +827,29 @@ rotcilfnoc = "rotcilfnoc"  instance PrimPatch prim => ShowPatchBasic (RepoPatchV2 prim) where-    showPatch (Duplicate d) = blueText duplicate $$ showNon d-    showPatch (Etacilpud d) = blueText etacilpud $$ showNon d-    showPatch (Normal p) = showPrim NewFormat p-    showPatch (Conflictor i NilFL p) =-        blueText conflictor <+> showNons i <+> blueText "[]" $$ showNon p-    showPatch (Conflictor i cs p) =-        blueText conflictor <+> showNons i <+> blueText "[" $$-        showPrimFL NewFormat cs $$+    showPatch f (Duplicate d) = blueText duplicate $$ showNon f d+    showPatch f (Etacilpud d) = blueText etacilpud $$ showNon f d+    showPatch f (Normal p) = showPatch f p+    showPatch f (Conflictor i NilFL p) =+        blueText conflictor <+> showNons f i <+> blueText "[]" $$ showNon f p+    showPatch f (Conflictor i cs p) =+        blueText conflictor <+> showNons f i <+> blueText "[" $$+        showFL f cs $$         blueText "]" $$-        showNon p-    showPatch (InvConflictor i NilFL p) =-        blueText rotcilfnoc <+> showNons i <+> blueText "[]" $$ showNon p-    showPatch (InvConflictor i cs p) =-        blueText rotcilfnoc <+> showNons i <+> blueText "[" $$-        showPrimFL NewFormat cs $$+        showNon f p+    showPatch f (InvConflictor i NilFL p) =+        blueText rotcilfnoc <+> showNons f i <+> blueText "[]" $$ showNon f p+    showPatch f (InvConflictor i cs p) =+        blueText rotcilfnoc <+> showNons f i <+> blueText "[" $$+        showFL f cs $$         blueText "]" $$-        showNon p+        showNon f p +instance PrimPatch prim => ShowContextPatch (RepoPatchV2 prim) where+    showContextPatch f (Normal p) = showContextPatch f p+    showContextPatch f p = return $ showPatch f p+ instance PrimPatch prim => ShowPatch (RepoPatchV2 prim) where-    showContextPatch (Normal p) = showContextPatch p-    showContextPatch c = return $ showPatch c     summary = plainSummary     summaryFL = plainSummary     thing _ = "change"@@ -874,7 +860,7 @@         let str = string . BC.pack             readConflictorPs = do                i <- readNons-               ps <- bracketedFL (readPrim NewFormat) '[' ']'+               ps <- bracketedFL readPatch' '[' ']'                p <- readNon                return (i, ps, p)         choice [ do str duplicate@@ -889,29 +875,29 @@                , do str rotcilfnoc                     (i, Sealed ps, p) <- readConflictorPs                     return $ Sealed $ InvConflictor i ps p-               , do Sealed p <- readPrim NewFormat+               , do Sealed p <- readPatch'                     return $ Sealed $ Normal p                ]  instance Show2 prim => Show (RepoPatchV2 prim wX wY) where     showsPrec d (Normal prim) =-        showParen (d > appPrec) $ showString "Darcs.Patch.V2.RepoPatch.Normal " . showsPrec2 (appPrec + 1) prim+        showParen (d > appPrec) $ showString "Normal " . showsPrec2 (appPrec + 1) prim      showsPrec d (Duplicate x) =-        showParen (d > appPrec) $ showString "Darcs.Patch.V2.RepoPatch.Duplicate " . showsPrec (appPrec + 1) x+        showParen (d > appPrec) $ showString "Duplicate " . showsPrec (appPrec + 1) x      showsPrec d (Etacilpud x) =-        showParen (d > appPrec) $ showString "Darcs.Patch.V2.Etacilpud " . showsPrec (appPrec + 1) x+        showParen (d > appPrec) $ showString "Etacilpud " . showsPrec (appPrec + 1) x      showsPrec d (Conflictor ix xx x) =         showParen (d > appPrec) $-            showString "Darcs.Patch.V2.RepoPatch.Conflictor " . showsPrec (appPrec + 1) ix .+            showString "Conflictor " . showsPrec (appPrec + 1) ix .             showString " " . showsPrec (appPrec + 1) xx .             showString " " . showsPrec (appPrec + 1) x      showsPrec d (InvConflictor ix xx x) =         showParen (d > appPrec) $-            showString "Darcs.Patch.V2.RepoPatch.InvConflictor " . showsPrec (appPrec + 1) ix .+            showString "InvConflictor " . showsPrec (appPrec + 1) ix .             showString " " . showsPrec (appPrec + 1) xx .             showString " " . showsPrec (appPrec + 1) x @@ -943,3 +929,10 @@ instance IsHunk prim => IsHunk (RepoPatchV2 prim) where     isHunk rp = do Normal p <- return rp                    isHunk p++displayNons :: (PatchListFormat p, ShowPatchBasic p, PrimPatchBase p) =>+               [Non p wX] -> Doc+displayNons p = showNons ForDisplay p++showFL :: ShowPatchBasic p => ShowPatchFor -> FL p wX wY -> Doc+showFL f = vcat . mapFL (showPatch f)
src/Darcs/Patch/Viewing.hs view
@@ -16,18 +16,16 @@ -- Boston, MA 02110-1301, USA.  {-# OPTIONS_GHC -fno-warn-orphans -fno-warn-unused-imports #-}-{-# LANGUAGE CPP #-}  module Darcs.Patch.Viewing     ( showContextHunk-    , showContextSeries     ) where  import Prelude () import Darcs.Prelude  import Control.Applicative( (<$>) )-import qualified Data.ByteString as BS ( null )+import qualified Data.ByteString as B ( null ) import Prelude hiding ( pi, readFile ) import Darcs.Util.Tree ( Tree ) import Darcs.Util.Tree.Monad ( virtualTreeMonad )@@ -38,24 +36,26 @@ import Darcs.Patch.FileHunk ( IsHunk(..), FileHunk(..), showFileHunk ) import Darcs.Patch.Format ( PatchListFormat(..), ListFormat(..),                             FileNameFormat(..) )-import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatch(..), formatFileName )+import Darcs.Patch.Show+    ( ShowPatchBasic(..), ShowPatch(..)+    , formatFileName, ShowPatchFor(..), ShowContextPatch(..) ) import Darcs.Patch.Witnesses.Ordered ( RL(..), FL(..), mapFL, mapFL_FL,                                        reverseRL, concatFL ) import Darcs.Util.ByteString ( linesPS ) import Darcs.Util.Printer ( Doc, empty, vcat, text, blueText, Color(Cyan, Magenta),                  lineColor, ($$), (<+>), prefix, userchunkPS ) -showContextSeries :: forall p m wX wY . (Apply p, ShowPatch p, IsHunk p,+showContextSeries :: forall p m wX wY . (Apply p, ShowContextPatch p, IsHunk p,                                          ApplyMonad (ApplyState p) m)-                  => FL p wX wY -> m Doc-showContextSeries = scs Nothing+                  => ShowPatchFor -> FileNameFormat -> FL p wX wY -> m Doc+showContextSeries use fmt = scs Nothing   where     scs :: forall wWw wXx wYy . Maybe (FileHunk wWw wXx) -> FL p wXx wYy -> m Doc     scs pold (p :>: ps) = do         (_, s') <- nestedApply (apply p) =<< getApplyState         case isHunk p of             Nothing -> do-                a <- showContextPatch p+                a <- showContextPatch use p                 b <- nestedApply (scs Nothing ps) s'                 return $ a $$ fst b             Just fh -> case ps of@@ -69,29 +69,30 @@     cool :: Maybe (FileHunk wA wB) -> FileHunk wB wC -> Maybe (FileHunk wC wD)          -> (ApplyState p) (ApplyMonadBase m) -> (ApplyMonadBase m) Doc     cool pold fh ps s =-        fst <$> virtualTreeMonad (coolContextHunk pold fh ps) (toTree s)+        fst <$> virtualTreeMonad (coolContextHunk fmt pold fh ps) (toTree s) -showContextHunk :: (ApplyMonad Tree m) => FileHunk wX wY -> m Doc-showContextHunk h = coolContextHunk Nothing h Nothing+showContextHunk :: (ApplyMonad Tree m) => FileNameFormat -> FileHunk wX wY -> m Doc+showContextHunk fmt h = coolContextHunk fmt Nothing h Nothing  coolContextHunk :: (ApplyMonad Tree m)-                => Maybe (FileHunk wA wB) -> FileHunk wB wC+                => FileNameFormat+                -> Maybe (FileHunk wA wB) -> FileHunk wB wC                 -> Maybe (FileHunk wC wD) -> m Doc-coolContextHunk prev fh@(FileHunk f l o n) next = do+coolContextHunk fmt prev fh@(FileHunk f l o n) next = do     have <- mDoesFileExist f     content <- if have then Just `fmap` mReadFilePS f else return Nothing     case linesPS `fmap` content of-        -- This is a weird error...-        Nothing -> return $ showFileHunk OldFormat fh+        -- FIXME This is a weird error...+        Nothing -> return $ showFileHunk fmt fh         Just ls ->             let pre = take numpre $ drop (l - numpre - 1) ls                 cleanedls = case reverse ls of                     (x : xs)-                        | BS.null x -> reverse xs+                        | B.null x -> reverse xs                     _ -> ls                 post = take numpost $ drop (max 0 $ l+length o-1) cleanedls in             return $-                blueText "hunk" <+> formatFileName OldFormat f+                blueText "hunk" <+> formatFileName fmt f                     <+> text (show l)                 $$ prefix " " (vcat $ map userchunkPS pre)                 $$ lineColor Magenta (prefix "-" (vcat $ map userchunkPS o))@@ -111,33 +112,36 @@         _ -> 3  instance (PatchListFormat p, ShowPatchBasic p) => ShowPatchBasic (FL p) where-    showPatch = showPatchInternal patchListFormat+    showPatch ForDisplay = vcat . mapFL (showPatch ForDisplay)+    showPatch ForStorage = showPatchInternal patchListFormat       where         showPatchInternal :: ListFormat p -> FL p wX wY -> Doc-        showPatchInternal ListFormatV1 (p :>: NilFL) = showPatch p+        showPatchInternal ListFormatV1 (p :>: NilFL) = (showPatch ForStorage) p         showPatchInternal ListFormatV1 NilFL = blueText "{" $$ blueText "}"         showPatchInternal ListFormatV1 ps = blueText "{"-                                            $$ vcat (mapFL showPatch ps)+                                            $$ vcat (mapFL (showPatch ForStorage) ps)                                             $$ blueText "}"-        showPatchInternal ListFormatV2 ps = vcat (mapFL showPatch ps)-        showPatchInternal ListFormatDefault ps = vcat (mapFL showPatch ps)+        showPatchInternal ListFormatV2 ps = vcat (mapFL (showPatch ForStorage) ps)+        showPatchInternal ListFormatDefault ps = vcat (mapFL (showPatch ForStorage) ps) -instance (Apply p, IsHunk p, PatchListFormat p, ShowPatch p)-        => ShowPatch (FL p) where-    showContextPatch = showContextPatchInternal patchListFormat+instance (Apply p, IsHunk p, PatchListFormat p, ShowContextPatch p)+        => ShowContextPatch (FL p) where+    showContextPatch ForDisplay = showContextSeries ForDisplay UserFormat+    showContextPatch ForStorage = showContextPatchInternal patchListFormat       where         showContextPatchInternal :: (ApplyMonad (ApplyState (FL p)) m)                                  => ListFormat p -> FL p wX wY -> m Doc         showContextPatchInternal ListFormatV1 (p :>: NilFL) =-            showContextPatch p+            showContextPatch ForStorage p         showContextPatchInternal ListFormatV1 NilFL =             return $ blueText "{" $$ blueText "}"         showContextPatchInternal ListFormatV1 ps = do-            x <- showContextSeries ps+            x <- showContextSeries ForStorage OldFormat ps             return $ blueText "{" $$ x $$ blueText "}"-        showContextPatchInternal ListFormatV2 ps = showContextSeries ps-        showContextPatchInternal ListFormatDefault ps = showContextSeries ps+        showContextPatchInternal ListFormatV2 ps = showContextSeries ForStorage NewFormat ps+        showContextPatchInternal ListFormatDefault ps = showContextSeries ForStorage NewFormat ps +instance (PatchListFormat p, ShowPatch p) => ShowPatch (FL p) where     description = vcat . mapFL description      summary = summaryFL@@ -152,12 +156,13 @@     things = thing  instance (PatchListFormat p, ShowPatchBasic p) => ShowPatchBasic (RL p) where-    showPatch = showPatch . reverseRL+    showPatch f = showPatch f . reverseRL -instance (Apply p, IsHunk p, PatchListFormat p, ShowPatch p)-        => ShowPatch (RL p) where-    showContextPatch = showContextPatch . reverseRL+instance (ShowContextPatch p, Apply p, IsHunk p, PatchListFormat p)+        => ShowContextPatch (RL p) where+    showContextPatch use = showContextPatch use . reverseRL +instance (PatchListFormat p, ShowPatch p) => ShowPatch (RL p) where     description = description . reverseRL      summary = summary . reverseRL
src/Darcs/Patch/Witnesses/Eq.hs view
@@ -1,6 +1,6 @@ module Darcs.Patch.Witnesses.Eq     ( EqCheck(..)-    , MyEq(..)+    , Eq2(..)     , isIsEq     ) where @@ -26,7 +26,7 @@  -- |An witness aware equality class. -- A minimal definition defines any one of 'unsafeCompare', '=\/=' and '=/\='.-class MyEq p where+class Eq2 p where     -- |It is unsafe to define a class instance via this method, because     -- if it returns True then the default implementations of '=\/=' and '=/\='     -- will coerce the equality of two witnesses.
src/Darcs/Patch/Witnesses/Ordered.hs view
@@ -15,8 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.Patch.Witnesses.Ordered     (      -- * Directed Types@@ -30,50 +28,58 @@     , (:/\:)(..)     , (:||:)(..)     , Fork(..)-    -- * Functions+    -- * Functions for 'FL's and 'RL's+    , nullFL+    , nullRL     , lengthFL+    , lengthRL     , mapFL+    , mapRL     , mapFL_FL-    , spanFL+    , mapRL_RL     , foldlFL+    , foldlRL     , allFL+    , allRL     , anyFL+    , anyRL     , filterFL+    , filterRL     , splitAtFL     , splitAtRL-    , bunchFL-    , foldlRL-    , lengthRL-    , isShorterThanRL-    , mapRL-    , mapRL_RL-    , zipWithFL     , filterOutFLFL     , filterOutRLRL-    , filterRL     , reverseFL     , reverseRL     , (+>+)     , (+<+)-    , nullFL+    , (+>>+)+    , (+<<+)     , concatFL     , concatRL-    , snocRLSealed-    , nullRL-    , toFL     , dropWhileFL     , dropWhileRL+    -- * 'FL' only+    , bunchFL+    , foldFL_M+    , spanFL     , spanFL_M+    , zipWithFL+    , toFL     , mapFL_FL_M+    , sequenceFL_     , eqFL     , eqFLRev     , eqFLUnsafe+    , initsFL+    -- * 'RL' only+    , isShorterThanRL+    , snocRLSealed     ) where  import Prelude () import Darcs.Prelude -#include "impossible.h" import Darcs.Patch.Witnesses.Show import Darcs.Patch.Witnesses.Sealed     ( FlippedSeal(..)@@ -84,7 +90,7 @@     , Sealed2(..)     , seal     )-import Darcs.Patch.Witnesses.Eq ( MyEq(..), EqCheck(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) )  -- * Directed Types @@ -221,11 +227,11 @@ instance (Show2 a, Show2 b) => Show ( (a :> b) wX wY ) where     showsPrec d (x :> y) = showOp2 1 ":>" d x y -instance (MyEq a, MyEq b) => MyEq (a :> b) where+instance (Eq2 a, Eq2 b) => Eq2 (a :> b) where     (a1 :> b1) =\/= (a2 :> b2) | IsEq <- a1 =\/= a2 = b1 =\/= b2                                | otherwise = NotEq -instance (MyEq a, MyEq b) => Eq ((a :> b) wX wY) where+instance (Eq2 a, Eq2 b) => Eq ((a :> b) wX wY) where     (==) = unsafeCompare  instance (Show2 a, Show2 b) => Show2 (a :> b) where@@ -262,7 +268,7 @@ filterOutFLFL :: (forall wX wY . p wX wY -> EqCheck wX wY) -> FL p wW wZ -> FL p wW wZ filterOutFLFL _ NilFL = NilFL filterOutFLFL f (x:>:xs) | IsEq <- f x = filterOutFLFL f xs-                    | otherwise = x :>: filterOutFLFL f xs+                         | otherwise = x :>: filterOutFLFL f xs  filterOutRLRL :: (forall wX wY . p wX wY -> EqCheck wX wY) -> RL p wW wZ -> RL p wW wZ filterOutRLRL _ NilRL = NilRL@@ -344,6 +350,14 @@           bFL bs = case splitAtFL n bs of                    a :> b -> a :>: bFL b +-- | Monadic fold over an 'FL'+-- associating to the left, i.e. from left to right.+-- The order of arguments follows the standard 'foldM' from base.+foldFL_M :: Monad m+         => (forall wA wB. r wA -> p wA wB -> m (r wB))+         -> r wX -> FL p wX wY -> m (r wY)+foldFL_M _ r NilFL = return r+foldFL_M f r (x :>: xs) = f r x >>= \r' -> foldFL_M f r' xs  allFL :: (forall wX wY . a wX wY -> Bool) -> FL a wW wZ -> Bool allFL f xs = and $ mapFL f xs@@ -351,6 +365,12 @@ anyFL :: (forall wX wY . a wX wY -> Bool) -> FL a wW wZ -> Bool anyFL f xs = or $ mapFL f xs +allRL :: (forall wA wB . a wA wB -> Bool) -> RL a wX wY -> Bool+allRL f xs = and $ mapRL f xs++anyRL :: (forall wA wB . a wA wB -> Bool) -> RL a wX wY -> Bool+anyRL f xs = or $ mapRL f xs+ foldlFL :: (forall wW wY . a -> b wW wY -> a) -> a -> FL b wX wZ -> a foldlFL _ x NilFL = x foldlFL f x (y:>:ys) = foldlFL f (f x y) ys@@ -369,6 +389,9 @@                            bs <- mapFL_FL_M f as                            return (b:>:bs) +sequenceFL_ :: Monad m => (forall wW wZ . a wW wZ -> m b) -> FL a wX wY -> m ()+sequenceFL_ f = sequence_ . mapFL f+ zipWithFL :: (forall wX wY . a -> p wX wY -> q wX wY)           -> [a] -> FL p wW wZ -> FL q wW wZ zipWithFL f (x:xs) (y :>: ys) = f x y :>: zipWithFL f xs ys@@ -430,19 +453,38 @@           | otherwise = seal xs  -- |Check that two 'FL's are equal element by element.--- This differs from the 'MyEq' instance for 'FL' which+-- This differs from the 'Eq2' instance for 'FL' which -- uses commutation.-eqFL :: MyEq a => FL a wX wY -> FL a wX wZ -> EqCheck wY wZ+eqFL :: Eq2 a => FL a wX wY -> FL a wX wZ -> EqCheck wY wZ eqFL NilFL NilFL = IsEq eqFL (x:>:xs) (y:>:ys) | IsEq <- x =\/= y, IsEq <- eqFL xs ys = IsEq eqFL _ _ = NotEq -eqFLRev :: MyEq a => FL a wX wZ -> FL a wY wZ -> EqCheck wX wY+eqFLRev :: Eq2 a => FL a wX wZ -> FL a wY wZ -> EqCheck wX wY eqFLRev NilFL NilFL = IsEq eqFLRev (x:>:xs) (y:>:ys) | IsEq <- eqFLRev xs ys, IsEq <- x =/\= y = IsEq eqFLRev _ _ = NotEq -eqFLUnsafe :: MyEq a => FL a wX wY -> FL a wZ wW -> Bool+eqFLUnsafe :: Eq2 a => FL a wX wY -> FL a wZ wW -> Bool eqFLUnsafe NilFL NilFL = True eqFLUnsafe (x:>:xs) (y:>:ys) = unsafeCompare x y && eqFLUnsafe xs ys eqFLUnsafe _ _ = False++infixr 5 +>>++infixl 5 +<<+++-- | Prepend an 'RL' to an 'FL'. This traverses only the left hand side.+(+>>+) :: RL p wX wY -> FL p wY wZ -> FL p wX wZ+NilRL +>>+ ys = ys+(xs:<:x) +>>+ ys = xs +>>+ (x :>: ys)++-- | Append an 'FL' to an 'RL'. This traverses only the right hand side.+(+<<+) :: RL p wX wY -> FL p wY wZ -> RL p wX wZ+xs +<<+ NilFL = xs+xs +<<+ (y:>:ys) = (xs:<:y) +<<+ ys++initsFL :: FL p wX wY -> [Sealed ((p :> FL p) wX)]+initsFL NilFL = []+initsFL (x :>: xs) =+    Sealed (x :> NilFL) :+    map (\(Sealed (y :> xs')) -> Sealed (x :> y :>: xs')) (initsFL xs)
src/Darcs/Patch/Witnesses/Sealed.hs view
@@ -15,7 +15,7 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, FlexibleInstances #-}+{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS_HADDOCK ignore-exports #-}  module Darcs.Patch.Witnesses.Sealed@@ -46,7 +46,7 @@ import Prelude () import Darcs.Prelude -import Darcs.Patch.Witnesses.Eq ( MyEq, EqCheck(..) )+import Darcs.Patch.Witnesses.Eq ( Eq2, EqCheck(..) ) import Darcs.Patch.Witnesses.Show import Darcs.Patch.Witnesses.Eq ( (=\/=) ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP1, unsafeCoerceP )@@ -60,7 +60,7 @@ seal :: a wX -> Sealed a seal = Sealed -instance MyEq a => Eq (Sealed (a wX)) where+instance Eq2 a => Eq (Sealed (a wX)) where     Sealed x == Sealed y | IsEq <- x =\/= y = True                          | otherwise = False @@ -139,7 +139,7 @@ -- of the type witnesses. newtype FreeLeft p = FLInternal (Poly (Stepped Sealed p)) --- |'FreeLeft' p is @ \forall y . \exists x . p x y @+-- |'FreeRight' p is @ \forall y . \exists x . p x y @ -- In other words the caller is free to specify the right witness, -- and then the left witness is an existential. -- Note that the order of the type constructors is important for ensuring
src/Darcs/Patch/Witnesses/Show.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE CPP #-}- module Darcs.Patch.Witnesses.Show     ( ShowDict(..)     , showD
src/Darcs/Patch/Witnesses/Unsafe.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE MagicHash #-} module Darcs.Patch.Witnesses.Unsafe     ( unsafeCoerceP     , unsafeCoercePStart@@ -7,19 +6,19 @@     , unsafeCoerceP1     ) where -import GHC.Base (unsafeCoerce#)+import Unsafe.Coerce  unsafeCoerceP :: a wX wY -> a wB wC-unsafeCoerceP = unsafeCoerce#+unsafeCoerceP = unsafeCoerce  unsafeCoercePStart :: a wX1 wY -> a wX2 wY-unsafeCoercePStart = unsafeCoerce#+unsafeCoercePStart = unsafeCoerce  unsafeCoercePEnd :: a wX wY1 -> a wX wY2-unsafeCoercePEnd = unsafeCoerce#+unsafeCoercePEnd = unsafeCoerce  unsafeCoerceP2 :: t wW wX wY wZ -> t wA wB wC wD-unsafeCoerceP2 = unsafeCoerce#+unsafeCoerceP2 = unsafeCoerce  unsafeCoerceP1 :: a wX -> a wY-unsafeCoerceP1 = unsafeCoerce#+unsafeCoerceP1 = unsafeCoerce
src/Darcs/Patch/Witnesses/WZipper.hs view
@@ -15,8 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.Patch.Witnesses.WZipper     ( FZipper(..)     , focus
src/Darcs/Prelude.hs view
@@ -2,27 +2,32 @@ -- BSD3  {--This module abstracts over the differences in the Haskell Prelude over multiple GHC versions,-and also hides some symbols that are exported by the Prelude but clash with common names in-the Darcs code.+This module abstracts over the differences in the Haskell Prelude over+multiple GHC versions, and also hides some symbols that are exported by the+Prelude but clash with common names in the Darcs code. -Broadly it exports everything that the latest Prelude supports, minus the things we explicitly exclude+Broadly it exports everything that the latest Prelude supports, minus the+things we explicitly exclude By default it should be imported with     import Prelude ()     import Darcs.Prelude -If necessary more things can be hidden in the 'Darcs.Prelude' import if they clash with something local,-but consider whether to either hide them globally instead or to choose a different name for the local thing.--If something is needed from the Prelude that's hidden by default, then add it to the Prelude import.+If necessary more things can be hidden in the 'Darcs.Prelude' import if they+clash with something local, but consider whether to either hide them+globally instead or to choose a different name for the local thing. +If something is needed from the Prelude that's hidden by default, then add+it to the Prelude import. -}  module Darcs.Prelude     ( module Prelude     , module Control.Applicative     , module Data.Monoid+    , module Data.Semigroup     , module Data.Traversable+    , module Data.Maybe+    , impossible, bug     ) where  import Prelude hiding@@ -30,12 +35,16 @@       -- because it's a good name for a PatchInfo       pi     ,-      -- because they're in the new Prelude but only in Control.Applicative in older GHCs+      -- because they're in the new Prelude but only in Control.Applicative+      -- in older GHCs       Applicative(..), (<$>), (<*>)     ,       -- because it's in the new Prelude but only in Data.Monoid in older GHCs       Monoid(..)     ,+      -- because it's in the new Prelude but only in Data.Semigroup in older GHCs+      Semigroup(..)+    ,       -- because it's in the new Prelude but only in Data.Traversable in older GHCs       traverse     ,@@ -51,4 +60,13 @@  import Control.Applicative ( Applicative(..), (<$>), (<*>) ) import Data.Monoid ( Monoid(..) )+import Data.Semigroup ( Semigroup(..) ) import Data.Traversable ( traverse )+import Data.Maybe ( fromJust )++impossible :: a+impossible = error "Impossible case"++bug :: String -> a+bug str = error ("This is a bug! Please report it at http://darcs.net\n" ++ str)+
src/Darcs/Repository.hs view
@@ -16,9 +16,13 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, ScopedTypeVariables #-} module Darcs.Repository     ( Repository+    , repoLocation+    , repoFormat+    , repoPristineType+    , repoCache+    , PristineType(..)     , HashedDir(..)     , Cache(..)     , CacheLoc(..)@@ -30,7 +34,8 @@     , withRepoLock     , withRepoLockCanFail     , withRepository-    , withRepositoryDirectory+    , withRepositoryLocation+    , withUMaskFlag     , writePatchSet     , findRepository     , amInRepository@@ -40,7 +45,6 @@     , readRepo     , prefsUrl     , repoPatchType-    , readRepoUsingSpecificInventory     , addToPending     , addPendingDiffToPending     , tentativelyAddPatch@@ -54,8 +58,10 @@     , revertRepositoryChanges     , finalizeRepositoryChanges     , createRepository+    , createRepositoryV1+    , createRepositoryV2+    , EmptyRepository(..)     , cloneRepository-    , patchSetToRepository     , unrevertUrl     , applyToWorking     , createPristineDirectoryTree@@ -67,7 +73,6 @@     , PatchInfoAnd     , setScriptsExecutable     , setScriptsExecutablePatches-    , checkUnrelatedRepos     , testTentative     , modifyCache     , reportBadSources@@ -75,77 +80,66 @@     , readRecorded     , readUnrecorded     , unrecordedChanges-    , unrecordedChangesWithPatches     , filterOutConflicts     , readPending     , readRecordedAndPending     -- * Index.     , readIndex     , invalidateIndex-    -- * Used as command arguments-    , listFiles-    , listRegisteredFiles-    , listUnregisteredFiles     ) where -import Prelude ()-import Darcs.Prelude--import Control.Monad ( unless, when )-import Data.List ( (\\) )-import System.Exit ( exitSuccess )- import Darcs.Repository.State     ( readRecorded     , readUnrecorded     , unrecordedChanges-    , unrecordedChangesWithPatches-    , readPendingAndWorking     , readPending     , readIndex     , invalidateIndex     , readRecordedAndPending-    , restrictDarcsdir-    , restrictBoring-    , applyTreeFilter     , filterOutConflicts+    , addPendingDiffToPending+    , addToPending     ) -import Darcs.Repository.Internal-    ( Repository(..)-    , maybeIdentifyRepository+import Darcs.Repository.Prefs ( prefsUrl )++import Darcs.Repository.Identify+    ( maybeIdentifyRepository     , identifyRepositoryFor     , findRepository     , amInRepository     , amNotInRepository     , amInHashedRepository-    , readRepo+    )+import Darcs.Repository.Hashed+    ( readRepo     , readTentativeRepo-    , readRepoUsingSpecificInventory-    , prefsUrl     , withRecorded     , tentativelyAddPatch     , tentativelyRemovePatches-    , tentativelyAddToPending     , revertRepositoryChanges     , finalizeRepositoryChanges     , unrevertUrl-    , applyToWorking     , createPristineDirectoryTree     , createPartialsPristineDirectoryTree     , reorderInventory     , cleanRepository+    )+import Darcs.Repository.Pending+    ( tentativelyAddToPending+    )+import Darcs.Repository.Working+    ( applyToWorking     , setScriptsExecutable     , setScriptsExecutablePatches-    , makeNewPending-    , repoPatchType     ) import Darcs.Repository.Job     ( RepoJob(..)     , withRepoLock     , withRepoLockCanFail     , withRepository-    , withRepositoryDirectory+    , withRepositoryLocation+    , withUMaskFlag     ) import Darcs.Repository.Rebase ( RebaseJobFlags(..), withManualRebaseUpdate ) import Darcs.Repository.Test ( testTentative )@@ -158,111 +152,27 @@                               , WritableOrNot(..)                               , reportBadSources                               )-import Darcs.Repository.InternalTypes ( modifyCache )-import Darcs.Repository.Flags-    ( DiffAlgorithm (..)-    , ScanKnown(..)-    , UpdateWorking(..)-    , UseCache(..)-    , UseIndex(..)+import Darcs.Repository.InternalTypes+    ( Repository+    , PristineType(..)+    , modifyCache+    , repoPatchType+    , repoLocation+    , repoFormat+    , repoPristineType+    , repoCache     ) import Darcs.Repository.Clone-    ( createRepository-    , cloneRepository+    ( cloneRepository     , replacePristine     , writePatchSet-    , patchSetToRepository     )+import Darcs.Repository.Create+    ( createRepository+    , createRepositoryV1+    , createRepositoryV2+    , EmptyRepository(..)+    ) -import Darcs.Patch ( RepoPatch-                   , PrimOf-                   )-import Darcs.Patch.Set ( PatchSet(..)-                       , SealedPatchSet-                       )-import Darcs.Patch.Commute( commuteFL )-import Darcs.Patch.Permutations ( genCommuteWhatWeCanRL )+import Darcs.Patch.Set ( PatchSet(..), SealedPatchSet ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd )-import Darcs.Patch.Apply( ApplyState )-import Darcs.Patch.Witnesses.Sealed ( Sealed(..), FreeLeft, unFreeLeft )-import Darcs.Patch.Witnesses.Ordered-       ( (:>)(..)-       , reverseRL-       , reverseFL-       , FL(..)-       , (+>+)-       )-import Darcs.Patch.Depends ( areUnrelatedRepos )--import Darcs.Util.Prompt ( promptYorn )-import Darcs.Util.Path( anchorPath )--import Darcs.Util.Tree( Tree, emptyTree, expand, list )-import Darcs.Util.Tree.Plain( readPlainTree )--checkUnrelatedRepos :: RepoPatch p-                    => Bool-                    -> PatchSet rt p wStart wX-                    -> PatchSet rt p wStart wY-                    -> IO ()-checkUnrelatedRepos allowUnrelatedRepos us them =-    when ( not allowUnrelatedRepos && areUnrelatedRepos us them ) $-         do confirmed <- promptYorn "Repositories seem to be unrelated. Proceed?"-            unless confirmed $ do putStrLn "Cancelled."-                                  exitSuccess---- | Add an FL of patches started from the pending state to the pending patch.--- TODO: add witnesses for pending so we can make the types precise: currently--- the passed patch can be applied in any context, not just after pending.-addPendingDiffToPending :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)-                          => Repository rt p wR wU wT -> UpdateWorking-                          -> FreeLeft (FL (PrimOf p)) -> IO ()-addPendingDiffToPending _ NoUpdateWorking  _ = return ()-addPendingDiffToPending repo@(Repo{}) uw@YesUpdateWorking newP = do-    (toPend :> _) <--        readPendingAndWorking (UseIndex, ScanKnown, MyersDiff) repo Nothing-    invalidateIndex repo-    case unFreeLeft newP of-        (Sealed p) -> makeNewPending repo uw $ toPend +>+ p---- | Add a FL of patches starting from the working state to the pending patch,--- including as much extra context as is necessary (context meaning--- dependencies), by commuting the patches to be added past as much of the--- changes between pending and working as is possible, and including anything--- that doesn't commute, and the patch itself in the new pending patch.-addToPending :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)-             => Repository rt p wR wU wT -> UpdateWorking -> FL (PrimOf p) wU wY -> IO ()-addToPending _ NoUpdateWorking  _ = return ()-addToPending repo@(Repo{}) uw@YesUpdateWorking p = do-   (toPend :> toUnrec) <- readPendingAndWorking (UseIndex, ScanKnown, MyersDiff) repo Nothing-   invalidateIndex repo-   case genCommuteWhatWeCanRL commuteFL (reverseFL toUnrec :> p) of-       (toP' :> p'  :> _excessUnrec) ->-           makeNewPending repo uw $ toPend +>+ reverseRL toP' +>+ p'---- | Get a list of all files and directories in the working copy, including--- boring files if necessary-listFiles :: Bool -> IO [String]-listFiles takeBoring =-  do-    nonboring <- considered emptyTree-    working <- expand =<< applyTreeFilter nonboring <$> readPlainTree "."-    return $ map (anchorPath "" . fst) $ list working-  where-    considered = if takeBoring-                 then const (return restrictDarcsdir)-                 else restrictBoring---- | 'listUnregisteredFiles' returns the list of all non-boring unregistered--- files in the repository.-listUnregisteredFiles :: Bool -> IO [String]-listUnregisteredFiles includeBoring =-    do unregd <- listFiles includeBoring-       regd <- listRegisteredFiles-       return $ unregd \\ regd -- (inefficient)---- | 'listRegisteredFiles' returns the list of all registered files in the repository.-listRegisteredFiles :: IO [String]-listRegisteredFiles =-    do recorded <- expand =<< withRepository YesUseCache (RepoJob readRecordedAndPending)-       return $ map (anchorPath "" . fst) $ list recorded
src/Darcs/Repository/ApplyPatches.hs view
@@ -47,7 +47,7 @@  import Darcs.Util.Exception ( prettyException ) import Darcs.Util.Progress ( beginTedious, endTedious, tediousSize, finishedOneIO )-import Darcs.Util.Printer ( hPutDocLn, RenderMode(..) )+import Darcs.Util.Printer ( hPutDocLn ) import Darcs.Util.Printer.Color ( showDoc ) import Darcs.Util.External ( backupByCopying, backupByRenaming ) import Darcs.Util.Path ( FileName, fn2fp )@@ -66,9 +66,9 @@        mapM_ go items        endTedious what     where go item =-            do finishedOneIO what (showDoc Encode $ paMessage item)+            do finishedOneIO what (showDoc $ paMessage item)                runDefaultIO (paAction item) `catch` \e ->-                 do hPutDocLn Encode stderr $ paOnError item+                 do hPutDocLn stderr $ paOnError item                     ioError e  instance ApplyMonad Tree DefaultIO where
src/Darcs/Repository/Cache.hs view
@@ -1,9 +1,6 @@-{-# LANGUAGE CPP #-}- module Darcs.Repository.Cache     ( cacheHash     , okayHash-    , takeHash     , Cache(..)     , CacheType(..)     , CacheLoc(..)@@ -29,11 +26,10 @@     , reportBadSources     ) where -import Control.Monad ( liftM, when, guard, unless, filterM, forM_, mplus )-import qualified Data.ByteString as B (length, drop, ByteString )-import qualified Data.ByteString.Char8 as BC (unpack)+import Control.Monad ( liftM, when, unless, filterM, forM_, mplus )+import qualified Data.ByteString as B (length, ByteString ) import Data.List ( nub, intercalate )-import Data.Maybe ( catMaybes, listToMaybe, fromMaybe )+import Data.Maybe ( catMaybes, fromMaybe ) import System.FilePath.Posix ( (</>), joinPath, dropFileName ) import System.Directory ( createDirectoryIfMissing, removeFile, doesFileExist,                           doesDirectoryExist, getDirectoryContents,@@ -42,7 +38,7 @@ import System.IO ( hPutStrLn, stderr ) import System.Posix.Files ( createLink, linkCount, getSymbolicLinkStatus ) -import Darcs.Util.ByteString ( gzWriteFilePS, linesPS )+import Darcs.Util.ByteString ( gzWriteFilePS ) import Darcs.Util.Global ( darcsdir, addBadSource, isBadSource, addReachableSource,                       isReachableSource, getBadSourcesList, defaultRemoteDarcsCmd ) import Darcs.Util.External ( gzFetchFilePS, fetchFilePS@@ -54,8 +50,7 @@ import Darcs.Util.SignalHandler ( catchNonSignal ) import Darcs.Util.URL ( isValidLocalPath, isHttpUrl, isSshUrl ) import Darcs.Util.File ( withCurrentDirectory )-import Darcs.Util.Crypt.SHA1 ( sha1PS )-import Darcs.Util.Crypt.SHA256 ( sha256sum )+import Darcs.Util.Hash ( sha256sum ) import Darcs.Util.English ( englishNum, Noun(..), Pronoun(..) ) import Darcs.Util.Exception ( catchall ) import Darcs.Util.Progress ( progressList, debugMessage, debugFail )@@ -178,18 +173,10 @@     shaOfPs = sha256sum ps  okayHash :: String -> Bool-okayHash s = length s `elem` [40, 64, 75]--takeHash :: B.ByteString -> Maybe (String, B.ByteString)-takeHash ps = do-    h <- listToMaybe $ linesPS ps-    let v = BC.unpack h-    guard $ okayHash v-    return (v, B.drop (B.length h) ps)+okayHash s = length s `elem` [64, 75]  checkHash :: String -> B.ByteString -> Bool checkHash h s-    | length h == 40 = (show $ sha1PS s) == h     | length h == 64 = sha256sum s == h     | length h == 75 =         B.length s == read (take 10 h) && sha256sum s == drop 11 h
src/Darcs/Repository/Clone.hs view
@@ -1,53 +1,53 @@-{-# LANGUAGE CPP, ScopedTypeVariables #-} module Darcs.Repository.Clone-    ( createRepository-    , cloneRepository+    ( cloneRepository     , replacePristine     , writePatchSet-    , patchSetToRepository     ) where  import Prelude () import Darcs.Prelude  import Control.Exception ( catch, SomeException )-import Control.Monad ( when, void )-import qualified Data.ByteString.Char8 as BS+import Control.Monad ( when )+import qualified Data.ByteString.Char8 as BC import Data.List( intercalate )-import Data.Maybe( catMaybes, isJust )+import Data.Maybe( catMaybes ) import System.FilePath( (</>) ) import System.Directory-    ( createDirectory-    , removeFile+    ( removeFile     , getDirectoryContents-    , getCurrentDirectory-    , setCurrentDirectory     ) import System.IO ( stderr )-import System.IO.Error ( isAlreadyExistsError ) -import Darcs.Repository.State ( invalidateIndex, readWorking )--import Darcs.Repository.Internal-    ( Repository(..)-    , IdentifyRepo(..)+import Darcs.Repository.Create+    ( EmptyRepository(..)+    , createRepository+    , writePristine+    )+import Darcs.Repository.State ( invalidateIndex )+import Darcs.Repository.Pending ( tentativelyAddToPending )+import Darcs.Repository.Identify+    ( IdentifyRepo(..)     , identifyRepositoryFor-    , identifyRepository-    , maybeIdentifyRepository-    , readRepo+    , maybeIdentifyRepository )+import Darcs.Repository.Hashed+    ( readRepo     , tentativelyRemovePatches-    , tentativelyAddToPending     , finalizeRepositoryChanges     , createPristineDirectoryTree-    , setScriptsExecutable-    , setScriptsExecutablePatches-    , seekRepo-    , repoPatchType     , revertRepositoryChanges     )+import Darcs.Repository.Working+    ( setScriptsExecutable+    , setScriptsExecutablePatches ) import Darcs.Repository.InternalTypes-    ( modifyCache )-import Darcs.Repository.Job ( RepoJob(..), withRepoLock, withRepository )+    ( Repository+    , repoLocation+    , repoFormat+    , repoCache+    , modifyCache+    , repoPatchType )+import Darcs.Repository.Job ( withUMaskFlag ) import Darcs.Repository.Cache     ( unionRemoteCaches     , unionCaches@@ -60,22 +60,19 @@     ) import qualified Darcs.Repository.Cache as DarcsCache -import qualified Darcs.Repository.HashedRepo as HashedRepo-import Darcs.Repository.ApplyPatches ( applyPatches, runDefault )-import Darcs.Repository.HashedRepo-    ( applyToTentativePristine-    , pris2inv-    , inv2pris+import qualified Darcs.Repository.Hashed as HashedRepo+import Darcs.Repository.ApplyPatches ( runDefault )+import Darcs.Repository.Hashed+    ( applyToTentativePristineCwd+    , peekPristineHash     ) import Darcs.Repository.Format     ( RepoProperty ( HashedInventory, Darcs2 )     , RepoFormat-    , createRepoFormat     , formatHas-    , writeRepoFormat     , readProblem     )-import Darcs.Repository.Prefs ( writeDefaultPrefs, addRepoSource, deleteSources )+import Darcs.Repository.Prefs ( addRepoSource, deleteSources ) import Darcs.Repository.Match ( getOnePatchset ) import Darcs.Util.External     ( copyFileOrUrl@@ -83,8 +80,7 @@     , gzFetchFilePS     ) import Darcs.Repository.PatchIndex-    ( createOrUpdatePatchIndexDisk-    , doesPatchIndexExist+    ( doesPatchIndexExist     , createPIWithInterrupt     ) import Darcs.Repository.Packs@@ -92,11 +88,7 @@     , fetchAndUnpackPatches     , packsDir     )-import Darcs.Util.Lock-    ( writeBinFile-    , writeDocBinFile-    , appendBinFile-    )+import Darcs.Util.Lock ( appendTextFile, withNewDirectory ) import Darcs.Repository.Flags     ( UpdateWorking(..)     , UseCache(..)@@ -116,12 +108,12 @@     , PatchFormat (..)     ) -import Darcs.Patch ( RepoPatch, IsRepoType, apply, invert, effect, PrimOf )+import Darcs.Patch ( RepoPatch, IsRepoType, apply, invert, effect ) import Darcs.Patch.Depends ( findCommonWithThem, countUsThem ) import Darcs.Patch.Set ( Origin-                       , PatchSet(..)-                       , newset2RL-                       , newset2FL+                       , PatchSet+                       , patchSet2RL+                       , patchSet2FL                        , progressPatchSet                        ) import Darcs.Patch.Match ( MatchFlag(..), havePatchsetMatch )@@ -140,19 +132,15 @@     ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, extractHash, hopefully ) -import Darcs.Util.Hash( encodeBase16 ) import Darcs.Util.Tree( Tree, emptyTree )-import Darcs.Util.Tree.Hashed( writeDarcsHashed, darcsAddMissingHashes ) -import Darcs.Util.ByteString( gzReadFilePS ) import Darcs.Util.Download ( maxPipelineLength ) import Darcs.Util.Exception ( catchall )-import Darcs.Util.File ( withCurrentDirectory ) import Darcs.Util.English ( englishNum, Noun(..) ) import Darcs.Util.Global ( darcsdir ) import Darcs.Util.URL ( isValidLocalPath ) import Darcs.Util.SignalHandler ( catchInterrupt )-import Darcs.Util.Printer ( Doc, text, hPutDocLn, putDocLn, errorDoc, RenderMode(..) )+import Darcs.Util.Printer ( Doc, text, hPutDocLn, putDocLn, errorDoc ) import Darcs.Util.Progress     ( debugMessage     , tediousSize@@ -160,31 +148,6 @@     , endTedious     ) -#include "impossible.h"--createRepository :: PatchFormat -> WithWorkingDir -> WithPatchIndex -> IO ()-createRepository patchfmt withWorkingDir createPatchIndex = do-  createDirectory darcsdir `catch`-      (\e-> if isAlreadyExistsError e-            then fail "Tree has already been initialized!"-            else fail $ "Error creating directory `"++darcsdir++"'.")-  cwd <- getCurrentDirectory-  x <- seekRepo-  when (isJust x) $ do-      setCurrentDirectory cwd-      putStrLn "WARNING: creating a nested repository."-  createDirectory $ darcsdir </> "pristine.hashed"-  createDirectory $ darcsdir </> "patches"-  createDirectory $ darcsdir </> "inventories"-  createDirectory $ darcsdir </> "prefs"-  writeDefaultPrefs-  writeRepoFormat (createRepoFormat patchfmt withWorkingDir) (darcsdir </> "format")-  writeBinFile (darcsdir </> "hashed_inventory") ""-  writePristine "." emptyTree-  withRepository NoUseCache $ RepoJob $ \repo -> case createPatchIndex of-      NoPatchIndex -> return () -- default-      YesPatchIndex -> createOrUpdatePatchIndexDisk repo- joinUrl :: [String] -> String joinUrl = intercalate "/" @@ -203,41 +166,45 @@     -> Bool   -- use packs     -> ForgetParent     -> IO ()-cloneRepository repodir mysimplename v uc cloneKind um rdarcs sse remoteRepos-                setDefault matchFlags rfsource withWorkingDir usePatchIndex usePacks forget = do-  createDirectory mysimplename-  setCurrentDirectory mysimplename-  createRepository (if formatHas Darcs2 rfsource then PatchFormat2 else PatchFormat1)-                   withWorkingDir-                   (if cloneKind == LazyClone then NoPatchIndex else usePatchIndex)-  debugMessage "Finished initializing new repository."-  addRepoSource repodir NoDryRun remoteRepos setDefault+cloneRepository repodir mysimplename v useCache cloneKind um rdarcs sse remoteRepos+                setDefault matchFlags rfsource withWorkingDir usePatchIndex usePacks+                forget =+  withUMaskFlag um $ withNewDirectory mysimplename $ do+      let patchfmt = if formatHas Darcs2 rfsource then PatchFormat2 else PatchFormat1+      EmptyRepository toRepo' <-+        createRepository patchfmt withWorkingDir+          (if cloneKind == LazyClone then NoPatchIndex else usePatchIndex) useCache+      debugMessage "Finished initializing new repository."+      addRepoSource repodir NoDryRun remoteRepos setDefault -  debugMessage "Grabbing lock in new repository."-  withRepoLock NoDryRun uc YesUpdateWorking um-   $ RepoJob $ \repository -> do       debugMessage "Identifying and copying repository..."-      fromRepo@(Repo fromDir rffrom _ fromCache) <- identifyRepositoryFor repository uc repodir+      fromRepo <- identifyRepositoryFor toRepo' useCache repodir+      let fromLoc = repoLocation fromRepo+      let rffrom = repoFormat fromRepo       case readProblem rffrom of-        Just e ->  fail $ "Incompatibility with repository " ++ fromDir ++ ":\n" ++ e+        Just e ->  fail $ "Incompatibility with repository " ++ fromLoc ++ ":\n" ++ e         Nothing -> return ()-      debugMessage "Copying prefs"-      copyFileOrUrl (remoteDarcs rdarcs) (joinUrl [fromDir, darcsdir, "prefs", "prefs"])+      debugMessage "Copying prefs..."+      copyFileOrUrl (remoteDarcs rdarcs)+        (joinUrl [fromLoc, darcsdir, "prefs", "prefs"])         (darcsdir </> "prefs/prefs") (MaxAge 600) `catchall` return ()-      -- prepare sources and cache-      (Repo toDir toFormat toPristine toCache) <- identifyRepository uc "."-      toCache2 <- unionRemoteCaches toCache fromCache fromDir-      toRepo <- copySources (Repo toDir toFormat toPristine toCache2) fromDir+      debugMessage "Copying sources..."+      cache <- unionRemoteCaches (repoCache toRepo') (repoCache fromRepo) fromLoc+      appendTextFile (darcsdir </> "prefs/sources")+                     (show $ repo2cache fromLoc `unionCaches` dropNonRepos cache)+      debugMessage "Done copying and filtering sources."+      -- put remote source last+      let toRepo = modifyCache toRepo' (const $ cache `unionCaches` repo2cache fromLoc)       if formatHas HashedInventory rffrom then do        -- copying basic repository (hashed_inventory and pristine)-       if usePacks && (not . isValidLocalPath) fromDir+       if usePacks && (not . isValidLocalPath) fromLoc          then copyBasicRepoPacked    fromRepo toRepo v rdarcs withWorkingDir          else copyBasicRepoNotPacked fromRepo toRepo v rdarcs withWorkingDir        when (cloneKind /= LazyClone) $ do          when (cloneKind /= CompleteClone) $            putInfo v $ text "Copying patches, to get lazy repository hit ctrl-C..."        -- copying complete repository (inventories and patches)-         if usePacks && (not . isValidLocalPath) fromDir+         if usePacks && (not . isValidLocalPath) fromLoc            then copyCompleteRepoPacked    fromRepo toRepo v cloneKind            else copyCompleteRepoNotPacked fromRepo toRepo v cloneKind       else@@ -245,8 +212,8 @@        -- we need to copy all patches first and then build pristine        copyRepoOldFashioned fromRepo toRepo v withWorkingDir       when (sse == YesSetScriptsExecutable) setScriptsExecutable-      when (havePatchsetMatch (repoPatchType repository) matchFlags) $ do-        putStrLn "Going to specified version..."+      when (havePatchsetMatch (repoPatchType toRepo) matchFlags) $ do+        putInfo v $ text "Going to specified version..."         -- the following is necessary to be able to read repo's patches         revertRepositoryChanges toRepo YesUpdateWorking         patches <- readRepo toRepo@@ -266,24 +233,33 @@         when (sse == YesSetScriptsExecutable) $ setScriptsExecutablePatches (invert $ effect ps)       when (forget == YesForgetParent) deleteSources +-- | This keeps only NonWritable Repo entries.+dropNonRepos :: Cache -> Cache+dropNonRepos (Ca cache) = Ca $ filter notRepo cache where+  notRepo xs = case xs of+    Cache DarcsCache.Directory _ _ -> False+    -- we don't want to write thisrepo: entries to the disk+    Cache DarcsCache.Repo DarcsCache.Writable _ -> False+    _ -> True+ putInfo :: Verbosity -> Doc -> IO () putInfo Quiet _ = return ()-putInfo _ d = hPutDocLn Encode stderr d+putInfo _ d = hPutDocLn stderr d  putVerbose :: Verbosity -> Doc -> IO () putVerbose Verbose d = putDocLn d putVerbose _ _ = return () -copyBasicRepoNotPacked  :: forall rt p wR wU wT. (RepoPatch p, ApplyState p ~ Tree)-                        => Repository rt p wR wU wT -- remote+copyBasicRepoNotPacked  :: forall rt p wR wU wT.+                           Repository rt p wR wU wT -- remote                         -> Repository rt p wR wU wT -- existing empty local                         -> Verbosity                         -> RemoteDarcs                         -> WithWorkingDir                         -> IO ()-copyBasicRepoNotPacked (Repo fromDir _ _ _) toRepo verb rdarcs withWorkingDir = do+copyBasicRepoNotPacked fromRepo toRepo verb rdarcs withWorkingDir = do   putVerbose verb $ text "Copying hashed inventory from remote repo..."-  HashedRepo.copyHashedInventory toRepo rdarcs fromDir+  HashedRepo.copyHashedInventory toRepo rdarcs (repoLocation fromRepo)   putVerbose verb $ text "Writing pristine and working directory contents..."   createPristineDirectoryTree toRepo "." withWorkingDir @@ -293,31 +269,33 @@                         -> Verbosity                         -> CloneKind                         -> IO ()-copyCompleteRepoNotPacked _ torepository@(Repo todir _ _ _) verb cloneKind = do+copyCompleteRepoNotPacked _ toRepo verb cloneKind = do        let cleanup = putInfo verb $ text "Using lazy repository."        allowCtrlC cloneKind cleanup $ do-         fetchPatchesIfNecessary torepository-         pi <- doesPatchIndexExist todir-         when pi $ createPIWithInterrupt torepository+         fetchPatchesIfNecessary toRepo+         pi <- doesPatchIndexExist (repoLocation toRepo)+         ps <- readRepo toRepo+         when pi $ createPIWithInterrupt toRepo ps  copyBasicRepoPacked ::-  forall rt p wR wU wT. (IsRepoType rt, RepoPatch p, ApplyState (PrimOf p) ~ Tree, ApplyState p ~ Tree)-  => Repository rt p wR wU wT -- remote+  forall rt p wR wU wT.+     Repository rt p wR wU wT -- remote   -> Repository rt p wR wU wT -- existing empty local repository   -> Verbosity   -> RemoteDarcs   -> WithWorkingDir   -> IO ()-copyBasicRepoPacked r@(Repo fromDir _ _ _) toRepo verb rdarcs withWorkingDir =-  do let hashURL = joinUrl [fromDir, darcsdir, packsDir, "pristine"]+copyBasicRepoPacked fromRepo toRepo verb rdarcs withWorkingDir =+  do let fromLoc = repoLocation fromRepo+     let hashURL = joinUrl [fromLoc, darcsdir, packsDir, "pristine"]      mPackHash <- (Just <$> gzFetchFilePS hashURL Uncachable) `catchall` (return Nothing)-     let hiURL = joinUrl [fromDir, darcsdir, "hashed_inventory"]+     let hiURL = joinUrl [fromLoc, darcsdir, "hashed_inventory"]      i <- gzFetchFilePS hiURL Uncachable-     let currentHash = BS.pack $ inv2pris i-     let copyNormally = copyBasicRepoNotPacked r toRepo verb rdarcs withWorkingDir+     let currentHash = BC.pack $ peekPristineHash i+     let copyNormally = copyBasicRepoNotPacked fromRepo toRepo verb rdarcs withWorkingDir      case mPackHash of       Just packHash | packHash == currentHash-              -> ( copyBasicRepoPacked2 r toRepo verb withWorkingDir+              -> ( copyBasicRepoPacked2 fromRepo toRepo verb withWorkingDir                     `catch` \(e :: SomeException) ->                                do putStrLn ("Exception while getting basic pack:\n" ++ show e)                                   copyNormally)@@ -325,53 +303,53 @@                     copyNormally  copyBasicRepoPacked2 ::-  forall rt p wR wU wT. (IsRepoType rt, RepoPatch p, ApplyState (PrimOf p) ~ Tree, ApplyState p ~ Tree)-  => Repository rt p wR wU wT -- remote+  forall rt p wR wU wT.+     Repository rt p wR wU wT -- remote   -> Repository rt p wR wU wT -- existing empty local repository   -> Verbosity   -> WithWorkingDir   -> IO ()-copyBasicRepoPacked2 (Repo fromDir _ _ _) toRepo@(Repo _ _ _ toCache) verb withWorkingDir = do+copyBasicRepoPacked2 fromRepo toRepo verb withWorkingDir = do   putVerbose verb $ text "Cloning packed basic repository."   -- unpack inventory & pristine cache   cleanDir $ darcsdir </> "pristine.hashed"   removeFile $ darcsdir </> "hashed_inventory"-  fetchAndUnpackBasic toCache fromDir+  fetchAndUnpackBasic (repoCache toRepo) (repoLocation fromRepo)   putInfo verb $ text "Done fetching and unpacking basic pack."   createPristineDirectoryTree toRepo "." withWorkingDir  copyCompleteRepoPacked ::-  forall rt p wR wU wT. (IsRepoType rt, RepoPatch p, ApplyState (PrimOf p) ~ Tree, ApplyState p ~ Tree)+  forall rt p wR wU wT. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)   => Repository rt p wR wU wT -- remote   -> Repository rt p wR wU wT -- existing basic local repository   -> Verbosity   -> CloneKind   -> IO ()-copyCompleteRepoPacked r to verb cloneKind =-  ( copyCompleteRepoPacked2 r to verb cloneKind-   `catch` \(e :: SomeException) ->-             do putStrLn ("Exception while getting patches pack:\n" ++ show e)-                putVerbose verb $ text "Problem while copying patches pack, copying normally."-                copyCompleteRepoNotPacked r to verb cloneKind )+copyCompleteRepoPacked from to verb cloneKind =+    copyCompleteRepoPacked2 from to verb cloneKind+  `catch`+    \(e :: SomeException) -> do+      putStrLn ("Exception while getting patches pack:\n" ++ show e)+      putVerbose verb $ text "Problem while copying patches pack, copying normally."+      copyCompleteRepoNotPacked from to verb cloneKind  copyCompleteRepoPacked2 ::-  forall rt p wR wU wT. (IsRepoType rt, RepoPatch p, ApplyState (PrimOf p) ~ Tree, ApplyState p ~ Tree)+  forall rt p wR wU wT. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)   => Repository rt p wR wU wT   -> Repository rt p wR wU wT   -> Verbosity   -> CloneKind   -> IO ()-copyCompleteRepoPacked2 (Repo fromDir _ _ _)-                        toRepo@(Repo toDir _ _ toCache)-                        verb cloneKind = do+copyCompleteRepoPacked2 fromRepo toRepo verb cloneKind = do   us <- readRepo toRepo   -- get old patches   let cleanup = putInfo verb $ text "Using lazy repository."   allowCtrlC cloneKind cleanup $ do     putVerbose verb $ text "Using patches pack."-    fetchAndUnpackPatches (mapRL hashedPatchFileName $ newset2RL us) toCache fromDir-    pi <- doesPatchIndexExist toDir-    when pi $ createPIWithInterrupt toRepo+    fetchAndUnpackPatches (mapRL hashedPatchFileName $ patchSet2RL us)+      (repoCache toRepo) (repoLocation fromRepo)+    pi <- doesPatchIndexExist (repoLocation toRepo)+    when pi $ createPIWithInterrupt toRepo us -- TODO or do another readRepo?  cleanDir :: FilePath -> IO () cleanDir d = mapM_ (\x -> removeFile $ d </> x) .@@ -383,35 +361,35 @@                         -> Verbosity                         -> WithWorkingDir                         -> IO ()-copyRepoOldFashioned fromrepository toRepo@(Repo _ _ _ toCache) verb withWorkingDir = do+copyRepoOldFashioned fromrepository toRepo verb withWorkingDir = do   HashedRepo.revertTentativeChanges   patches <- readRepo fromrepository   let k = "Copying patch"   beginTedious k-  tediousSize k (lengthRL $ newset2RL patches)+  tediousSize k (lengthRL $ patchSet2RL patches)   let patches' = progressPatchSet k patches-  HashedRepo.writeTentativeInventory toCache GzipCompression patches'+  HashedRepo.writeTentativeInventory (repoCache toRepo) GzipCompression patches'   endTedious k   HashedRepo.finalizeTentativeChanges toRepo GzipCompression   -- apply all patches into current hashed repository   HashedRepo.revertTentativeChanges   local_patches <- readRepo toRepo   replacePristine toRepo emptyTree-  let patchesToApply = progressFL "Applying patch" $ newset2FL local_patches-  sequence_ $ mapFL applyToTentativePristine $ bunchFL 100 patchesToApply+  let patchesToApply = progressFL "Applying patch" $ patchSet2FL local_patches+  sequence_ $ mapFL applyToTentativePristineCwd $ bunchFL 100 patchesToApply   finalizeRepositoryChanges toRepo YesUpdateWorking GzipCompression   putVerbose verb $ text "Writing pristine and working directory contents..."   createPristineDirectoryTree toRepo "." withWorkingDir  -- | This function fetches all patches that the given repository has --   with fetchFileUsingCache, unless --lazy is passed.-fetchPatchesIfNecessary :: forall rt p wR wU wT. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+fetchPatchesIfNecessary :: forall rt p wR wU wT. (IsRepoType rt, RepoPatch p)                         => Repository rt p wR wU wT                         -> IO ()-fetchPatchesIfNecessary torepository@(Repo _ _ _ c) =-  do  r <- readRepo torepository+fetchPatchesIfNecessary toRepo =+  do  ps <- readRepo toRepo       pipelineLength <- maxPipelineLength-      let patches = newset2RL r+      let patches = patchSet2RL ps           ppatches = progressRLShowTags "Copying patches" patches           (first, other) = splitAt (pipelineLength - 1) $ tail $ hashes patches           speculate | pipelineLength > 1 = [] : first : map (:[]) other@@ -423,56 +401,54 @@         fetchAndSpeculate (f, ss) = do           _ <- fetchFileUsingCache c HashedPatchesDir f           mapM_ (speculateFileUsingCache c HashedPatchesDir) ss+        c = repoCache toRepo +{- -- | patchSetToRepository takes a patch set, and writes a new repository --   in the current directory that contains all the patches in the patch --   set.  This function is used when 'darcs get'ing a repository with --   the --to-match flag.+-- bf: no it is not used anywhere patchSetToRepository :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)                      => Repository rt p wR1 wU1 wR1                      -> PatchSet rt p Origin wX                      -> UseCache -> RemoteDarcs                      -> IO ()-patchSetToRepository (Repo fromrepo rf _ _) patchset useCache rDarcs = do-    when (formatHas HashedInventory rf) $ -- set up sources and all that+patchSetToRepository fromRepo patchset useCache rDarcs = do+    when (formatHas HashedInventory (repoFormat fromRepo)) $+       -- set up sources and all that        do writeFile (darcsdir </> "tentative_pristine") "" -- this is hokey           repox <- writePatchSet patchset useCache-          HashedRepo.copyHashedInventory repox rDarcs fromrepo-          void $ copySources repox fromrepo-    repo@(Repo dir _ _ _) <- writePatchSet patchset useCache-    readRepo repo >>= (runDefault . applyPatches . newset2FL)+          let fromLoc = repoLocation fromRepo+          HashedRepo.copyHashedInventory repox rDarcs fromLoc+          void $ copySources repox fromLoc+    repo <- writePatchSet patchset useCache+    readRepo repo >>= (runDefault . applyPatches . patchSet2FL)     debugMessage "Writing the pristine"-    withCurrentDirectory dir $ readWorking >>= replacePristine repo+    withRepoLocation repo $ readWorking >>= replacePristine repo+-}  -- | writePatchSet is like patchSetToRepository, except that it doesn't -- touch the working directory or pristine cache.-writePatchSet :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+writePatchSet :: (IsRepoType rt, RepoPatch p)               => PatchSet rt p Origin wX               -> UseCache               -> IO (Repository rt p wR wU wT) writePatchSet patchset useCache = do     maybeRepo <- maybeIdentifyRepository useCache "."-    let repo@(Repo _ _ _ c) =+    let repo =           case maybeRepo of             GoodRepository r -> r             BadRepository e -> bug ("Current directory is a bad repository in writePatchSet: " ++ e)             NonRepository e -> bug ("Current directory not a repository in writePatchSet: " ++ e)     debugMessage "Writing inventory"-    HashedRepo.writeTentativeInventory c GzipCompression patchset+    HashedRepo.writeTentativeInventory (repoCache repo) GzipCompression patchset     HashedRepo.finalizeTentativeChanges repo GzipCompression     return repo  -- | Replace the existing pristine with a new one (loaded up in a Tree object). replacePristine :: Repository rt p wR wU wT -> Tree IO -> IO ()-replacePristine (Repo r _ _ _) = writePristine r--writePristine :: FilePath -> Tree IO -> IO ()-writePristine r tree = withCurrentDirectory r $-    do let t = darcsdir </> "hashed_inventory"-       i <- gzReadFilePS t-       tree' <- darcsAddMissingHashes tree-       root <- writeDarcsHashed tree' $ darcsdir </> "pristine.hashed"-       writeDocBinFile t $ pris2inv (BS.unpack $ encodeBase16 root) i+replacePristine = writePristine . repoLocation  allowCtrlC :: CloneKind -> IO () -> IO () -> IO () allowCtrlC CompleteClone _       action = action@@ -482,30 +458,3 @@ hashedPatchFileName x = case extractHash x of   Left _ -> fail "unexpected unhashed patch"   Right h -> h---- |'copySources' does two things:--- * it copies the prefs/sources file to the local repo, from the---   remote, having first filtered the local filesystem sources.--- * it returns the original list of sources of the local repo---   updated with the remote repo as an additional source-copySources :: RepoPatch p-            => Repository rt p wR wU wT-            -> String-            -> IO (Repository rt p wR wU wT)-copySources repo@(Repo outr _ _ cache0) inr = do-    let (Repo s f p newCache1) = modifyCache repo dropNonRepos-    let sourcesToWrite = repo2cache inr `unionCaches` newCache1-    appendBinFile (outr ++ "/" ++ darcsdir ++ "/prefs/sources")-                  (show sourcesToWrite)-    debugMessage "Done copying and filtering pref/sources."--    -- put remote source last:-    let newSources = cache0 `unionCaches` repo2cache inr-    return (Repo s f p newSources)-  where-    dropNonRepos (Ca cache) = Ca $ filter notRepo cache-    notRepo xs = case xs of-        Cache DarcsCache.Directory _                   _ -> False-        -- we don't want to write thisrepo: entries to the disk-        Cache DarcsCache.Repo      DarcsCache.Writable _ -> False-        _                              -> True
+ src/Darcs/Repository/Create.hs view
@@ -0,0 +1,165 @@+module Darcs.Repository.Create+    ( createRepository+    , createRepositoryV1+    , createRepositoryV2+    , EmptyRepository(..)+    , writePristine+    ) where++import Prelude ()+import Darcs.Prelude++import Control.Monad ( when )+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC+import Data.Maybe( isJust )+import System.Directory+    ( createDirectory+    , getCurrentDirectory+    , setCurrentDirectory+    )+import System.FilePath ( (</>) )+import System.IO.Error+    ( catchIOError+    , isAlreadyExistsError+    )++import Darcs.Patch ( RepoPatch )+import Darcs.Patch.Apply( ApplyState )+import Darcs.Patch.RepoType ( RepoType(..), RebaseType(..) )+import Darcs.Patch.Set ( Origin, emptyPatchSet )+import Darcs.Patch.V1 ( RepoPatchV1 )+import Darcs.Patch.V2 ( RepoPatchV2 )+import qualified Darcs.Patch.V1.Prim as V1 ( Prim(..) )+import qualified Darcs.Patch.V2.Prim as V2 ( Prim(..) )++import Darcs.Repository.Cache ( Cache )+import Darcs.Repository.Format+    ( RepoFormat+    , createRepoFormat+    , writeRepoFormat+    )+import Darcs.Repository.Flags+    ( UseCache(..)+    , WithWorkingDir (..)+    , WithPatchIndex (..)+    , PatchFormat (..)+    )+import Darcs.Repository.Hashed+    ( pokePristineHash+    , pristineDirPath+    , patchesDirPath+    , inventoriesDirPath+    , hashedInventoryPath+    )+import Darcs.Repository.Identify ( seekRepo )+import Darcs.Repository.InternalTypes+    ( Repository+    , PristineType(..)+    , mkRepo+    )+import Darcs.Repository.PatchIndex ( createOrUpdatePatchIndexDisk )+import Darcs.Repository.Prefs+    ( writeDefaultPrefs+    , getCaches+    , prefsDirPath+    )++import Darcs.Util.ByteString( gzReadFilePS )+import Darcs.Util.File ( withCurrentDirectory )+import Darcs.Util.Global ( darcsdir )+import Darcs.Util.Hash( encodeBase16 )+import Darcs.Util.Lock+    ( writeBinFile+    , writeDocBinFile+    )+import Darcs.Util.Tree( Tree, emptyTree )+import Darcs.Util.Tree.Hashed( writeDarcsHashed, darcsAddMissingHashes )++createRepositoryFiles :: PatchFormat -> WithWorkingDir -> IO RepoFormat+createRepositoryFiles patchfmt withWorkingDir = do+  cwd <- getCurrentDirectory+  x <- seekRepo+  when (isJust x) $ do+      setCurrentDirectory cwd+      putStrLn "WARNING: creating a nested repository."+  createDirectory darcsdir `catchIOError`+      (\e-> if isAlreadyExistsError e+            then fail "Tree has already been initialized!"+            else fail $ "Error creating directory `"++darcsdir++"'.")+  createDirectory pristineDirPath+  createDirectory patchesDirPath+  createDirectory inventoriesDirPath+  createDirectory prefsDirPath+  writeDefaultPrefs+  let repo_format = createRepoFormat patchfmt withWorkingDir+  writeRepoFormat repo_format (darcsdir </> "format")+  -- note: all repos we create nowadays are hashed+  writeBinFile hashedInventoryPath B.empty+  writePristine here emptyTree+  return repo_format++data EmptyRepository where+  EmptyRepository :: (RepoPatch p, ApplyState p ~ Tree)+                  => Repository ('RepoType 'NoRebase) p Origin Origin Origin+                  -> EmptyRepository++createRepository :: PatchFormat -> WithWorkingDir -> WithPatchIndex -> UseCache+                 -> IO EmptyRepository+createRepository patchfmt withWorkingDir withPatchIndex useCache = do+  rfmt <- createRepositoryFiles patchfmt withWorkingDir+  cache <- getCaches useCache here+  repo@(EmptyRepository r) <- case patchfmt of+    PatchFormat1 -> return $ EmptyRepository $ mkRepoV1 rfmt cache+    PatchFormat2 -> return $ EmptyRepository $ mkRepoV2 rfmt cache+  maybeCreatePatchIndex withPatchIndex r+  return repo++mkRepoV1+  :: RepoFormat+  -> Cache+  -> Repository ('RepoType 'NoRebase) (RepoPatchV1 V1.Prim) Origin Origin Origin+mkRepoV1 repofmt cache = mkRepo "." repofmt HashedPristine cache++mkRepoV2+  :: RepoFormat+  -> Cache+  -> Repository ('RepoType 'NoRebase) (RepoPatchV2 V2.Prim) Origin Origin Origin+mkRepoV2 repofmt cache = mkRepo "." repofmt HashedPristine cache++createRepositoryV1+  :: WithWorkingDir -> WithPatchIndex -> UseCache+  -> IO (Repository ('RepoType 'NoRebase) (RepoPatchV1 V1.Prim) Origin Origin Origin)+createRepositoryV1 withWorkingDir withPatchIndex useCache = do+  rfmt <- createRepositoryFiles PatchFormat1 withWorkingDir+  cache <- getCaches useCache here+  let repo = mkRepoV1 rfmt cache+  maybeCreatePatchIndex withPatchIndex repo+  return repo++createRepositoryV2+  :: WithWorkingDir -> WithPatchIndex -> UseCache+  -> IO (Repository ('RepoType 'NoRebase) (RepoPatchV2 V2.Prim) Origin Origin Origin)+createRepositoryV2 withWorkingDir withPatchIndex useCache = do+  rfmt <- createRepositoryFiles PatchFormat2 withWorkingDir+  cache <- getCaches useCache here+  let repo = mkRepoV2 rfmt cache+  maybeCreatePatchIndex withPatchIndex repo+  return repo++maybeCreatePatchIndex :: (RepoPatch p, ApplyState p ~ Tree)+                      => WithPatchIndex -> Repository rt p Origin wU Origin -> IO ()+maybeCreatePatchIndex NoPatchIndex _ = return ()+maybeCreatePatchIndex YesPatchIndex repo =+  createOrUpdatePatchIndexDisk repo emptyPatchSet++writePristine :: FilePath -> Tree IO -> IO ()+writePristine dir tree =+  withCurrentDirectory dir $ do+    inv <- gzReadFilePS hashedInventoryPath+    tree' <- darcsAddMissingHashes tree+    root <- writeDarcsHashed tree' pristineDirPath+    writeDocBinFile hashedInventoryPath $ pokePristineHash (BC.unpack $ encodeBase16 root) inv++here :: String+here = "."
src/Darcs/Repository/Diff.hs view
@@ -28,7 +28,6 @@ -- Stability   : experimental -- Portability : portable -{-# LANGUAGE CPP #-} module Darcs.Repository.Diff     (       treeDiff@@ -38,7 +37,7 @@ import Darcs.Prelude  import qualified Data.ByteString.Lazy.Char8 as BLC-import qualified Data.ByteString as BS+import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL  import Data.List ( sortBy )@@ -69,9 +68,6 @@ import Darcs.Patch.Witnesses.Sealed ( Gap(..) ) import Darcs.Repository.Flags ( DiffAlgorithm(..) ) -#include "impossible.h"-- data Diff m = Added (TreeItem m)             | Removed (TreeItem m)             | Changed (TreeItem m) (TreeItem m)@@ -87,7 +83,7 @@ getDiff _ Nothing Nothing = impossible -- zipTrees should never return this  -treeDiff :: forall m w prim . (Functor m, Monad m, Gap w, PrimPatch prim)+treeDiff :: forall m w prim . (Monad m, Gap w, PrimPatch prim)          => DiffAlgorithm          -> (FilePath -> FileType)          -> Tree m@@ -148,12 +144,40 @@         | BL.null a && BL.null b = emptyGap NilFL         | BL.null a = freeGap (diff_from_empty p b)         | BL.null b = freeGap (diff_to_empty p a)++        -- What is 'a line'? One view is that a line is something that is+        -- /terminated/ by either a newline or end of file. Another view is+        -- that lines are /separated/ by newline symbols.+        --+        -- The first view is the more "intuitive" one. The second is more+        -- "technical", it has the simpler definition and the highly desirable+        -- property that splitting a text into lines and joining them with+        -- newline symbols are inverse operations. The last point is the reason+        -- we never use the standard versions of 'unlines' for ByteString+        -- anywhere in darcs.+        --+        -- The two views differ mostly when enumerating the lines of a file+        -- that ends with a newline symbol: here, the technical view counts one+        -- more (empty) line. This leads to un-intuitive (though technically+        -- not incorrect) results when calculating the diff for a change that+        -- appends an empty line to a file that already has a newline at the+        -- end. For instance, for a file with a single, newline-terminated line+        -- of text, the LCS algorithm would tell us that a *third* (empty) line+        -- is being added.+        --+        -- To avoid this, we add a special case here: we strip off common+        -- newline symbols at the end. When we later split the result into+        -- lines for the diff algorithm, it never gets to see the empty+        -- last lines in both files and thus gives us the more intuitive result.++        | BLC.last a == '\n' && BLC.last b == '\n'+                    = freeGap (line_diff p (linesB $ BLC.init a) (linesB $ BLC.init b))         | otherwise = freeGap (line_diff p (linesB a) (linesB b))      line_diff p a b = canonize da (hunk p 1 a b)      diff_to_empty p x | BLC.last x == '\n' = line_diff p (init $ linesB x) []-                      | otherwise = line_diff p (linesB x) [BS.empty]+                      | otherwise = line_diff p (linesB x) [B.empty]      diff_from_empty p x = invert (diff_to_empty p x) @@ -161,4 +185,4 @@      linesB = map strict . BLC.split '\n' -    strict = BS.concat . BL.toChunks+    strict = B.concat . BL.toChunks
src/Darcs/Repository/Flags.hs view
@@ -30,6 +30,8 @@     , ForgetParent (..)     , PatchFormat (..)     , IncludeBoring (..)+    , HooksConfig (..)+    , HookConfig (..)     ) where  import Darcs.Util.Diff ( DiffAlgorithm(..) )@@ -129,3 +131,13 @@  data PatchFormat = PatchFormat1 | PatchFormat2     deriving ( Eq, Show )++data HooksConfig = HooksConfig+  { pre :: HookConfig+  , post :: HookConfig+  }++data HookConfig = HookConfig+  { cmd :: Maybe String+  , prompt :: Bool+  }
src/Darcs/Repository/Format.hs view
@@ -2,8 +2,6 @@ -- -- This file is licensed under the GPL, version two or later. -{-# LANGUAGE CPP #-}- module Darcs.Repository.Format     ( RepoFormat(..)     , RepoProperty(..)@@ -22,10 +20,8 @@ import Prelude () import Darcs.Prelude -#include "impossible.h"- import Control.Monad ( mplus, (<=<) )-import qualified Data.ByteString.Char8 as BC ( split, unpack, elemIndex )+import qualified Data.ByteString.Char8 as BC ( split, pack, unpack, elemIndex ) import qualified Data.ByteString  as B ( null, empty ) import Data.List ( partition, intercalate, (\\) ) import Data.Maybe ( isJust, mapMaybe )@@ -149,7 +145,8 @@  -- | Write the repo format to the given file. writeRepoFormat :: RepoFormat -> FilePath -> IO ()-writeRepoFormat rf loc = writeBinFile loc $ show rf+writeRepoFormat rf loc = writeBinFile loc $ BC.pack $ show rf+-- note: this assumes show returns ascii  -- | Create a repo format. The first argument is whether to use the old (darcs-1) -- format; the second says whether the repo has a working tree.
+ src/Darcs/Repository/Hashed.hs view
@@ -0,0 +1,1101 @@+-- Copyright (C) 2006-2007 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.++module Darcs.Repository.Hashed+    ( inventoriesDir+    , inventoriesDirPath+    , pristineDir+    , pristineDirPath+    , patchesDir+    , patchesDirPath+    , hashedInventory+    , hashedInventoryPath++    , revertTentativeChanges+    , revertRepositoryChanges+    , finalizeTentativeChanges+    , cleanPristine+    , filterDirContents+    , cleanInventories+    , cleanPatches+    , copyPristine+    , copyPartialsPristine+    , applyToTentativePristine+    , applyToTentativePristineCwd+    , addToTentativeInventory+    , readRepo+    , readRepoHashed+    , readTentativeRepo+    , writeAndReadPatch+    , writeTentativeInventory+    , copyHashedInventory+    , readHashedPristineRoot+    , pokePristineHash+    , peekPristineHash+    , listInventories+    , listInventoriesLocal+    , listInventoriesRepoDir+    , listPatchesLocalBucketed+    , writePatchIfNecessary+    , diffHashLists+    , withRecorded+    , withTentative+    , tentativelyAddPatch+    , tentativelyRemovePatches+    , tentativelyRemovePatches_+    , tentativelyAddPatch_+    , tentativelyAddPatches_+    , tentativelyReplacePatches+    , finalizeRepositoryChanges+    , unrevertUrl+    , createPristineDirectoryTree+    , createPartialsPristineDirectoryTree+    , reorderInventory+    , cleanRepository+    , UpdatePristine(..)+    , repoXor+    ) where++import Prelude ()+import Darcs.Prelude++import Control.Arrow ( (&&&) )+import Control.Exception ( catch, IOException )+import Darcs.Util.Exception ( catchall )+import Control.Monad ( when, unless, void )+import Data.Maybe+import Data.List( foldl' )++import qualified Data.ByteString as B ( empty, readFile, append )+import qualified Data.ByteString.Char8 as BC ( unpack, pack )+import qualified Data.Set as Set++import Darcs.Util.Hash( encodeBase16, Hash(..), SHA1, sha1Xor, sha1zero )+import Darcs.Util.Prompt ( promptYorn )+import Darcs.Util.Tree( treeHash, Tree )+import Darcs.Util.Tree.Hashed( hashedTreeIO, readDarcsHashedNosize,+                             readDarcsHashed, writeDarcsHashed,+                             decodeDarcsHash, decodeDarcsSize )+import Darcs.Util.SignalHandler ( withSignalsBlocked )++import System.Directory ( createDirectoryIfMissing, getDirectoryContents+                        , doesFileExist, doesDirectoryExist )+import System.FilePath.Posix( (</>) )+import System.IO.Unsafe ( unsafeInterleaveIO )+import System.IO ( stderr, hPutStrLn )++import Darcs.Util.External+    ( copyFileOrUrl+    , cloneFile+    , fetchFilePS+    , gzFetchFilePS+    , Cachable( Uncachable )+    )+import Darcs.Repository.Flags ( Compression, RemoteDarcs, remoteDarcs+    , Verbosity(..), UpdateWorking (..), WithWorkingDir (WithWorkingDir) )++import Darcs.Repository.Format ( RepoProperty( HashedInventory ), formatHas )+import Darcs.Repository.Pending+    ( readPending+    , pendingName+    , tentativelyRemoveFromPending+    , finalizePending+    , setTentativePending+    , prepend+    )+import Darcs.Repository.PatchIndex ( createOrUpdatePatchIndexDisk, doesPatchIndexExist )+import Darcs.Repository.State ( readRecorded, updateIndex )++import Darcs.Util.Global ( darcsdir )+import Darcs.Util.Lock+    ( writeBinFile+    , writeDocBinFile+    , writeAtomicFilePS+    , appendDocBinFile+    , removeFileMayNotExist+    )+import Darcs.Patch.Set ( PatchSet(..), Tagged(..)+                       , SealedPatchSet, Origin+                       , patchSet2RL+                       )++import Darcs.Patch.Show ( ShowPatch, ShowPatchFor(..) )+import Darcs.Patch.PatchInfoAnd+    ( PatchInfoAnd, Hopefully, patchInfoAndPatch, info+    , extractHash, createHashed, hopefully )+import Darcs.Patch ( IsRepoType, RepoPatch, showPatch, apply+                   , description+                   , commuteRL+                   , readPatch+                   , effect+                   , invert+                   )++import Darcs.Patch.Apply ( Apply, ApplyState )++import Darcs.Patch.Bundle ( scanBundle+                          , makeBundleN+                          )+import Darcs.Patch.Named.Wrapped ( namedIsInternal )+import Darcs.Patch.Read ( ReadPatch )+import Darcs.Patch.Depends ( removeFromPatchSet, slightlyOptimizePatchset+                           , mergeThem, splitOnTag )+import Darcs.Patch.Info+    ( PatchInfo, displayPatchInfo, isTag, makePatchname )+import Darcs.Util.Path ( FilePathLike, ioAbsoluteOrRemote, toPath+                       , AbsolutePath, toFilePath )+import Darcs.Repository.Cache ( Cache(..), fetchFileUsingCache,+                                speculateFilesUsingCache, writeFileUsingCache,+                                HashedDir(..), hashedDir, peekInCache, bucketFolder )+import Darcs.Repository.HashedIO ( copyHashed, copyPartialsHashed,+                                   cleanHashdir )+import Darcs.Repository.Inventory+import Darcs.Repository.InternalTypes+    ( Repository+    , repoCache+    , repoFormat+    , repoLocation+    , withRepoLocation+    , coerceT )+import qualified Darcs.Repository.Old as Old ( readOldRepo, oldRepoFailMsg )+import Darcs.Util.File ( withCurrentDirectory )+import Darcs.Patch.Witnesses.Ordered+    ( (+<+), FL(..), RL(..), mapRL, foldFL_M+    , (:>)(..), lengthFL, filterOutFLFL+    , reverseFL, reverseRL )+import Darcs.Patch.Witnesses.Sealed ( Sealed(..), seal, unseal, mapSeal )+import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )++import Darcs.Util.ByteString ( gzReadFilePS )+import Darcs.Util.Printer.Color ( showDoc )+import Darcs.Util.Printer+    ( Doc, hcat, ($$), renderString, renderPS, text, putDocLn, (<+>) )+import Darcs.Util.Progress ( beginTedious, endTedious, debugMessage, finishedOneIO )+import Darcs.Patch.Progress (progressFL)+import Darcs.Util.Workaround ( renameFile )+import Darcs.Repository.Prefs ( globalCacheDir )+++makeDarcsdirPath :: String -> String+makeDarcsdirPath name = darcsdir </> name++-- TODO rename xyzPath to xyzLocal to make it clear that it is+-- relative to the local darcsdir++-- Location of the (one and only) head inventory.+hashedInventory, hashedInventoryPath :: String+hashedInventory = "hashed_inventory"+hashedInventoryPath = makeDarcsdirPath hashedInventory++-- Location of the (one and only) tentative head inventory.+tentativeHashedInventory, tentativeHashedInventoryPath :: String+tentativeHashedInventory = "tentative_hashed_inventory"+tentativeHashedInventoryPath = makeDarcsdirPath tentativeHashedInventory++-- Location of parent inventories.+inventoriesDir, inventoriesDirPath :: String+inventoriesDir = "inventories"+inventoriesDirPath = makeDarcsdirPath inventoriesDir++-- Location of pristine trees.+pristineDir, tentativePristinePath, pristineDirPath :: String+tentativePristinePath = makeDarcsdirPath "tentative_pristine"+pristineDir = "pristine.hashed"+pristineDirPath = makeDarcsdirPath pristineDir++-- Location of patches.+patchesDir, patchesDirPath :: String+patchesDir = "patches"+patchesDirPath = makeDarcsdirPath patchesDir++-- | The way patchfiles, inventories, and pristine trees are stored.+-- 'PlainLayout' means all files are in the same directory. 'BucketedLayout'+-- means we create a second level of subdirectories, such that all files whose+-- hash starts with the same two letters are in the same directory.+data DirLayout = PlainLayout | BucketedLayout++-- | 'applyToHashedPristine' takes a root hash, a patch @p@ and attempts to+-- apply the patch to the 'Tree' identified by @h@. If we encounter an old,+-- size-prefixed pristine, we first convert it to the non-size-prefixed format,+-- then apply the patch.+applyToHashedPristine :: (Apply p, ApplyState p ~ Tree) => String -> p wX wY+                      -> IO String+applyToHashedPristine h p = applyOrConvertOldPristineAndApply+  where+    applyOrConvertOldPristineAndApply =+        tryApply hash `catch` \(_ :: IOException) -> handleOldPristineAndApply++    hash = decodeDarcsHash $ BC.pack h++    failOnMalformedRoot (SHA256 _) = return ()+    failOnMalformedRoot root = fail $ "Cannot handle hash: " ++ show root++    hash2root = BC.unpack . encodeBase16++    tryApply :: Hash -> IO String+    tryApply root = do+        failOnMalformedRoot root+        -- Read a non-size-prefixed pristine, failing if we encounter one.+        tree <- readDarcsHashedNosize pristineDirPath root+        (_, updatedTree) <- hashedTreeIO (apply p) tree pristineDirPath+        return . hash2root $ treeHash updatedTree++    warn = "WARNING: Doing a one-time conversion of pristine format.\n"+           ++ "This may take a while. The new format is backwards-compatible."++    handleOldPristineAndApply = do+        hPutStrLn stderr warn+        inv <- gzReadFilePS hashedInventoryPath+        let oldroot = BC.pack $ peekPristineHash inv+            oldrootSizeandHash = (decodeDarcsSize &&& decodeDarcsHash) oldroot+        -- Read the old size-prefixed pristine tree+        old <- readDarcsHashed pristineDirPath oldrootSizeandHash+        -- Write out the pristine tree as a non-size-prefixed pristine.+        root <- writeDarcsHashed old pristineDirPath+        let newroot = hash2root root+        -- Write out the new inventory.+        writeDocBinFile hashedInventoryPath $ pokePristineHash newroot inv+        cleanHashdir (Ca []) HashedPristineDir [newroot]+        hPutStrLn stderr "Pristine conversion done..."+        -- Retry applying the patch, which should now succeed.+        tryApply root++-- |revertTentativeChanges swaps the tentative and "real" hashed inventory+-- files, and then updates the tentative pristine with the "real" inventory+-- hash.+revertTentativeChanges :: IO ()+revertTentativeChanges = do+    cloneFile hashedInventoryPath tentativeHashedInventoryPath+    i <- gzReadFilePS hashedInventoryPath+    writeBinFile tentativePristinePath $ B.append pristineName (BC.pack (peekPristineHash i))++-- |finalizeTentativeChanges trys to atomically swap the tentative+-- inventory/pristine pointers with the "real" pointers; it first re-reads the+-- inventory to optimize it, presumably to take account of any new tags, and+-- then writes out the new tentative inventory, and finally does the atomic+-- swap. In general, we can't clean the pristine cache at the same time, since+-- a simultaneous get might be in progress.+finalizeTentativeChanges :: (IsRepoType rt, RepoPatch p)+                         => Repository rt p wR wU wT -> Compression -> IO ()+finalizeTentativeChanges r compr = do+    debugMessage "Optimizing the inventory..."+    -- Read the tentative patches+    ps <- readTentativeRepo r "."+    writeTentativeInventory (repoCache r) compr ps+    i <- gzReadFilePS tentativeHashedInventoryPath+    p <- gzReadFilePS tentativePristinePath+    -- Write out the "optimised" tentative inventory.+    writeDocBinFile tentativeHashedInventoryPath $ pokePristineHash (peekPristineHash p) i+    -- Atomically swap.+    renameFile tentativeHashedInventoryPath hashedInventoryPath++-- |readHashedPristineRoot attempts to read the pristine hash from the current+-- inventory, returning Nothing if it cannot do so.+readHashedPristineRoot :: Repository rt p wR wU wT -> IO (Maybe String)+readHashedPristineRoot r = withRepoLocation r $ do+    i <- (Just <$> gzReadFilePS hashedInventoryPath)+         `catch` (\(_ :: IOException) -> return Nothing)+    return $ peekPristineHash <$> i++-- |cleanPristine removes any obsolete (unreferenced) entries in the pristine+-- cache.+cleanPristine :: Repository rt p wR wU wT -> IO ()+cleanPristine r = withRepoLocation r $ do+    debugMessage "Cleaning out the pristine cache..."+    i <- gzReadFilePS hashedInventoryPath+    cleanHashdir (repoCache r) HashedPristineDir [peekPristineHash i]++-- |filterDirContents returns the contents of the directory @d@+-- except files whose names begin with '.' (directories . and ..,+-- hidden files) and files whose names are filtered by the function @f@, if+-- @dir@ is empty, no paths are returned.+filterDirContents :: FilePath -> (FilePath -> Bool) -> IO [FilePath]+filterDirContents d f = do+    let realPath = makeDarcsdirPath d+    exists <- doesDirectoryExist realPath+    if exists+        then filter (\x -> head x /= '.' && f x) <$>+            getDirectoryContents realPath+        else return []++-- | Set difference between two lists of hashes.+diffHashLists :: [String] -> [String] -> [String]+diffHashLists xs ys = from_set $ (to_set xs) `Set.difference` (to_set ys)+  where+    to_set = Set.fromList . map BC.pack+    from_set = map BC.unpack . Set.toList++-- |cleanInventories removes any obsolete (unreferenced) files in the+-- inventories directory.+cleanInventories :: Repository rt p wR wU wT -> IO ()+cleanInventories _ = do+    debugMessage "Cleaning out inventories..."+    hs <- listInventoriesLocal+    fs <- filterDirContents inventoriesDir (const True)+    mapM_ (removeFileMayNotExist . (inventoriesDirPath </>))+        (diffHashLists fs hs)++-- FIXME this is ugly, these files should be directly under _darcs+-- since they are not hashed. And 'unrevert' isn't even a real patch but+-- a patch bundle.+-- |specialPatches list of special patch files that may exist in the directory+-- _darcs/patches/.+specialPatches :: [FilePath]+specialPatches = ["unrevert", "pending", "pending.tentative"]++-- |cleanPatches removes any obsolete (unreferenced) files in the+-- patches directory.+cleanPatches :: Repository rt p wR wU wT -> IO ()+cleanPatches _ = do+    debugMessage "Cleaning out patches..."+    hs <- listPatchesLocal PlainLayout darcsdir darcsdir+    fs <- filterDirContents patchesDir (`notElem` specialPatches)+    mapM_ (removeFileMayNotExist . (patchesDirPath </>))+        (diffHashLists fs hs)+++-- |addToSpecificInventory adds a patch to a specific inventory file, and+-- returns the FilePath whichs corresponds to the written-out patch.+addToSpecificInventory :: RepoPatch p => String -> Cache -> Compression+                       -> PatchInfoAnd rt p wX wY -> IO FilePath+addToSpecificInventory invPath c compr p = do+    let invFile = makeDarcsdirPath invPath+    hash <- snd <$> writePatchIfNecessary c compr p+    appendDocBinFile invFile $+      showInventoryEntry (info p, hash)+    return $ patchesDirPath </> getValidHash hash++-- | Warning: this allows to add any arbitrary patch! Used by convert import.+addToTentativeInventory :: RepoPatch p => Cache -> Compression+                        -> PatchInfoAnd rt p wX wY -> IO FilePath+addToTentativeInventory = addToSpecificInventory tentativeHashedInventory++-- | Attempt to remove an FL of patches from the tentative inventory.+-- This is used for commands that wish to modify already-recorded patches.+--+-- Precondition: it must be possible to remove the patches, i.e.+--+-- * the patches are in the repository+--+-- * any necessary commutations will succeed+removeFromTentativeInventory :: (IsRepoType rt, RepoPatch p)+                             => Repository rt p wR wU wT -> Compression+                             -> FL (PatchInfoAnd rt p) wX wT -> IO ()+removeFromTentativeInventory repo compr to_remove = do+    debugMessage $ "Start removeFromTentativeInventory"+    allpatches <- readTentativeRepo repo "."+    remaining <- case removeFromPatchSet to_remove allpatches of+        Nothing -> bug "Hashed.removeFromTentativeInventory: precondition violated"+        Just r -> return r+    writeTentativeInventory (repoCache repo) compr remaining+    debugMessage $ "Done removeFromTentativeInventory"++-- |writeHashFile takes a Doc and writes it as a hash-named file, returning the+-- filename that the contents were written to.+writeHashFile :: Cache -> Compression -> HashedDir -> Doc -> IO String+writeHashFile c compr subdir d = do+    debugMessage $ "Writing hash file to " ++ hashedDir subdir+    writeFileUsingCache c compr subdir $ renderPS d++-- |readRepo returns the "current" repo patchset.+readRepoHashed :: (IsRepoType rt, RepoPatch p) => Repository rt p wR wU wT+               -> String -> IO (PatchSet rt p Origin wR)+readRepoHashed = readRepoUsingSpecificInventory hashedInventory++-- |readRepo returns the tentative repo patchset.+readTentativeRepo :: (IsRepoType rt, RepoPatch p)+                  => Repository rt p wR wU wT -> String+                  -> IO (PatchSet rt p Origin wT)+readTentativeRepo = readRepoUsingSpecificInventory tentativeHashedInventory++-- |readRepoUsingSpecificInventory uses the inventory at @invPath@ to read the+-- repository @repo@.+readRepoUsingSpecificInventory :: (IsRepoType rt, RepoPatch p)+                               => String -> Repository rt p wR wU wT+                               -> String -> IO (PatchSet rt p Origin wS)+readRepoUsingSpecificInventory invPath repo dir = do+    realdir <- toPath <$> ioAbsoluteOrRemote dir+    Sealed ps <- readRepoPrivate (repoCache repo) realdir invPath+                 `catch` \e -> do+                     hPutStrLn stderr ("Invalid repository: " ++ realdir)+                     ioError e+    return $ unsafeCoerceP ps+  where+    readRepoPrivate :: (IsRepoType rt, RepoPatch p) => Cache -> FilePath+                    -> FilePath -> IO (SealedPatchSet rt p Origin)+    readRepoPrivate cache d iname = do+      inventory <- readInventoryPrivate (d </> darcsdir </> iname)+      readRepoFromInventoryList cache inventory++-- | Read a 'PatchSet' from the repository (assumed to be located at the+-- current working directory) by following the chain of 'Inventory's, starting+-- with the given one. The 'Cache' parameter is used to locate patches and parent+-- inventories, since not all of them need be present inside the current repo.+readRepoFromInventoryList+  :: (IsRepoType rt, RepoPatch p)+  => Cache+  -> Inventory+  -> IO (SealedPatchSet rt p Origin)+readRepoFromInventoryList cache = parseInv+  where+    parseInv :: (IsRepoType rt, RepoPatch p)+             => Inventory+             -> IO (SealedPatchSet rt p Origin)+    parseInv (Inventory Nothing ris) =+        mapSeal (PatchSet NilRL) <$> read_patches (reverse ris)+    parseInv (Inventory (Just h) []) =+        -- TODO could be more tolerant and create a larger PatchSet+        bug $ "bad inventory " ++ getValidHash h ++ " (no tag) in parseInv!"+    parseInv (Inventory (Just h) (t : ris)) = do+        Sealed ts <- unseal seal <$> unsafeInterleaveIO (read_ts t h)+        Sealed ps <- unseal seal <$>+                        unsafeInterleaveIO (read_patches $ reverse ris)+        return $ seal $ PatchSet ts ps++    read_patches :: (IsRepoType rt, RepoPatch p) => [InventoryEntry]+                 -> IO (Sealed (RL (PatchInfoAnd rt p) wX))+    read_patches [] = return $ seal NilRL+    read_patches allis@((i1, h1) : is1) =+        lift2Sealed (\p rest -> rest :<: i1 `patchInfoAndPatch` p) (rp is1)+                    (createValidHashed h1 (const $ speculateAndParse h1 allis i1))+      where+        rp :: (IsRepoType rt, RepoPatch p) => [InventoryEntry]+           -> IO (Sealed (RL (PatchInfoAnd rt p) wX))+        rp [] = return $ seal NilRL+        rp [(i, h), (il, hl)] =+            lift2Sealed (\p rest -> rest :<: i `patchInfoAndPatch` p)+                        (rp [(il, hl)])+                        (createValidHashed h+                            (const $ speculateAndParse h (reverse allis) i))+        rp ((i, h) : is) =+            lift2Sealed (\p rest -> rest :<: i `patchInfoAndPatch` p)+                        (rp is)+                        (createValidHashed h (parse i))++    lift2Sealed :: (forall wY wZ . q wY wZ -> p wX wY -> r wX wZ)+                -> IO (Sealed (p wX))+                -> (forall wB . IO (Sealed (q wB)))+                -> IO (Sealed (r wX))+    lift2Sealed f iox ioy = do+        Sealed x <- unseal seal <$> unsafeInterleaveIO iox+        Sealed y <- unseal seal <$> unsafeInterleaveIO ioy+        return $ seal $ f y x++    speculateAndParse h is i = speculate h is >> parse i h++    speculate :: PatchHash -> [InventoryEntry] -> IO ()+    speculate h is = do+        already_got_one <- peekInCache cache HashedPatchesDir (getValidHash h)+        unless already_got_one $+            speculateFilesUsingCache cache HashedPatchesDir (map (getValidHash . snd) is)++    parse :: ReadPatch p => PatchInfo -> PatchHash -> IO (Sealed (p wX))+    parse i h = do+        debugMessage ("Reading patch file: "++ showDoc (displayPatchInfo i))+        (fn, ps) <- fetchFileUsingCache cache HashedPatchesDir (getValidHash h)+        case readPatch ps of+            Just p -> return p+            Nothing -> fail $ unlines [ "Couldn't parse file " ++ fn+                                      , "which is patch"+                                      , renderString $ displayPatchInfo i ]++    read_ts :: (IsRepoType rt, RepoPatch p) => InventoryEntry+            -> InventoryHash -> IO (Sealed (RL (Tagged rt p) Origin))+    read_ts tag0 h0 = do+        contents <- unsafeInterleaveIO $ readTaggedInventoryFromHash (getValidHash h0)+        let is = reverse $ case contents of+                               (Inventory (Just _) (_ : ris0)) -> ris0+                               (Inventory Nothing ris0) -> ris0+                               (Inventory (Just _) []) -> bug "inventory without tag!"+        Sealed ts <- unseal seal <$>+                         unsafeInterleaveIO+                            (case contents of+                                 (Inventory (Just h') (t' : _)) -> read_ts t' h'+                                 (Inventory (Just _) []) -> bug "inventory without tag!"+                                 (Inventory Nothing _) -> return $ seal NilRL)+        Sealed ps <- unseal seal <$> unsafeInterleaveIO (read_patches is)+        Sealed tag00 <- read_tag tag0+        return $ seal $ ts :<: Tagged tag00 (Just (getValidHash h0)) ps++    read_tag :: (IsRepoType rt, RepoPatch p) => InventoryEntry+             -> IO (Sealed (PatchInfoAnd rt p wX))+    read_tag (i, h) =+        mapSeal (patchInfoAndPatch i) <$> createValidHashed h (parse i)++    readTaggedInventoryFromHash :: String+                                -> IO Inventory+    readTaggedInventoryFromHash invHash = do+        (fileName, pristineAndInventory) <-+            fetchFileUsingCache cache HashedInventoriesDir invHash+        case parseInventory pristineAndInventory of+          Just r -> return r+          Nothing -> fail $ unwords ["parse error in file", fileName]++-- | Read an inventory from a file. Fails with an error message if+-- file is not there or cannot be parsed.+readInventoryPrivate :: FilePath+                     -> IO Inventory+readInventoryPrivate path = do+    inv <- skipPristineHash <$> gzFetchFilePS path Uncachable+    case parseInventory inv of+      Just r -> return r+      Nothing -> fail $ unwords ["parse error in file", path]++-- |copyRepo copies the hashed inventory of @repo@ to the repository located at+-- @remote@.+copyHashedInventory :: Repository rt p wR wU wT -> RemoteDarcs -> String -> IO ()+copyHashedInventory outrepo rdarcs inloc | remote <- remoteDarcs rdarcs = do+    let outloc = repoLocation outrepo+    createDirectoryIfMissing False (outloc ++ "/" ++ inventoriesDirPath)+    copyFileOrUrl remote (inloc </> hashedInventoryPath)+                         (outloc </> hashedInventoryPath)+                  Uncachable -- no need to copy anything but hashed_inventory!+    debugMessage "Done copying hashed inventory."++-- |writeAndReadPatch makes a patch lazy, by writing it out to disk (thus+-- forcing it), and then re-reads the patch lazily.+writeAndReadPatch :: (IsRepoType rt, RepoPatch p) => Cache -> Compression+                  -> PatchInfoAnd rt p wX wY -> IO (PatchInfoAnd rt p wX wY)+writeAndReadPatch c compr p = do+    (i, h) <- writePatchIfNecessary c compr p+    unsafeInterleaveIO $ readp h i+  where+    parse i h = do+        debugMessage ("Rereading patch file: "++ showDoc (displayPatchInfo i))+        (fn, ps) <- fetchFileUsingCache c HashedPatchesDir (getValidHash h)+        case readPatch ps of+            Just x -> return x+            Nothing -> fail $ unlines [ "Couldn't parse patch file " ++ fn+                                      , "which is"+                                      , renderString $ displayPatchInfo i]++    readp h i = do Sealed x <- createValidHashed h (parse i)+                   return . patchInfoAndPatch i $ unsafeCoerceP x++createValidHashed :: PatchHash+                  -> (PatchHash -> IO (Sealed (a wX)))+                  -> IO (Sealed (Darcs.Patch.PatchInfoAnd.Hopefully a wX))+createValidHashed h f = createHashed (getValidHash h) (f . mkValidHash)++-- | writeTentativeInventory writes @patchSet@ as the tentative inventory.+writeTentativeInventory :: RepoPatch p => Cache -> Compression+                        -> PatchSet rt p Origin wX -> IO ()+writeTentativeInventory cache compr patchSet = do+    debugMessage "in writeTentativeInventory..."+    createDirectoryIfMissing False inventoriesDirPath+    beginTedious tediousName+    hsh <- writeInventoryPrivate $ slightlyOptimizePatchset patchSet+    endTedious tediousName+    debugMessage "still in writeTentativeInventory..."+    case hsh of+        Nothing -> writeBinFile (makeDarcsdirPath tentativeHashedInventory) B.empty+        Just h -> do+            content <- snd <$> fetchFileUsingCache cache HashedInventoriesDir h+            writeAtomicFilePS (makeDarcsdirPath tentativeHashedInventory) content+  where+    tediousName = "Writing inventory"+    writeInventoryPrivate :: RepoPatch p => PatchSet rt p Origin wX+                          -> IO (Maybe String)+    writeInventoryPrivate (PatchSet NilRL NilRL) = return Nothing+    writeInventoryPrivate (PatchSet NilRL ps) = do+        inventory <- sequence $ mapRL (writePatchIfNecessary cache compr) ps+        let inventorylist = showInventoryPatches (reverse inventory)+        hash <- writeHashFile cache compr HashedInventoriesDir inventorylist+        return $ Just hash+    writeInventoryPrivate+        (PatchSet xs@(_ :<: Tagged t _ _) x) = do+        resthash <- write_ts xs+        finishedOneIO tediousName $ fromMaybe "" resthash+        inventory <- sequence $ mapRL (writePatchIfNecessary cache compr)+                                    (NilRL :<: t +<+ x)+        let inventorylist = hcat (map showInventoryEntry $ reverse inventory)+            inventorycontents =+                case resthash of+                    Just h -> text ("Starting with inventory:\n" ++ h) $$+                                  inventorylist+                    Nothing -> inventorylist+        hash <- writeHashFile cache compr HashedInventoriesDir inventorycontents+        return $ Just hash+      where+        -- | write_ts writes out a tagged patchset. If it has already been+        -- written, we'll have the hash, so we can immediately return it.+        write_ts :: RepoPatch p => RL (Tagged rt p) Origin wX+                 -> IO (Maybe String)+        write_ts (_ :<: Tagged _ (Just h) _) = return (Just h)+        write_ts (tts :<: Tagged _ Nothing pps) =+            writeInventoryPrivate $ PatchSet tts pps+        write_ts NilRL = return Nothing++-- |writeHashIfNecessary writes the patch and returns the resulting info/hash,+-- if it has not already been written. If it has been written, we have the hash+-- in the PatchInfoAnd, so we extract and return the info/hash.+writePatchIfNecessary :: RepoPatch p => Cache -> Compression+                      -> PatchInfoAnd rt p wX wY -> IO InventoryEntry+writePatchIfNecessary c compr hp = infohp `seq`+    case extractHash hp of+        Right h -> return (infohp, mkValidHash h)+        Left p -> do+          h <- writeHashFile c compr HashedPatchesDir (showPatch ForStorage p)+          return (infohp, mkValidHash h)+  where+    infohp = info hp++-- |listInventoriesWith returns a list of the inventories hashes.+-- The first argument is to choose directory format.+-- The first argument can be readInventoryPrivate or readInventoryLocalPrivate.+-- The second argument specifies whether the files are expected+-- to be stored in plain or in bucketed format.+-- The third argument is the directory of the parent inventory files.+-- The fourth argument is the directory of the head inventory file.+listInventoriesWith+  :: (FilePath -> IO Inventory)+  -> DirLayout+  -> String -> String -> IO [String]+listInventoriesWith readInv dirformat baseDir startDir = do+    mbStartingWithInv <- getStartingWithHash startDir hashedInventory+    followStartingWiths mbStartingWithInv+  where+    getStartingWithHash dir file = inventoryParent <$> readInv (dir </> file)++    invDir = baseDir </> inventoriesDir+    nextDir dir = case dirformat of+        BucketedLayout -> invDir </> bucketFolder dir+        PlainLayout -> invDir++    followStartingWiths Nothing = return []+    followStartingWiths (Just hash) = do+        let startingWith = getValidHash hash+        mbNextInv <- getStartingWithHash (nextDir startingWith) startingWith+        (startingWith :) <$> followStartingWiths mbNextInv++-- |listInventories returns a list of the inventories hashes.+-- This function attempts to retrieve missing inventory files.+listInventories :: IO [String]+listInventories =+    listInventoriesWith readInventoryPrivate PlainLayout darcsdir darcsdir++-- | Read the given inventory file if it exist, otherwise return an empty+-- inventory. Used when we expect that some inventory files may be missing.+readInventoryLocalPrivate :: FilePath -> IO Inventory+readInventoryLocalPrivate path = do+    b <- doesFileExist path+    if b then readInventoryPrivate path+        else return emptyInventory++-- | Return inventories hashes by following the head inventory.+-- This function does not attempt to retrieve missing inventory files.+listInventoriesLocal :: IO [String]+listInventoriesLocal =+    listInventoriesWith readInventoryLocalPrivate PlainLayout darcsdir darcsdir++-- |listInventoriesRepoDir returns a list of the inventories hashes.+-- The argument @repoDir@ is the directory of the repository from which+-- we are going to read the head inventory file.+-- The rest of hashed files are read from the global cache.+listInventoriesRepoDir :: String -> IO [String]+listInventoriesRepoDir repoDir = do+    gCacheDir' <- globalCacheDir+    let gCacheInvDir = fromJust gCacheDir'+    listInventoriesWith+      readInventoryLocalPrivate BucketedLayout gCacheInvDir (repoDir </> darcsdir)++-- | Return a list of the patch filenames, extracted from inventory+-- files, by starting with the head inventory and then following the+-- chain of parent inventories.+--+-- This function does not attempt to download missing inventory files.+--+-- * The first argument specifies whether the files are expected+--   to be stored in plain or in bucketed format.+-- * The second argument is the directory of the parent inventory.+-- * The third argument is the directory of the head inventory.+listPatchesLocal :: DirLayout -> String -> String -> IO [String]+listPatchesLocal dirformat baseDir startDir = do+    inventory <- readInventoryPrivate (startDir </> hashedInventory)+    followStartingWiths (inventoryParent inventory) (inventoryPatchNames inventory)+    where+        invDir = baseDir </> inventoriesDir+        nextDir dir = case dirformat of+            BucketedLayout -> invDir </> bucketFolder dir+            PlainLayout -> invDir++        followStartingWiths Nothing patches = return patches+        followStartingWiths (Just hash) patches = do+            let startingWith = getValidHash hash+            inv <- readInventoryLocalPrivate+                (nextDir startingWith </> startingWith)+            (patches++) <$> followStartingWiths (inventoryParent inv) (inventoryPatchNames inv)++-- |listPatchesLocalBucketed is similar to listPatchesLocal, but+-- it read the inventory directory under @darcsDir@ in bucketed format.+listPatchesLocalBucketed :: String -> String -> IO [String]+listPatchesLocalBucketed = listPatchesLocal BucketedLayout++-- | copyPristine copies a pristine tree into the current pristine dir,+--   and possibly copies a clean working copy.+--   The target is read from the passed-in dir/inventory name combination.+copyPristine :: Cache -> String -> String -> WithWorkingDir -> IO ()+copyPristine cache dir iname wwd = do+    i <- fetchFilePS (dir ++ "/" ++ iname) Uncachable+    debugMessage $ "Copying hashed pristine tree: " ++ peekPristineHash i+    let tediousName = "Copying pristine"+    beginTedious tediousName+    copyHashed tediousName cache wwd $ peekPristineHash i+    endTedious tediousName++-- |copyPartialsPristine copies the pristine entries for a given list of+-- filepaths.+copyPartialsPristine :: FilePathLike fp => Cache -> String+                     -> String -> [fp] -> IO ()+copyPartialsPristine c d iname fps = do+    i <- fetchFilePS (d ++ "/" ++ iname) Uncachable+    copyPartialsHashed c (peekPristineHash i) fps++unrevertUrl :: Repository rt p wR wU wT -> String+unrevertUrl r = repoLocation r ++ "/"++darcsdir++"/patches/unrevert"++tentativelyAddPatch :: (RepoPatch p, ApplyState p ~ Tree)+                    => Repository rt p wR wU wT+                    -> Compression+                    -> Verbosity+                    -> UpdateWorking+                    -> PatchInfoAnd rt p wT wY+                    -> IO (Repository rt p wR wU wY)+tentativelyAddPatch = tentativelyAddPatch_ UpdatePristine++data UpdatePristine = UpdatePristine +                    | DontUpdatePristine+                    | DontUpdatePristineNorRevert deriving Eq++tentativelyAddPatches_ :: (RepoPatch p, ApplyState p ~ Tree)+                       => UpdatePristine+                       -> Repository rt p wR wU wT+                       -> Compression+                       -> Verbosity+                       -> UpdateWorking+                       -> FL (PatchInfoAnd rt p) wT wY+                       -> IO (Repository rt p wR wU wY)+tentativelyAddPatches_ up r c v uw ps =+    foldFL_M (\r' p -> tentativelyAddPatch_ up r' c v uw p) r ps++-- TODO re-add a safety catch for --dry-run? Maybe using a global, like dryRun+-- :: Bool, with dryRun = unsafePerformIO $ readIORef ...+tentativelyAddPatch_ :: (RepoPatch p, ApplyState p ~ Tree)+                     => UpdatePristine+                     -> Repository rt p wR wU wT+                     -> Compression+                     -> Verbosity+                     -> UpdateWorking+                     -> PatchInfoAnd rt p wT wY+                     -> IO (Repository rt p wR wU wY)++tentativelyAddPatch_ up r compr verb uw p =+    withRepoLocation r $ do+       void $ addToTentativeInventory (repoCache r) compr p+       when (up == UpdatePristine) $ do debugMessage "Applying to pristine cache..."+                                        applyToTentativePristine r verb p+                                        debugMessage "Updating pending..."+                                        tentativelyRemoveFromPending r uw p+       return (coerceT r)+++-- |applyToTentativePristine applies a patch @p@ to the tentative pristine+-- tree, and updates the tentative pristine hash+applyToTentativePristine :: (ApplyState q ~ Tree, Apply q, ShowPatch q)+                         => Repository rt p wR wU wT+                         -> Verbosity+                         -> q wT wY+                         -> IO ()+applyToTentativePristine r verb p =+    withRepoLocation r $+    do when (verb == Verbose) $ putDocLn $ text "Applying to pristine..." <+> description p+       applyToTentativePristineCwd p++applyToTentativePristineCwd :: (ApplyState p ~ Tree, Apply p) => p wX wY+                            -> IO ()+applyToTentativePristineCwd p = do+    tentativePristine <- gzReadFilePS tentativePristinePath+    -- Extract the pristine hash from the tentativePristine file, using+    -- peekPristineHash (this is valid since we normally just extract the hash from the+    -- first line of an inventory file; we can pass in a one-line file that+    -- just contains said hash).+    let tentativePristineHash = peekPristineHash tentativePristine+    newPristineHash <- applyToHashedPristine tentativePristineHash p+    writeDocBinFile tentativePristinePath $+        pokePristineHash newPristineHash tentativePristine++tentativelyRemovePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+                         => Repository rt p wR wU wT+                         -> Compression+                         -> UpdateWorking+                         -> FL (PatchInfoAnd rt p) wX wT+                         -> IO (Repository rt p wR wU wX)+tentativelyRemovePatches = tentativelyRemovePatches_ UpdatePristine++tentativelyRemovePatches_ :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+                          => UpdatePristine+                          -> Repository rt p wR wU wT+                          -> Compression+                          -> UpdateWorking+                          -> FL (PatchInfoAnd rt p) wX wT+                          -> IO (Repository rt p wR wU wX)+tentativelyRemovePatches_ up r compr uw ps =+    withRepoLocation r $ do+      when (up == UpdatePristine) $ do debugMessage "Adding changes to pending..."+                                       prepend r uw $ effect ps+      unless (up == DontUpdatePristineNorRevert) $ removeFromUnrevertContext r ps+      debugMessage "Removing changes from tentative inventory..."+      if formatHas HashedInventory (repoFormat r)+        then do removeFromTentativeInventory r compr ps+                when (up == UpdatePristine) $+                     applyToTentativePristineCwd $+                     progressFL "Applying inverse to pristine" $ invert ps+        else fail Old.oldRepoFailMsg+      return (coerceT r)++-- FIXME this is a rather weird API. If called with a patch that isn't already+-- in the repo, it fails with an obscure error from 'commuteToEnd'. It also+-- ends up redoing the work that the caller has already done - if it has+-- already commuted these patches to the end, it must also know the commuted+-- versions of the other patches in the repo.+-- |Given a sequence of patches anchored at the end of the current repository,+-- actually pull them to the end of the repository by removing any patches+-- with the same name and then adding the passed in sequence.+-- Typically callers will have obtained the passed in sequence using+-- 'findCommon' and friends.+tentativelyReplacePatches :: forall rt p wR wU wT wX+                           . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+                          => Repository rt p wR wU wT+                          -> Compression+                          -> UpdateWorking+                          -> Verbosity+                          -> FL (PatchInfoAnd rt p) wX wT+                          -> IO ()+tentativelyReplacePatches repository compr uw verb ps =+    do let ps' = filterOutFLFL (namedIsInternal . hopefully) ps+       repository' <- tentativelyRemovePatches_ DontUpdatePristineNorRevert repository compr uw ps'+       mapAdd repository' ps'+  where mapAdd :: Repository rt p wM wL wI+               -> FL (PatchInfoAnd rt p) wI wJ+               -> IO ()+        mapAdd _ NilFL = return ()+        mapAdd r (a:>:as) =+               do r' <- tentativelyAddPatch_ DontUpdatePristine r compr verb uw a+                  mapAdd r' as++-- The type here should rather be+--  ... -> Repo rt p wR wU wT -> IO (Repo rt p wT wU wT)+-- In other words: we set the recorded state to the tentative state.+finalizeRepositoryChanges :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+                          => Repository rt p wR wU wT+                          -> UpdateWorking+                          -> Compression+                          -> IO ()+finalizeRepositoryChanges r updateWorking compr+    | formatHas HashedInventory (repoFormat r) =+        withRepoLocation r $ do+            debugMessage "Finalizing changes..."+            withSignalsBlocked $ do+                 finalizeTentativeChanges r compr+                 recordedState <- readRecorded r+                 finalizePending r updateWorking recordedState+            debugMessage "Done finalizing changes..."+            ps <- readRepo r+            doesPatchIndexExist (repoLocation r) >>= (`when` createOrUpdatePatchIndexDisk r ps)+            updateIndex r+    | otherwise = fail Old.oldRepoFailMsg++-- TODO: rename this and document the transaction protocol (revert/finalize)+-- clearly.+-- |Slightly confusingly named: as well as throwing away any tentative+-- changes, revertRepositoryChanges also re-initialises the tentative state.+-- It's therefore used before makign any changes to the repo.+-- So the type should rather be+--+-- > ... -> Repo rt p wR wU wT -> IO (Repo rt p wR wU wR)+revertRepositoryChanges :: RepoPatch p+                        => Repository rt p wR wU wT+                        -> UpdateWorking+                        -> IO ()+revertRepositoryChanges r uw+ | formatHas HashedInventory (repoFormat r) =+    withRepoLocation r $+    do removeFileMayNotExist (pendingName ++ ".tentative")+       Sealed x <- readPending r+       setTentativePending r uw x+       when (uw == NoUpdateWorking) $ removeFileMayNotExist pendingName+       revertTentativeChanges+ | otherwise = fail Old.oldRepoFailMsg++removeFromUnrevertContext :: forall rt p wR wU wT wX+                           . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+                          => Repository rt p wR wU wT+                          -> FL (PatchInfoAnd rt p) wX wT+                          -> IO ()+removeFromUnrevertContext r ps = do+  Sealed bundle <- unrevert_patch_bundle `catchall` return (seal (PatchSet NilRL NilRL))+  remove_from_unrevert_context_ bundle+  where unrevert_impossible =+            do confirmed <- promptYorn "This operation will make unrevert impossible!\nProceed?"+               if confirmed then removeFileMayNotExist (unrevertUrl r)+                            else fail "Cancelled."+        unrevert_patch_bundle :: IO (SealedPatchSet rt p Origin)+        unrevert_patch_bundle = do pf <- B.readFile (unrevertUrl r)+                                   case scanBundle pf of+                                     Right foo -> return foo+                                     Left err -> fail $ "Couldn't parse unrevert patch:\n" ++ err+        remove_from_unrevert_context_ :: PatchSet rt p Origin wZ -> IO ()+        remove_from_unrevert_context_ (PatchSet NilRL NilRL) = return ()+        remove_from_unrevert_context_ bundle =+         do debugMessage "Adjusting the context of the unrevert changes..."+            debugMessage $ "Removing "++ show (lengthFL ps) +++                                  " patches in removeFromUnrevertContext!"+            ref <- readTentativeRepo r (repoLocation r)+            let withSinglet :: Sealed (FL ppp wXxx)+                            -> (forall wYyy . ppp wXxx wYyy -> IO ()) -> IO ()+                withSinglet (Sealed (x :>: NilFL)) j = j x+                withSinglet _ _ = return ()+            withSinglet (mergeThem ref bundle) $ \h_us ->+                  case commuteRL (reverseFL ps :> h_us) of+                    Nothing -> unrevert_impossible+                    Just (us' :> _) ->+                      case removeFromPatchSet ps ref of+                      Nothing -> unrevert_impossible+                      Just common ->+                          do debugMessage "Have now found the new context..."+                             bundle' <- makeBundleN Nothing common (hopefully us':>:NilFL)+                             writeDocBinFile (unrevertUrl r) bundle'+            debugMessage "Done adjusting the context of the unrevert changes!"++cleanRepository :: Repository rt p wR wU wT -> IO ()+cleanRepository r = cleanPristine r >> cleanInventories r >> cleanPatches r++-- | grab the pristine hash of _darcs/hash_inventory, and retrieve whole pristine tree,+--   possibly writing a clean working copy in the process.+createPristineDirectoryTree :: Repository rt p wR wU wT -> FilePath -> WithWorkingDir -> IO ()+createPristineDirectoryTree r reldir wwd+    | formatHas HashedInventory (repoFormat r) =+        do createDirectoryIfMissing True reldir+           withCurrentDirectory reldir $+              copyPristine (repoCache r) (repoLocation r) hashedInventoryPath wwd+    | otherwise = fail Old.oldRepoFailMsg++-- fp below really should be FileName+-- | Used by the commands dist and diff+createPartialsPristineDirectoryTree :: (FilePathLike fp)+                                    => Repository rt p wR wU wT+                                    -> [fp]+                                    -> FilePath+                                    -> IO ()+createPartialsPristineDirectoryTree r prefs dir+    | formatHas HashedInventory (repoFormat r) =+        do createDirectoryIfMissing True dir+           withCurrentDirectory dir $+            copyPartialsPristine (repoCache r) (repoLocation r)+              hashedInventoryPath prefs+    | otherwise = fail Old.oldRepoFailMsg++withRecorded :: Repository rt p wR wU wT+             -> ((AbsolutePath -> IO a) -> IO a)+             -> (AbsolutePath -> IO a)+             -> IO a+withRecorded repository mk_dir f+    = mk_dir $ \d -> do createPristineDirectoryTree repository (toFilePath d) WithWorkingDir+                        f d++withTentative :: forall rt p a wR wU wT.+                 Repository rt p wR wU wT+              -> ((AbsolutePath -> IO a) -> IO a)+              -> (AbsolutePath -> IO a)+              -> IO a+withTentative r mk_dir f+    | formatHas HashedInventory (repoFormat r) =+        mk_dir $ \d -> do copyPristine+                              (repoCache r)+                              (repoLocation r)+                              (darcsdir++"/tentative_pristine")+                              WithWorkingDir+                          f d+    | otherwise = fail Old.oldRepoFailMsg++-- | Writes out a fresh copy of the inventory that minimizes the+-- amount of inventory that need be downloaded when people pull from+-- the repository.+--+-- Specifically, it breaks up the inventory on the most recent tag.+-- This speeds up most commands when run remotely, both because a+-- smaller file needs to be transfered (only the most recent+-- inventory).  It also gives a guarantee that all the patches prior+-- to a given tag are included in that tag, so less commutation and+-- history traversal is needed.  This latter issue can become very+-- important in large repositories.+reorderInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+                 => Repository rt p wR wU wR+                 -> Compression+                 -> UpdateWorking+                 -> Verbosity+                 -> IO ()+reorderInventory repository compr uw verb = do+        debugMessage "Reordering the inventory."+        PatchSet _ ps <- misplacedPatches `fmap` readRepo repository+        tentativelyReplacePatches repository compr uw verb $ reverseRL ps+        finalizeTentativeChanges repository compr+        debugMessage "Done reordering the inventory."++-- | Returns the patches that make the most recent tag dirty.+misplacedPatches :: forall rt p wS wX . RepoPatch p+                 => PatchSet rt p wS wX+                 -> PatchSet rt p wS wX+misplacedPatches ps = +        -- Filter the repository keeping only with the tags, ordered from the+        -- most recent.+        case filter isTag $ mapRL info $ patchSet2RL ps of+                [] -> ps+                (lt:_) -> +                    -- Take the most recent tag, and split the repository in,+                    -- the clean PatchSet "up to" the tag (ts), and a RL of+                    -- patches after the tag (r).+                    case splitOnTag lt ps of+                        Just (PatchSet ts xs :> r) -> PatchSet ts (xs+<+r)+                        _ -> impossible -- Because the tag is in ps.++-- @todo: we should not have to open the result of HashedRepo and+-- seal it.  Instead, update this function to work with type witnesses+-- by fixing DarcsRepo to match HashedRepo in the handling of+-- Repository state.+readRepo :: (IsRepoType rt, RepoPatch p)+         => Repository rt p wR wU wT+         -> IO (PatchSet rt p Origin wR)+readRepo r+    | formatHas HashedInventory (repoFormat r) = readRepoHashed r (repoLocation r)+    | otherwise = do Sealed ps <- Old.readOldRepo (repoLocation r)+                     return $ unsafeCoerceP ps++-- | XOR of all hashes of the patches' metadata.+-- It enables to quickly see whether two repositories+-- have the same patches, independently of their order.+-- It relies on the assumption that the same patch cannot+-- be present twice in a repository.+-- This checksum is not cryptographically secure,+-- see http://robotics.stanford.edu/~xb/crypto06b/ .+repoXor :: (IsRepoType rt, RepoPatch p)+        => Repository rt p wR wU wR -> IO SHA1+repoXor repo = do+  hashes <- mapRL (makePatchname . info) . patchSet2RL <$> readRepo repo+  return $ foldl' sha1Xor sha1zero hashes+++
src/Darcs/Repository/HashedIO.hs view
@@ -15,14 +15,12 @@ -- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  {-# OPTIONS_GHC -fno-warn-missing-methods #-}-{-# LANGUAGE CPP, TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses #-}+{-# LANGUAGE MultiParamTypeClasses #-}  -module Darcs.Repository.HashedIO ( HashedIO,-                                   copyHashed, copyPartialsHashed,+module Darcs.Repository.HashedIO ( copyHashed, copyPartialsHashed,                                    cleanHashdir, getHashedFiles,-                                   RW(RW) -- only exported to make warning go away-                                 , pathsAndContents+                                   pathsAndContents                                  ) where  import Prelude ()@@ -49,8 +47,8 @@     , normPath     , fp2fn     , fn2fp-    , fn2niceps-    , niceps2fn+    , fn2ps+    , ps2fn     , breakOnDir     , ownName     , superName@@ -72,23 +70,15 @@ readHashFile :: Cache -> HashedDir -> String -> IO (String,B.ByteString) readHashFile c subdir hash =     do debugMessage $ "Reading hash file "++hash++" from "++hashedDir subdir++"/"-       fetchFileUsingCache c subdir hash--data HashDir r p = HashDir { permissions :: !r, cache :: !Cache,-                             rootHash :: !String }-type HashedIO p = StateT (HashDir RW p) IO+       r <- fetchFileUsingCache c subdir hash+       debugMessage $ "Result of reading hash file: " ++ show r+       return r -data RW = RW-{--class Readable r where-    isRO :: r -> Bool-    isRO = const False-instance Readable RW-instance Readable RO where-    isRO RO = True--}+data HashDir = HashDir { cache :: !Cache,+                         rootHash :: !String }+type HashedIO = StateT HashDir IO -mWithCurrentDirectory :: FileName -> HashedIO p a -> HashedIO p a+mWithCurrentDirectory :: FileName -> HashedIO a -> HashedIO a mWithCurrentDirectory fn j     | fn' == fp2fn "" = j     | otherwise =@@ -107,7 +97,7 @@                                            return x     where fn' = normPath fn -mInCurrentDirectory :: FileName -> HashedIO p a -> HashedIO p a+mInCurrentDirectory :: FileName -> HashedIO a -> HashedIO a mInCurrentDirectory fn j | fn' == fp2fn "" = j                          | otherwise =                              case breakOnDir fn' of@@ -121,10 +111,10 @@                                                    Just h -> inh h $ mInCurrentDirectory fn'' j     where fn' = normPath fn -instance ApplyMonad Tree (HashedIO p) where-    type ApplyMonadBase (HashedIO p) = IO+instance ApplyMonad Tree HashedIO where+    type ApplyMonadBase HashedIO = IO -instance ApplyMonadTree (HashedIO p) where+instance ApplyMonadTree HashedIO where     mDoesDirectoryExist fn = do thing <- identifyThing fn                                 case thing of Just (D,_) -> return True                                               _ -> return False@@ -150,7 +140,7 @@                             fail $ "Cannot remove non-empty file "++fn2fp f                        rmThing f -identifyThing :: FileName -> HashedIO p (Maybe (ObjType,String))+identifyThing :: FileName -> HashedIO (Maybe (ObjType,String)) identifyThing fn | fn' == fp2fn "" = do h <- gets rootHash                                         return $ Just (D, h)                  | otherwise = case breakOnDir fn' of@@ -161,11 +151,11 @@                                                      Just h -> inh h $ identifyThing fn''         where fn' = normPath fn -makeThing :: FileName -> (ObjType,String) -> HashedIO p ()+makeThing :: FileName -> (ObjType,String) -> HashedIO () makeThing fn (o,h) = mWithCurrentDirectory (superName $ normPath fn) $                      seta o (ownName $ normPath fn) h `fmap` readroot >>= writeroot -rmThing :: FileName -> HashedIO p ()+rmThing :: FileName -> HashedIO () rmThing fn = mWithCurrentDirectory (superName $ normPath fn) $              do c <- readroot                 let c' = filter (\(_,x,_)->x/= ownName (normPath fn)) c@@ -173,13 +163,13 @@                   then writeroot c'                   else fail "obj doesn't exist in rmThing" -readhash :: String -> HashedIO p B.ByteString+readhash :: String -> HashedIO B.ByteString readhash h = do c <- gets cache                 z <- lift $ unsafeInterleaveIO $ readHashFile c HashedPristineDir h                 let (_,out) = z                 return out -withh :: String -> HashedIO p a -> HashedIO p (String,a)+withh :: String -> HashedIO a -> HashedIO (String,a) withh h j = do hd <- get                put $ hd { rootHash = h }                x <- j@@ -187,24 +177,25 @@                put hd                return (h',x) -inh :: String -> HashedIO p a -> HashedIO p a+inh :: String -> HashedIO a -> HashedIO a inh h j = snd `fmap` withh h j -readroot :: HashedIO p [(ObjType, FileName, String)]+readroot :: HashedIO [(ObjType, FileName, String)] readroot = do haveitalready <- peekroot               cc <- gets rootHash >>= readdir               unless haveitalready $ speculate cc               return cc-    where speculate :: [(a,b,String)] -> HashedIO q ()+    where speculate :: [(a,b,String)] -> HashedIO ()           speculate c = do cac <- gets cache                            mapM_ (\(_,_,z) -> lift $ speculateFileUsingCache cac HashedPristineDir z) c-          peekroot :: HashedIO p Bool-          peekroot = do HashDir _ c h <- get+          peekroot :: HashedIO Bool+          peekroot = do HashDir c h <- get                         lift $ peekInCache c HashedPristineDir h -writeroot :: [(ObjType, FileName, String)] -> HashedIO p ()-writeroot c = do h <- writedir c-                 modify $ \hd -> hd { rootHash = h }+writeroot :: [(ObjType, FileName, String)] -> HashedIO ()+writeroot c = do+  h <- writedir c+  modify $ \hd -> hd { rootHash = h }  data ObjType = F | D deriving Eq @@ -224,24 +215,35 @@ seta o f h ((_,f',_):r) | f == f' = (o,f,h):r seta o f h (x:xs) = x : seta o f h xs -readdir :: String -> HashedIO p [(ObjType, FileName, String)]-readdir hash = (parsed . linesPS) `fmap` readhash hash-    where parsed (t:n:h:rest) | t == dir = (D, niceps2fn n, BC.unpack h) : parsed rest-                              | t == file = (F, niceps2fn n, BC.unpack h) : parsed rest-          parsed _ = []+readdir :: String -> HashedIO [(ObjType, FileName, String)]+readdir hash = do+  x <- readhash hash+  lift $ debugMessage  $ show x+  let r = (parsed . linesPS) x+  lift $ debugMessage  $ unlines $ map (\(_,fn,_) -> "DEBUG readdir " ++ hash ++ " entry: " ++ show fn) r+  return r+  where+    parsed (t:n:h:rest) | t == dir = (D, ps2fn n, BC.unpack h) : parsed rest+                        | t == file = (F, ps2fn n, BC.unpack h) : parsed rest+    parsed _ = []+ dir :: B.ByteString dir = BC.pack "directory:" file :: B.ByteString file = BC.pack "file:"  -writedir :: [(ObjType, FileName, String)] -> HashedIO p String-writedir c = writeHashFile cps-    where cps = unlinesPS $ concatMap (\ (o,d,h) -> [showO o,fn2niceps d,BC.pack h]) c++[B.empty]-          showO D = dir-          showO F = file+writedir :: [(ObjType, FileName, String)] -> HashedIO String+writedir c = do+  lift $ debugMessage  $ unlines $ map (\(_,fn,_) -> "DEBUG writedir entry: " ++ show fn) c+  writeHashFile cps+  where+    cps = unlinesPS $ concatMap wr c ++ [B.empty]+    wr (o,d,h) = [showO o,fn2ps d,BC.pack h]+    showO D = dir+    showO F = file -writeHashFile :: B.ByteString -> HashedIO p String+writeHashFile :: B.ByteString -> HashedIO String writeHashFile ps = do c <- gets cache                       -- pristine files are always compressed                       lift $ writeFileUsingCache c GzipCompression HashedPristineDir ps@@ -250,13 +252,14 @@ -- | Grab a whole pristine tree from a hash, and, if asked, --   write files in the working copy. copyHashed :: String -> Cache -> WithWorkingDir -> String -> IO ()-copyHashed k c wwd z = void . runStateT cph $ HashDir { permissions = RW, cache = c, rootHash = z }+copyHashed k c wwd z = void . runStateT cph $ HashDir { cache = c, rootHash = z }     where cph = do cc <- readroot                    lift $ tediousSize k (length cc)                    mapM_ cp cc           cp (F,n,h) = do               ps <- readhash h               lift $ finishedOneIO k (fn2fp n)+              lift $ debugMessage $ "DEBUG copyHashed " ++ show n               case wwd of                 WithWorkingDir -> lift $ writeAtomicFilePS (fn2fp n) ps                 NoWorkingDir   -> ps `seq` return ()@@ -279,7 +282,7 @@ --   Separator "/" is used since this function is used to generate --   zip archives from pristine trees. pathsAndContents :: FilePath -> Cache ->  String -> IO [(FilePath,B.ByteString)]-pathsAndContents path c root = evalStateT cph $ HashDir { permissions = RW, cache = c, rootHash = root }+pathsAndContents path c root = evalStateT cph HashDir { cache = c, rootHash = root }     where cph = do cc <- readroot                    pacs <- concat <$> mapM cp cc                    let current = if path == "." then [] else [(path ++ "/" , B.empty)]@@ -300,7 +303,7 @@ copyPartialHashed c root ff =     do createDirectoryIfMissing True (basename $ toFilePath ff)        void $ runStateT (cp $ fp2fn $ toFilePath ff)-                 HashDir { permissions = RW, cache = c,+                 HashDir { cache = c,                            rootHash = root }  where basename = reverse . dropWhile ('/' /=) . dropWhile ('/' ==) . reverse        cp f = do mt <- identifyThing f@@ -335,5 +338,4 @@                          let subs = [ fst $ darcsLocation "" (s, h') | (TreeType, _, s, h') <- x ]                              hashes = h : [ fst $ darcsLocation "" (s, h') | (_, _, s, h') <- x ]                          (hashes++) . concat <$> mapM listone subs-      hs <- concat <$> mapM listone hashroots-      return hs+      concat <$> mapM listone hashroots
− src/Darcs/Repository/HashedRepo.hs
@@ -1,776 +0,0 @@--- Copyright (C) 2006-2007 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.--{-# LANGUAGE CPP, ScopedTypeVariables #-}-module Darcs.Repository.HashedRepo-    ( inventoriesDir-    , pristineDir-    , patchesDir-    , hashedInventory-    , revertTentativeChanges-    , finalizeTentativeChanges-    , cleanPristine-    , filterDirContents-    , cleanInventories-    , cleanPatches-    , copyPristine-    , copyPartialsPristine-    , applyToTentativePristine-    , addToSpecificInventory-    , addToTentativeInventory-    , removeFromTentativeInventory-    , readRepo-    , readTentativeRepo-    , readRepoUsingSpecificInventory-    , writeAndReadPatch-    , writeTentativeInventory-    , copyHashedInventory-    , readHashedPristineRoot-    , pris2inv-    , inv2pris-    , listInventories-    , listInventoriesLocal-    , listInventoriesRepoDir-    , listPatchesLocalBucketed-    , writePatchIfNecessary-    , readRepoFromInventoryList-    , readPatchIds-    , set-    , unset-    ) where--#include "impossible.h"--import Prelude ()-import Darcs.Prelude--import Control.Arrow ( (&&&) )-import Control.Exception ( catch, IOException )-import Control.Monad ( unless )-import Data.Maybe-import qualified Data.ByteString as B ( null, length, empty ,tail, drop,-                                        ByteString, splitAt )-import qualified Data.ByteString.Char8 as BC ( unpack, dropWhile, break, pack,-                                                ByteString )-import qualified Data.Set as Set-import Darcs.Util.Hash( encodeBase16, Hash(..) )-import Darcs.Util.Tree( treeHash, Tree )-import Darcs.Util.Tree.Hashed( hashedTreeIO, readDarcsHashedNosize,-                             readDarcsHashed, writeDarcsHashed,-                             decodeDarcsHash, decodeDarcsSize )-import System.Directory ( createDirectoryIfMissing, getDirectoryContents-                        , doesFileExist, doesDirectoryExist )-import System.FilePath.Posix( (</>) )-import System.IO.Unsafe ( unsafeInterleaveIO )-import System.IO ( stderr, hPutStrLn )--import Darcs.Util.Printer.Color ( showDoc )-import Darcs.Util.External-    ( copyFileOrUrl-    , cloneFile-    , fetchFilePS-    , gzFetchFilePS-    , Cachable( Uncachable )-    )-import Darcs.Repository.Flags ( Compression, RemoteDarcs, remoteDarcs, WithWorkingDir )-import Darcs.Util.Global ( darcsdir )-import Darcs.Util.Lock-    ( writeBinFile-    , writeDocBinFile-    , writeAtomicFilePS-    ,  appendBinFile-    , appendDocBinFile-    , removeFileMayNotExist-    )-import Darcs.Patch.Set ( PatchSet(..), Tagged(..), SealedPatchSet, Origin )--import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, patchInfoAndPatch, info,-                                  extractHash, createHashed )-import Darcs.Patch ( IsRepoType, RepoPatch, Patchy, showPatch, readPatch, apply )-import Darcs.Patch.Apply ( ApplyState )-import Darcs.Patch.Read ( ReadPatch )-import Darcs.Patch.ReadMonads ( parseStrictly )-import Darcs.Patch.Depends ( removeFromPatchSet, slightlyOptimizePatchset )-import Darcs.Patch.Info ( PatchInfo, showPatchInfo, showPatchInfoUI,-                          readPatchInfo )-import Darcs.Util.Path ( FilePathLike, ioAbsoluteOrRemote, toPath )-import Darcs.Repository.Cache ( Cache(..), fetchFileUsingCache,-                                speculateFilesUsingCache, writeFileUsingCache,-                                okayHash, takeHash,-                                HashedDir(..), hashedDir, peekInCache, bucketFolder )-import Darcs.Repository.HashedIO ( copyHashed, copyPartialsHashed,-                                   cleanHashdir )-import Darcs.Repository.InternalTypes ( Repository(..), extractCache )-import Darcs.Util.File ( withCurrentDirectory )-import Darcs.Patch.Witnesses.Ordered-    ( (+<+), FL(..), RL(..), mapRL )-import Darcs.Patch.Witnesses.Sealed ( Sealed(..), seal, unseal, mapSeal )-import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )--import Darcs.Util.ByteString ( gzReadFilePS, dropSpace )-import Darcs.Util.Crypt.SHA256 ( sha256sum )-import Darcs.Util.Printer ( Doc, hcat, (<>), ($$), renderString, renderPS, text,-                 invisiblePS, RenderMode(..) )-import Darcs.Util.Progress ( beginTedious, endTedious, debugMessage, finishedOneIO )-import Darcs.Util.Workaround ( renameFile )-import Darcs.Repository.Prefs ( globalCacheDir )--makeDarcsdirPath :: String -> String-makeDarcsdirPath name = darcsdir </> name--hashedInventory, hashedInventoryPath :: String-hashedInventory = "hashed_inventory"-hashedInventoryPath = makeDarcsdirPath hashedInventory--tentativeHashedInventory, tentativeHashedInventoryPath :: String-tentativeHashedInventory = "tentative_hashed_inventory"-tentativeHashedInventoryPath = makeDarcsdirPath tentativeHashedInventory--inventoriesDir, inventoriesDirPath :: String-inventoriesDir = "inventories"-inventoriesDirPath = makeDarcsdirPath inventoriesDir--pristineDir, tentativePristinePath, pristineDirPath :: String-tentativePristinePath = makeDarcsdirPath "tentative_pristine"-pristineDir = "pristine.hashed"-pristineDirPath = makeDarcsdirPath pristineDir--patchesDir, patchesDirPath :: String-patchesDir = "patches"-patchesDirPath = makeDarcsdirPath patchesDir--pristineNamePrefix :: String-pristineNamePrefix = "pristine:"--pristineName :: B.ByteString-pristineName = BC.pack pristineNamePrefix---- | 'applyToHashedPristine' takes a root hash, a patch @p@ and attempts to--- apply the patch to the 'Tree' identified by @h@. If we encounter an old,--- size-prefixed pristine, we first convert it to the non-size-prefixed format,--- then apply the patch.-applyToHashedPristine :: (ApplyState p ~ Tree, Patchy p) => String -> p wX wY-                      -> IO String-applyToHashedPristine h p = applyOrConvertOldPristineAndApply-  where-    applyOrConvertOldPristineAndApply =-        tryApply hash `catch` \(_ :: IOException) -> handleOldPristineAndApply--    hash = decodeDarcsHash $ BC.pack h--    failOnMalformedRoot (SHA256 _) = return ()-    failOnMalformedRoot root = fail $ "Cannot handle hash: " ++ show root--    hash2root = BC.unpack . encodeBase16--    tryApply :: Hash -> IO String-    tryApply root = do-        failOnMalformedRoot root-        -- Read a non-size-prefixed pristine, failing if we encounter one.-        tree <- readDarcsHashedNosize pristineDirPath root-        (_, updatedTree) <- hashedTreeIO (apply p) tree pristineDirPath-        return . hash2root $ treeHash updatedTree--    warn = "WARNING: Doing a one-time conversion of pristine format.\n"-           ++ "This may take a while. The new format is backwards-compatible."--    handleOldPristineAndApply = do-        hPutStrLn stderr warn-        inv <- gzReadFilePS hashedInventoryPath-        let oldroot = BC.pack $ inv2pris inv-            oldrootSizeandHash = (decodeDarcsSize &&& decodeDarcsHash) oldroot-        -- Read the old size-prefixed pristine tree-        old <- readDarcsHashed pristineDirPath oldrootSizeandHash-        -- Write out the pristine tree as a non-size-prefixed pristine.-        root <- writeDarcsHashed old pristineDirPath-        let newroot = hash2root root-        -- Write out the new inventory.-        writeDocBinFile hashedInventoryPath $ pris2inv newroot inv-        cleanHashdir (Ca []) HashedPristineDir [newroot]-        hPutStrLn stderr "Pristine conversion done..."-        -- Retry applying the patch, which should now succeed.-        tryApply root---- |revertTentativeChanges swaps the tentative and "real" hashed inventory--- files, and then updates the tentative pristine with the "real" inventory--- hash.-revertTentativeChanges :: IO ()-revertTentativeChanges = do-    cloneFile hashedInventoryPath tentativeHashedInventoryPath-    i <- gzReadFilePS hashedInventoryPath-    writeBinFile tentativePristinePath $ pristineNamePrefix ++ inv2pris i---- |finalizeTentativeChanges trys to atomically swap the tentative--- inventory/pristine pointers with the "real" pointers; it first re-reads the--- inventory to optimize it, presumably to take account of any new tags, and--- then writes out the new tentative inventory, and finally does the atomic--- swap. In general, we can't clean the pristine cache at the same time, since--- a simultaneous get might be in progress.-finalizeTentativeChanges :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                         => Repository rt p wR wU wT -> Compression -> IO ()-finalizeTentativeChanges r compr = do-    debugMessage "Optimizing the inventory..."-    -- Read the tentative patches-    ps <- readTentativeRepo r "."-    writeTentativeInventory (extractCache r) compr ps-    i <- gzReadFilePS tentativeHashedInventoryPath-    p <- gzReadFilePS tentativePristinePath-    -- Write out the "optimised" tentative inventory.-    writeDocBinFile tentativeHashedInventoryPath $ pris2inv (inv2pris p) i-    -- Atomically swap.-    renameFile tentativeHashedInventoryPath hashedInventoryPath---- |readHashedPristineRoot attempts to read the pristine hash from the current--- inventory, returning Nothing if it cannot do so.-readHashedPristineRoot :: Repository rt p wR wU wT -> IO (Maybe String)-readHashedPristineRoot (Repo d _ _ _) = withCurrentDirectory d $ do-    i <- (Just <$> gzReadFilePS hashedInventoryPath)-         `catch` (\(_ :: IOException) -> return Nothing)-    return $ inv2pris <$> i---- |cleanPristine removes any obsolete (unreferenced) entries in the pristine--- cache.-cleanPristine :: Repository rt p wR wU wT -> IO ()-cleanPristine r@(Repo d _ _ _) = withCurrentDirectory d $ do-    debugMessage "Cleaning out the pristine cache..."-    i <- gzReadFilePS hashedInventoryPath-    cleanHashdir (extractCache r) HashedPristineDir [inv2pris i]---- |filterDirContents returns the contents of the directory @d@--- except files whose names begin with '.' (directories . and ..,--- hidden files) and files whose names are filtered by the function @f@, if--- @dir@ is empty, no paths are returned.-filterDirContents :: FilePath -> (FilePath -> Bool) -> IO [FilePath]-filterDirContents d f = do-    let realPath = makeDarcsdirPath d-    exists <- doesDirectoryExist realPath-    if exists-        then filter (\x -> head x /= '.' && f x) <$>-            getDirectoryContents realPath-        else return []---- |set converts a list of strings into a set of Char8 ByteStrings for faster--- Set operations.-set :: [String] -> Set.Set BC.ByteString-set = Set.fromList . map BC.pack---- |unset is the inverse of set.-unset :: Set.Set BC.ByteString -> [String]-unset = map BC.unpack . Set.toList---- |cleanInventories removes any obsolete (unreferenced) files in the--- inventories directory.-cleanInventories :: Repository rt p wR wU wT -> IO ()-cleanInventories _ = do-    debugMessage "Cleaning out inventories..."-    hs <- listInventoriesLocal-    fs <- filterDirContents inventoriesDir (const True)-    mapM_ (removeFileMayNotExist . (inventoriesDirPath </>))-        (unset $ (set fs) `Set.difference` (set hs))---- |specialPatches list of special patch files that may exist in the directory--- _darcs/patches/.-specialPatches :: [FilePath]-specialPatches = ["unrevert", "pending", "pending.tentative"]---- |cleanPatches removes any obsolete (unreferenced) files in the--- patches directory.-cleanPatches :: Repository rt p wR wU wT -> IO ()-cleanPatches _ = do-    debugMessage "Cleaning out patches..."-    hs <- listPatchesLocal darcsdir-    fs <- filterDirContents patchesDir (`notElem` specialPatches)-    mapM_ (removeFileMayNotExist . (patchesDirPath </>))-        (unset $ (set fs) `Set.difference` (set hs))----- |addToSpecificInventory adds a patch to a specific inventory file, and--- returns the FilePath whichs corresponds to the written-out patch.-addToSpecificInventory :: RepoPatch p => String -> Cache -> Compression-                       -> PatchInfoAnd rt p wX wY -> IO FilePath-addToSpecificInventory invPath c compr p = do-    let invFile = darcsdir </> invPath-    hash <- snd <$> writePatchIfNecessary c compr p-    appendDocBinFile invFile $ showPatchInfo $ info p-    appendBinFile invFile $ "\nhash: " ++ hash ++ "\n"-    return $ darcsdir </> "patches" </> hash--addToTentativeInventory :: RepoPatch p => Cache -> Compression-                        -> PatchInfoAnd rt p wX wY -> IO FilePath-addToTentativeInventory = addToSpecificInventory tentativeHashedInventory---- | Attempt to remove an FL of patches from the tentative inventory.--- This is used for commands that wish to modify already-recorded patches.------ Precondition: it must be possible to remove the patches, i.e.------ * the patches are in the repository------ * any necessary commutations will succeed-removeFromTentativeInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                             => Repository rt p wR wU wT -> Compression-                             -> FL (PatchInfoAnd rt p) wX wT -> IO ()-removeFromTentativeInventory repo compr to_remove = do-    debugMessage $ "Start removeFromTentativeInventory"-    allpatches <- readTentativeRepo repo "."-    remaining <- case removeFromPatchSet to_remove allpatches of-        Nothing -> bug "HashedRepo.removeFromTentativeInventory: precondition violated"-        Just r -> return r-    writeTentativeInventory (extractCache repo) compr remaining-    debugMessage $ "Done removeFromTentativeInventory"---- |writeHashFile takes a Doc and writes it as a hash-named file, returning the--- filename that the contents were written to.-writeHashFile :: Cache -> Compression -> HashedDir -> Doc -> IO String-writeHashFile c compr subdir d = do-    debugMessage $ "Writing hash file to " ++ hashedDir subdir-    writeFileUsingCache c compr subdir $ renderPS Standard d---- |readRepo returns the "current" repo patchset.-readRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT-         -> String -> IO (PatchSet rt p Origin wR)-readRepo = readRepoUsingSpecificInventory hashedInventory---- |readRepo returns the tentative repo patchset.-readTentativeRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                  => Repository rt p wR wU wT -> String-                  -> IO (PatchSet rt p Origin wT)-readTentativeRepo = readRepoUsingSpecificInventory tentativeHashedInventory---- |readRepoUsingSpecificInventory uses the inventory at @invPath@ to read the--- repository @repo@.-readRepoUsingSpecificInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                               => String -> Repository rt p wR wU wT-                               -> String -> IO (PatchSet rt p Origin wS)-readRepoUsingSpecificInventory invPath repo dir = do-    realdir <- toPath <$> ioAbsoluteOrRemote dir-    Sealed ps <- readRepoPrivate (extractCache repo) realdir invPath-                 `catch` \e -> do-                     hPutStrLn stderr ("Invalid repository: " ++ realdir)-                     ioError e-    return $ unsafeCoerceP ps-  where-    readRepoPrivate :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Cache -> FilePath-                    -> FilePath -> IO (SealedPatchSet rt p Origin)-    readRepoPrivate cache d iname = do-      inventory <- readInventoryPrivate (d </> darcsdir) iname-      readRepoFromInventoryList cache inventory---- |readRepoFromInventoryList allows the caller to provide an optional "from--- inventory" hash, and a list of info/hash pairs that identify a list of--- patches, returning a patchset of the resulting repo.-readRepoFromInventoryList :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Cache-                          -> (Maybe String, [(PatchInfo, String)])-                          -> IO (SealedPatchSet rt p Origin)-readRepoFromInventoryList cache = parseinvs-  where-    speculateAndParse h is i = speculate h is >> parse i h--    read_patches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => [(PatchInfo, String)]-                 -> IO (Sealed (RL (PatchInfoAnd rt p) wX))-    read_patches [] = return $ seal NilRL-    read_patches allis@((i1, h1) : is1) =-        lift2Sealed (\p rest -> rest :<: i1 `patchInfoAndPatch` p) (rp is1)-                    (createHashed h1 (const $ speculateAndParse h1 allis i1))-      where-        rp :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => [(PatchInfo, String)]-           -> IO (Sealed (RL (PatchInfoAnd rt p) wX))-        rp [] = return $ seal NilRL-        rp [(i, h), (il, hl)] =-            lift2Sealed (\p rest -> rest :<: i `patchInfoAndPatch` p)-                        (rp [(il, hl)])-                        (createHashed h-                            (const $ speculateAndParse h (reverse allis) i))-        rp ((i, h) : is) =-            lift2Sealed (\p rest -> rest :<: i `patchInfoAndPatch` p)-                        (rp is)-                        (createHashed h (parse i))--    read_tag :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => (PatchInfo, String)-             -> IO (Sealed (PatchInfoAnd rt p wX))-    read_tag (i, h) =-        mapSeal (patchInfoAndPatch i) <$> createHashed h (parse i)--    speculate :: String -> [(PatchInfo, String)] -> IO ()-    speculate h is = do-        already_got_one <- peekInCache cache HashedPatchesDir h-        unless already_got_one $-            speculateFilesUsingCache cache HashedPatchesDir (map snd is)--    parse :: ReadPatch p => PatchInfo -> String -> IO (Sealed (p wX))-    parse i h = do-        debugMessage ("Reading patch file: "++ showDoc Encode (showPatchInfoUI i))-        (fn, ps) <- fetchFileUsingCache cache HashedPatchesDir h-        case readPatch ps of-            Just p -> return p-            Nothing -> fail $ unlines [ "Couldn't parse file " ++ fn-                                      , "which is patch"-                                      , renderString Encode $ showPatchInfoUI i ]--    parseinvs :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-              => (Maybe String, [(PatchInfo, String)])-              -> IO (SealedPatchSet rt p Origin)-    parseinvs (Nothing, ris) =-        mapSeal (PatchSet NilRL) <$> read_patches (reverse ris)-    parseinvs (Just h, []) =-        bug $ "bad inventory " ++ h ++ " (no tag) in parseinvs!"-    parseinvs (Just h, t : ris) = do-        Sealed ts <- unseal seal <$> unsafeInterleaveIO (read_ts t h)-        Sealed ps <- unseal seal <$>-                        unsafeInterleaveIO (read_patches $ reverse ris)-        return $ seal $ PatchSet ts ps--    read_ts :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => (PatchInfo, String)-            -> String -> IO (Sealed (RL (Tagged rt p) Origin))-    read_ts tag0 h0 = do-        contents <- unsafeInterleaveIO $ readTaggedInventoryFromHash h0-        let is = reverse $ case contents of-                               (Just _, _ : ris0) -> ris0-                               (Nothing, ris0) -> ris0-                               (Just _, []) -> bug "inventory without tag!"-        Sealed ts <- unseal seal <$>-                         unsafeInterleaveIO-                            (case contents of-                                 (Just h', t' : _) -> read_ts t' h'-                                 (Just _, []) -> bug "inventory without tag!"-                                 (Nothing, _) -> return $ seal NilRL)-        Sealed ps <- unseal seal <$> unsafeInterleaveIO (read_patches is)-        Sealed tag00 <- read_tag tag0-        return $ seal $ ts :<: Tagged tag00 (Just h0) ps--    readTaggedInventoryFromHash :: String-                                -> IO (Maybe String, [(PatchInfo, String)])-    readTaggedInventoryFromHash invHash = do-        (fileName, pristineAndInventory) <--            fetchFileUsingCache cache HashedInventoriesDir invHash-        readInventoryFromContent fileName pristineAndInventory--    lift2Sealed :: (forall wY wZ . q wY wZ -> p wX wY -> r wX wZ)-                -> IO (Sealed (p wX))-                -> (forall wB . IO (Sealed (q wB)))-                -> IO (Sealed (r wX))-    lift2Sealed f iox ioy = do-        Sealed x <- unseal seal <$> unsafeInterleaveIO iox-        Sealed y <- unseal seal <$> unsafeInterleaveIO ioy-        return $ seal $ f y x---- |readInventoryPrivate reads the inventory with name @invName@ in @dir@.-readInventoryPrivate :: String -> String-                     -> IO (Maybe String, [(PatchInfo, String)])-readInventoryPrivate dir invName = do-    inv <- skipPristine <$> gzFetchFilePS (dir </> invName) Uncachable-    readInventoryFromContent (toPath dir ++ "/" ++ darcsdir ++ invName) inv---- |readInventoryFromContent extracts an inventory from the content of an--- inventory file, who's path is @fileName@.-readInventoryFromContent :: FilePath -> B.ByteString-                         -> IO (Maybe String, [(PatchInfo, String)])-readInventoryFromContent fileName pristineAndInventory = do-    (hash, patchIds) <--        if mbStartingWith == BC.pack "Starting with inventory:"-            then let (hash, pids) = BC.break ('\n' ==) $ B.tail pistr-                     hashStr = BC.unpack hash in-                 if okayHash hashStr-                     then return (Just hashStr, pids)-                     else fail $ "Bad hash in file " ++ fileName-            else return (Nothing, inventory)-    return (hash, readPatchIds patchIds)-  where-    inventory = skipPristine pristineAndInventory-    (mbStartingWith, pistr) = BC.break ('\n' ==) inventory---- |copyRepo copies the hashed inventory of @repo@ to the repository located at--- @remote@.-copyHashedInventory :: RepoPatch p => Repository rt p wR wU wT -> RemoteDarcs -> String -> IO ()-copyHashedInventory (Repo outr _ _ _) rdarcs inr | remote <- remoteDarcs rdarcs = do-    createDirectoryIfMissing False (outr ++ "/" ++ inventoriesDirPath)-    copyFileOrUrl remote (inr </> darcsdir </> hashedInventory)-                         (outr </> darcsdir </> hashedInventory)-                  Uncachable -- no need to copy anything but hashed_inventory!-    debugMessage "Done copying hashed inventory."---- |writeAndReadPatch makes a patch lazy, by writing it out to disk (thus--- forcing it), and then re-reads the patch lazily.-writeAndReadPatch :: (IsRepoType rt, RepoPatch p) => Cache -> Compression-                  -> PatchInfoAnd rt p wX wY -> IO (PatchInfoAnd rt p wX wY)-writeAndReadPatch c compr p = do-    (i, h) <- writePatchIfNecessary c compr p-    unsafeInterleaveIO $ readp h i-  where-    parse i h = do-        debugMessage ("Rereading patch file: "++ showDoc Encode (showPatchInfoUI i))-        (fn, ps) <- fetchFileUsingCache c HashedPatchesDir h-        case readPatch ps of-            Just x -> return x-            Nothing -> fail $ unlines [ "Couldn't parse patch file " ++ fn-                                      , "which is"-                                      , renderString Encode $ showPatchInfoUI i]--    readp h i = do Sealed x <- createHashed h (parse i)-                   return . patchInfoAndPatch i $ unsafeCoerceP x---- | writeTentativeInventory writes @patchSet@ as the tentative inventory.-writeTentativeInventory :: RepoPatch p => Cache -> Compression-                        -> PatchSet rt p Origin wX -> IO ()-writeTentativeInventory cache compr patchSet = do-    debugMessage "in writeTentativeInventory..."-    createDirectoryIfMissing False inventoriesDirPath-    beginTedious tediousName-    hsh <- writeInventoryPrivate $ slightlyOptimizePatchset patchSet-    endTedious tediousName-    debugMessage "still in writeTentativeInventory..."-    case hsh of-        Nothing -> writeBinFile (darcsdir </> tentativeHashedInventory) ""-        Just h -> do-            content <- snd <$> fetchFileUsingCache cache HashedInventoriesDir h-            writeAtomicFilePS (darcsdir </> tentativeHashedInventory) content-  where-    tediousName = "Writing inventory"-    writeInventoryPrivate :: RepoPatch p => PatchSet rt p Origin wX-                          -> IO (Maybe String)-    writeInventoryPrivate (PatchSet NilRL NilRL) = return Nothing-    writeInventoryPrivate (PatchSet NilRL ps) = do-        inventory <- sequence $ mapRL (writePatchIfNecessary cache compr) ps-        let inventorylist = hcat (map pihash $ reverse inventory)-        hash <- writeHashFile cache compr HashedInventoriesDir inventorylist-        return $ Just hash-    writeInventoryPrivate-        (PatchSet xs@(_ :<: Tagged t _ _) x) = do-        resthash <- write_ts xs-        finishedOneIO tediousName $ fromMaybe "" resthash-        inventory <- sequence $ mapRL (writePatchIfNecessary cache compr)-                                    (NilRL :<: t +<+ x)-        let inventorylist = hcat (map pihash $ reverse inventory)-            inventorycontents =-                case resthash of-                    Just h -> text ("Starting with inventory:\n" ++ h) $$-                                  inventorylist-                    Nothing -> inventorylist-        hash <- writeHashFile cache compr HashedInventoriesDir inventorycontents-        return $ Just hash-      where-        -- | write_ts writes out a tagged patchset. If it has already been-        -- written, we'll have the hash, so we can immediately return it.-        write_ts :: RepoPatch p => RL (Tagged rt p) Origin wX-                 -> IO (Maybe String)-        write_ts (_ :<: Tagged _ (Just h) _) = return (Just h)-        write_ts (tts :<: Tagged _ Nothing pps) =-            writeInventoryPrivate $ PatchSet tts pps-        write_ts NilRL = return Nothing---- |writeHashIfNecessary writes the patch and returns the resulting info/hash,--- if it has not already been written. If it has been written, we have the hash--- in the PatchInfoAnd, so we extract and return the info/hash.-writePatchIfNecessary :: RepoPatch p => Cache -> Compression-                      -> PatchInfoAnd rt p wX wY -> IO (PatchInfo, String)-writePatchIfNecessary c compr hp = infohp `seq`-    case extractHash hp of-        Right h -> return (infohp, h)-        Left p -> (\h -> (infohp, h)) <$>-                        writeHashFile c compr HashedPatchesDir (showPatch p)-  where-    infohp = info hp---- |pihash takes an info/hash pair, and renders the info, along with the hash--- as a Doc.-pihash :: (PatchInfo, String) -> Doc-pihash (pinf, hash) = showPatchInfo pinf $$ text ("hash: " ++ hash ++ "\n")---- |listInventoriesWith returns a list of the inventories hashes.--- The function @f@ can be readInventoryPrivate or readInventoryLocalPrivate.--- The argument @hashedRepoDir@ is the path to the repository,--- where it's the 'hashed_inventory' file.--- The argument @darcsDir@ is the path to the directory of inventories files.-listInventoriesWith ::  (String -> String-    -> IO (Maybe String, [(PatchInfo, String)]))-    -> String -> String -> IO [String]-listInventoriesWith f darcsDir hashedRepoDir = do-    mbStartingWithInv <- getStartingWithHash hashedRepoDir hashedInventory-    followStartingWiths mbStartingWithInv-  where-    getStartingWithHash invDir inv =-        fst <$> f invDir inv--    followStartingWiths Nothing = return []-    followStartingWiths (Just startingWith) = do-        mbNextInv <- getStartingWithHash (darcsDir </> inventoriesDir) startingWith-        (startingWith :) <$> followStartingWiths mbNextInv---- |listInventoriesBucketedWith is similar to listInventoriesWith, but--- it read the inventory directory under @darcsDir@ in bucketed format.-listInventoriesBucketedWith ::  (String -> String-    -> IO (Maybe String, [(PatchInfo, String)]))-    -> String -> String -> IO [String]-listInventoriesBucketedWith f darcsDir hashedRepoDir = do-    mbStartingWithInv <- getStartingWithHash hashedRepoDir hashedInventory-    followStartingWiths mbStartingWithInv-  where-    getStartingWithHash invDir inv =-        fst <$> f invDir inv--    followStartingWiths Nothing = return []-    followStartingWiths (Just startingWith) = do-        mbNextInv <- getStartingWithHash-            (darcsDir </> inventoriesDir </> bucketFolder startingWith) startingWith-        (startingWith :) <$> followStartingWiths mbNextInv---- |listInventories returns a list of the inventories hashes.--- This function attempts to retrieve missing inventory files.-listInventories :: IO [String]-listInventories = listInventoriesWith readInventoryPrivate darcsdir darcsdir---- |readInventoryLocalPrivate reads the inventory with name @invName@ in @dir@--- if it exist, otherwise returns an empty inventory.-readInventoryLocalPrivate :: String -> String-    -> IO (Maybe String, [(PatchInfo, String)])-readInventoryLocalPrivate dir invName = do-    b <- doesFileExist (dir </> invName)-    if b then readInventoryPrivate dir invName-        else return (Nothing, [])---- |listInventoriesLocal returns a list of the inventories hashes.--- This function does not attempt to retrieve missing inventory files.-listInventoriesLocal :: IO [String]-listInventoriesLocal = listInventoriesWith readInventoryLocalPrivate darcsdir darcsdir---- |listInventoriesRepoDir returns a list of the inventories hashes.--- The argument @repoDir@ is the directory of the repository from which--- we are going to read the "hashed_inventory" file.--- The rest of hashed files are read from the global cache.-listInventoriesRepoDir :: String -> IO [String]-listInventoriesRepoDir repoDir = do-    gCacheDir' <- globalCacheDir-    let gCacheInvDir = fromJust gCacheDir'-    listInventoriesBucketedWith readInventoryLocalPrivate gCacheInvDir (repoDir </> darcsdir)---- |listPatchesLocal returns a list of the patches hashes, extracted--- from inventory files, by following the inventory "chain" of "Starting--- with inventory" hashes. This function does not attempt to download missing--- inventory files.--- The argument @darcsDir@ is the path to the darcs directory (e.g. "_darcs")--- of the repository from which we're going to read the inventories.-listPatchesLocal :: String -> IO [String]-listPatchesLocal darcsDir = do-    inventory <- readInventoryPrivate darcsDir hashedInventory-    followStartingWiths (fst inventory) (getPatches inventory)-    where-        followStartingWiths Nothing patches = return patches-        followStartingWiths (Just startingWith) patches = do-            inv <- readInventoryLocalPrivate (darcsDir </> inventoriesDir) startingWith-            (patches++) <$> followStartingWiths (fst inv) (getPatches inv)--        getPatches inv = map snd (snd inv)---- |listPatchesLocalBucketed is similar to listPatchesLocal, but--- it read the inventory directory under @darcsDir@ in bucketed format.-listPatchesLocalBucketed :: String -> String -> IO [String]-listPatchesLocalBucketed darcsDir hashedRepoDir = do-    inventory <- readInventoryPrivate hashedRepoDir hashedInventory-    followStartingWiths (fst inventory) (getPatches inventory)-    where-        followStartingWiths Nothing patches = return patches-        followStartingWiths (Just startingWith) patches = do-            inv <- readInventoryLocalPrivate-                (darcsDir </> inventoriesDir </> bucketFolder startingWith) startingWith-            (patches++) <$> followStartingWiths (fst inv) (getPatches inv)--        getPatches inv = map snd (snd inv)---- | 'readPatchIds inventory' parses the content of a hashed_inventory file--- after the "pristine:" and "Starting with inventory:" header lines have--- been removed.  The second value in the resulting tuples is the file hash--- of the associated patch (the "hash:" line).-readPatchIds :: B.ByteString -> [(PatchInfo, String)]-readPatchIds inv | B.null inv = []-readPatchIds inv = case parseStrictly readPatchInfo inv of-                       Nothing -> []-                       Just (pinfo, r) ->-                           case readHash r of-                               Nothing -> []-                               Just (h, r') -> (pinfo, h) : readPatchIds r'-  where-    readHash :: B.ByteString -> Maybe (String, B.ByteString)-    readHash s = let s' = dropSpace s-                     (l, r) = BC.break ('\n' ==) s'-                     (kw, h) = BC.break (' ' ==) l in-                 if kw /= BC.pack "hash:" || B.length h <= 1-                     then Nothing-                     else Just (BC.unpack $ B.tail h, r)---- |applyToTentativePristine applies a patch @p@ to the tentative pristine--- tree, and updates the tentative pristine hash-applyToTentativePristine :: (ApplyState p ~ Tree, Patchy p) => p wX wY-                         -> IO ()-applyToTentativePristine p = do-    tentativePristine <- gzReadFilePS tentativePristinePath-    -- Extract the pristine hash from the tentativePristine file, using-    -- inv2pris (this is valid since we normally just extract the hash from the-    -- first line of an inventory file; we can pass in a one-line file that-    -- just contains said hash).-    let tentativePristineHash = inv2pris tentativePristine-    newPristineHash <- applyToHashedPristine tentativePristineHash p-    writeDocBinFile tentativePristinePath $-        pris2inv newPristineHash tentativePristine---- | copyPristine copies a pristine tree into the current pristine dir,---   and possibly copies a clean working copy.---   The target is read from the passed-in dir/inventory name combination.-copyPristine :: Cache -> String -> String -> WithWorkingDir -> IO ()-copyPristine cache dir iname wwd = do-    i <- fetchFilePS (dir ++ "/" ++ iname) Uncachable-    debugMessage $ "Copying hashed pristine tree: " ++ inv2pris i-    let tediousName = "Copying pristine"-    beginTedious tediousName-    copyHashed tediousName cache wwd $ inv2pris i-    endTedious tediousName---- |copyPartialsPristine copies the pristine entries for a given list of--- filepaths.-copyPartialsPristine :: FilePathLike fp => Cache -> String-                     -> String -> [fp] -> IO ()-copyPartialsPristine c d iname fps = do-    i <- fetchFilePS (d ++ "/" ++ iname) Uncachable-    copyPartialsHashed c (inv2pris i) fps---- |pris2inv takes an updated pristine hash and an inventory, and outputs the--- new pristine hash followed by the original inventory (having skipped the old--- inventory hash).-pris2inv :: String -> B.ByteString -> Doc-pris2inv h inv = invisiblePS pristineName <> text h $$-                     invisiblePS (skipPristine inv)---- |inv2pris takes the content of an inventory, and extracts the corresponding--- pristine hash from the inventory (the hash is prefixed by "pristine:").-inv2pris :: B.ByteString -> String-inv2pris inv = case tryDropPristineName inv of-                   Just rest -> case takeHash rest of-                                    Just (h, _) -> h-                                    Nothing -> error "Bad hash in inventory!"-                   Nothing -> sha256sum B.empty---- |skipPristine drops the 'pristine: HASH' prefix line, if present.-skipPristine :: B.ByteString -> B.ByteString-skipPristine ps = case tryDropPristineName ps of-    Just rest -> B.drop 1 $ BC.dropWhile (/= '\n') rest-    Nothing -> ps---- |tryDropPristineName returns the result of dropping the pristineName from--- the input, if it was present, otherwise it returns Nothing.-tryDropPristineName :: B.ByteString -> Maybe B.ByteString-tryDropPristineName input =-    if prefix == pristineName then Just rest else Nothing-  where-    (prefix, rest) = B.splitAt (B.length pristineName) input
+ src/Darcs/Repository/Identify.hs view
@@ -0,0 +1,229 @@+{-|+License : GPL-2++A set of functions to identify and find Darcs repositories+from a given @URL@ or a given filesystem path.+-}++module Darcs.Repository.Identify+    ( maybeIdentifyRepository+    , identifyRepository+    , identifyRepositoryFor+    , IdentifyRepo(..)+    , findRepository+    , amInRepository+    , amNotInRepository+    , amInHashedRepository+    , seekRepo+    , findAllReposInDir+    ) where++import Prelude ()+import Darcs.Prelude++import Control.Monad ( forM )+import Darcs.Repository.Format ( tryIdentifyRepoFormat+                               , readProblem+                               , transferProblem+                               )+import System.Directory ( doesDirectoryExist+                        , setCurrentDirectory+                        , createDirectoryIfMissing+                        , doesFileExist+                        , getDirectoryContents+                        )+import System.FilePath.Posix ( (</>) )+import System.IO.Error ( catchIOError )+import Data.Maybe ( fromMaybe )++import Darcs.Repository.Old ( oldRepoFailMsg )+import Darcs.Repository.Flags ( UseCache(..), WorkRepo (..) )+import Darcs.Util.Path+    ( toFilePath+    , ioAbsoluteOrRemote+    , toPath+    )+import Darcs.Util.Exception ( catchall )+import Darcs.Util.URL ( isValidLocalPath )+import Darcs.Util.Workaround+    ( getCurrentDirectory+    )+import Darcs.Repository.Prefs ( getCaches )+import Darcs.Repository.InternalTypes( Repository+                                     , PristineType(..)+                                     , mkRepo+                                     , repoFormat+                                     , repoPristineType+                                     )+import Darcs.Util.Global ( darcsdir )++import System.Mem( performGC )++-- | The status of a given directory: is it a darcs repository?+data IdentifyRepo rt p wR wU wT+    = BadRepository String -- ^ looks like a repository with some error+    | NonRepository String -- ^ safest guess+    | GoodRepository (Repository rt p wR wU wT)++-- | Tries to identify the repository in a given directory+maybeIdentifyRepository :: UseCache -> String -> IO (IdentifyRepo rt p wR wU wT)+maybeIdentifyRepository useCache "." =+    do darcs <- doesDirectoryExist darcsdir+       if not darcs+        then return (NonRepository $ "Missing " ++ darcsdir ++ " directory")+        else do+        repoFormatOrError <- tryIdentifyRepoFormat "."+        here <- toPath `fmap` ioAbsoluteOrRemote "."+        case repoFormatOrError of+          Left err -> return $ NonRepository err+          Right rf ->+              case readProblem rf of+              Just err -> return $ BadRepository err+              Nothing -> do pris <- identifyPristine+                            cs <- getCaches useCache here+                            return $ GoodRepository $ mkRepo here rf pris cs+maybeIdentifyRepository useCache url' =+ do url <- toPath `fmap` ioAbsoluteOrRemote url'+    repoFormatOrError <- tryIdentifyRepoFormat url+    case repoFormatOrError of+      Left e -> return $ NonRepository e+      Right rf -> case readProblem rf of+                  Just err -> return $ BadRepository err+                  Nothing ->  do cs <- getCaches useCache url+                                 return $ GoodRepository $ mkRepo url rf NoPristine cs++identifyPristine :: IO PristineType+identifyPristine =+    do pristine <- doesDirectoryExist $ darcsdir++"/pristine"+       current  <- doesDirectoryExist $ darcsdir++"/current"+       hashinv  <- doesFileExist      $ darcsdir++"/hashed_inventory"+       case (pristine || current, hashinv) of+           (False, False) -> return NoPristine+           (True,  False) -> return PlainPristine+           (False, True ) -> return HashedPristine+           _ -> fail "Multiple pristine trees."++-- | identifyRepository identifies the repo at 'url'. Warning:+-- you have to know what kind of patches are found in that repo.+identifyRepository :: forall rt p wR wU wT. UseCache -> String+                           -> IO (Repository rt p wR wU wT)+identifyRepository useCache url =+    do er <- maybeIdentifyRepository useCache url+       case er of+         BadRepository s -> fail s+         NonRepository s -> fail s+         GoodRepository r -> return r++-- | @identifyRepositoryFor repo url@ identifies (and returns) the repo at 'url',+-- but fails if it is not compatible for reading from and writing to.+identifyRepositoryFor :: forall rt p wR wU wT vR vU vT.+                         Repository rt p wR wU wT+                      -> UseCache+                      -> String+                      -> IO (Repository rt p vR vU vT)+identifyRepositoryFor source useCache url =+    do target <- identifyRepository useCache url+       case transferProblem (repoFormat target) (repoFormat source) of+         Just e -> fail $ "Incompatibility with repository " ++ url ++ ":\n" ++ e+         Nothing -> return target++amInRepository :: WorkRepo -> IO (Either String ())+amInRepository (WorkRepoDir d) =+  do+    setCurrentDirectory d+    status <- maybeIdentifyRepository YesUseCache "."+    case status of+      GoodRepository _ -> return (Right ())+      BadRepository  e -> return (Left $ "While " ++ d ++ " looks like a repository directory, we have a problem with it:\n" ++ e)+      NonRepository  _ -> return (Left "You need to be in a repository directory to run this command.")+  `catchIOError`+    \e -> return (Left (show e))+  +amInRepository _ =+  fromMaybe (Left "You need to be in a repository directory to run this command.") <$> seekRepo++amInHashedRepository :: WorkRepo -> IO (Either String ())+amInHashedRepository wd+ = do inrepo <- amInRepository wd+      case inrepo of+       Right _ -> do pristine <- identifyPristine+                     case pristine of+                       HashedPristine -> return (Right ())+                       _ -> return (Left oldRepoFailMsg)+       left    -> return left++-- | hunt upwards for the darcs repository+-- This keeps changing up one parent directory, testing at each+-- step if the current directory is a repository or not.  $+-- The result is:+--   Nothing, if no repository found+--   Just (Left errorMessage), if bad repository found+--   Just (Right ()), if good repository found.+-- WARNING this changes the current directory for good if matchFn succeeds+seekRepo :: IO (Maybe (Either String ()))+seekRepo = getCurrentDirectory >>= helper where+   helper startpwd = do+    status <- maybeIdentifyRepository YesUseCache "."+    case status of+      GoodRepository _ -> return . Just $ Right ()+      BadRepository e  -> return . Just $ Left e+      NonRepository _ ->+            do cd <- toFilePath `fmap` getCurrentDirectory+               setCurrentDirectory ".."+               cd' <- toFilePath `fmap` getCurrentDirectory+               if cd' /= cd+                  then helper startpwd+                  else do setCurrentDirectory startpwd+                          return Nothing++-- The performGC in this function is a workaround for a library/GHC bug,+-- http://hackage.haskell.org/trac/ghc/ticket/2924 -- (doesn't seem to be a+-- problem on fast machines, but virtual ones trip this from time to time)+amNotInRepository :: WorkRepo -> IO (Either String ())+amNotInRepository (WorkRepoDir d) = do+    createDirectoryIfMissing False d+       `catchall` (performGC >> createDirectoryIfMissing False d)+    -- note that the above could always fail+    setCurrentDirectory d+    amNotInRepository WorkRepoCurrentDir+amNotInRepository _ = do+       status <- maybeIdentifyRepository YesUseCache "."+       case status of+         GoodRepository _ -> return (Left "You may not run this command in a repository.")+         BadRepository e  -> return (Left $ "You may not run this command in a repository.\nBy the way, we have a problem with it:\n" ++ e)+         NonRepository _  -> return (Right ())++findRepository :: WorkRepo -> IO (Either String ())+findRepository workrepo =+  case workrepo of+    WorkRepoPossibleURL d | isValidLocalPath d -> do+      setCurrentDirectory d+      findRepository WorkRepoCurrentDir+    WorkRepoDir d -> do+      setCurrentDirectory d+      findRepository WorkRepoCurrentDir+    _ -> fromMaybe (Right ()) <$> seekRepo+  `catchIOError` \e ->+    return (Left (show e))++-- | @findAllReposInDir topDir@ returns all paths to repositories under @topDir@.+findAllReposInDir :: FilePath -> IO [FilePath]+findAllReposInDir topDir = do+  isDir <- doesDirectoryExist topDir+  if isDir+    then do+      status <- maybeIdentifyRepository NoUseCache topDir+      case status of+        GoodRepository repo+          | HashedPristine <- repoPristineType repo -> return [topDir]+          | otherwise -> return [] -- old fashioned or broken repo+        _             -> getRecursiveDarcsRepos' topDir+    else return []+  where+    getRecursiveDarcsRepos' d = do+      names <- getDirectoryContents d+      let properNames = filter (\x -> head x /= '.') names+      paths <- forM properNames $ \name -> do+        let path = d </> name+        findAllReposInDir path+      return (concat paths)
− src/Darcs/Repository/Internal.hs
@@ -1,1092 +0,0 @@--- Copyright (C) 2002-2004,2007-2008 David Roundy--- Copyright (C) 2005 Juliusz Chroboczek------ 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.--{-# LANGUAGE CPP, ScopedTypeVariables, Rank2Types, RankNTypes, PatternGuards #-}--module Darcs.Repository.Internal-    ( Repository(..)-    , maybeIdentifyRepository-    , identifyRepository-    , identifyRepositoryFor-    , IdentifyRepo(..)-    , findRepository-    , amInRepository-    , amNotInRepository-    , amInHashedRepository-    , revertRepositoryChanges-    , announceMergeConflicts-    , setTentativePending-    , checkUnrecordedConflicts-    , readRepo-    , readTentativeRepo-    , readRepoUsingSpecificInventory-    , prefsUrl-    , withRecorded-    , withTentative-    , tentativelyAddPatch-    , tentativelyRemovePatches-    , tentativelyRemovePatches_-    , tentativelyRemoveFromPending-    , tentativelyAddToPending-    , tentativelyAddPatch_-    , tentativelyAddPatches_-    , tentativelyReplacePatches-    , finalizeRepositoryChanges-    , unrevertUrl-    , applyToWorking-    , createPristineDirectoryTree-    , createPartialsPristineDirectoryTree-    , reorderInventory-    , cleanRepository-    , setScriptsExecutable-    , setScriptsExecutablePatches-    , UpdatePristine(..)-    , MakeChanges(..)-    , applyToTentativePristine-    , makeNewPending-    , seekRepo-    , repoPatchType-    , repoXor-    ) where--import Prelude ()-import Darcs.Prelude--import Darcs.Util.Printer ( putDocLn-               , (<+>)-               , text-               , ($$)-               , redText-               , putDocLnWith-               , ($$)-               )-import Darcs.Util.Printer.Color (fancyPrinters)-import Darcs.Util.Crypt.SHA1 ( SHA1, sha1Xor, zero )-import Darcs.Repository.State ( readRecorded-                              , readWorking-                              , updateIndex-                              )-import Darcs.Repository.Pending-    ( readPending-    , readTentativePending-    , writeTentativePending-    , readNewPending-    , writeNewPending-    , pendingName-    )-import System.Exit ( exitSuccess )-import Darcs.Repository.ApplyPatches-    ( runTolerantly-    , runSilently-    , runDefault-    )--import Darcs.Util.SignalHandler ( withSignalsBlocked )-import Darcs.Repository.Format ( RepoFormat-                               , RepoProperty( HashedInventory-                                             , NoWorkingDir-                                             )-                               , tryIdentifyRepoFormat-                               , formatHas-                               , readProblem-                               , transferProblem-                               )-import System.Directory ( doesDirectoryExist-                        , setCurrentDirectory-                        , createDirectoryIfMissing-                        , doesFileExist-                        )-import Control.Monad ( when-                     , unless-                     , filterM-                     , void-                     )--import Control.Exception ( catch, IOException )--import qualified Data.ByteString as B ( readFile-                                      , isPrefixOf-                                      )-import qualified Data.ByteString.Char8 as BC (pack)-import Data.List( foldl' )-import Data.List.Ordered ( nubSort )-import Data.Maybe ( fromMaybe )-import Darcs.Patch ( Effect-                   , primIsHunk-                   , primIsBinary-                   , description-                   , tryToShrink-                   , commuteFLorComplain-                   , commute-                   , fromPrim-                   , RepoPatch-                   , IsRepoType-                   , Patchy-                   , merge-                   , listConflictedFiles-                   , listTouchedFiles-                   , WrappedNamed-                   , commuteRL-                   , fromPrims-                   , readPatch-                   , effect-                   , invert-                   , primIsAddfile-                   , primIsAdddir-                   , primIsSetpref-                   , apply-                   , applyToTree-                   )--import Darcs.Patch.Dummy ( DummyPatch )--import Darcs.Patch.Apply ( ApplyState )--import Darcs.Patch.Inspect ( PatchInspect )-import Darcs.Patch.Prim ( PrimPatchBase-                        , PrimOf-                        , tryShrinkingInverse-                        , PrimPatch-                        )-import Darcs.Patch.Bundle ( scanBundle-                          , makeBundleN-                          )-import Darcs.Patch.Info ( isTag, makePatchname )-import Darcs.Patch.Named.Wrapped ( namedIsInternal )-import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd-                                , hopefully-                                , info-                                )-import Darcs.Patch.Type ( PatchType(..) )--import qualified Darcs.Repository.HashedRepo as HashedRepo-                            ( revertTentativeChanges-                            , finalizeTentativeChanges-                            , removeFromTentativeInventory-                            , copyPristine-                            , copyPartialsPristine-                            , applyToTentativePristine-                            , addToTentativeInventory-                            , readRepo-                            , readTentativeRepo-                            , readRepoUsingSpecificInventory-                            , cleanPristine-                            , cleanInventories-                            , cleanPatches-                            )-import qualified Darcs.Repository.Old as Old-                            ( revertTentativeChanges-                            , readOldRepo-                            , oldRepoFailMsg-                            )-import Darcs.Repository.Flags-    ( Compression, Verbosity(..), UseCache(..), UpdateWorking (..), AllowConflicts (..), ExternalMerge (..)-    , WorkRepo (..), WithWorkingDir (WithWorkingDir) )-import Darcs.Patch.Witnesses.Eq ( EqCheck(..) )-import Darcs.Patch.Witnesses.Unsafe-    ( unsafeCoerceP, unsafeCoercePStart )-import Darcs.Patch.Witnesses.Ordered-    ( FL(..)-    , RL(..)-    , (:\/:)(..)-    , (:/\:)(..)-    , (:>)(..)-    , (+>+)-    , (+<+)-    , lengthFL-    , allFL-    , filterOutFLFL-    , reverseFL-    , mapFL_FL-    , concatFL-    , reverseRL-    , mapRL-    )-import Darcs.Patch.Witnesses.Sealed-    ( Sealed(Sealed)-    , seal-    , FlippedSeal(FlippedSeal)-    , flipSeal-    , mapSeal-    )-import Darcs.Patch.Permutations ( commuteWhatWeCanFL-                                , removeFL-                                )-import Darcs.Patch.Set ( PatchSet(..)-                       , SealedPatchSet-                       , newset2RL-                       , Origin-                       )-import Darcs.Patch.Depends ( removeFromPatchSet-                           , mergeThem-                           , splitOnTag-                           )-import Darcs.Patch.Show ( ShowPatch )-import Darcs.Util.Path-    ( FilePathLike-    , AbsolutePath-    , toFilePath-    , ioAbsoluteOrRemote-    , toPath-    , anchorPath-    )-import Darcs.Util.Exception ( catchall )-import Darcs.Util.File ( withCurrentDirectory )-import Darcs.Util.Prompt ( promptYorn )-import Darcs.Util.Progress ( debugMessage )-import Darcs.Patch.Progress (progressFL)-import Darcs.Util.URL ( isValidLocalPath )-import Darcs.Util.Workaround-    ( getCurrentDirectory-    , renameFile-    , setExecutable-    )-import Darcs.Repository.Prefs ( getCaches )-import Darcs.Util.Lock-    ( writeDocBinFile-    , removeFileMayNotExist-    )-import Darcs.Repository.InternalTypes( Repository(..)-                                     , Pristine(..)-                                     )-import Darcs.Util.Global ( darcsdir )--import System.Mem( performGC )--import Darcs.Util.Tree ( Tree )-import qualified Darcs.Util.Tree as Tree-import Darcs.Repository.PatchIndex ( createOrUpdatePatchIndexDisk, doesPatchIndexExist )-#include "impossible.h"---- | The status of a given directory: is it a darcs repository?-data IdentifyRepo rt p wR wU wT-    = BadRepository String -- ^ looks like a repository with some error-    | NonRepository String -- ^ safest guess-    | GoodRepository (Repository rt p wR wU wT)---- | Tries to identify the repository in a given directory-maybeIdentifyRepository :: UseCache -> String -> IO (IdentifyRepo rt p wR wU wT)-maybeIdentifyRepository useCache "." =-    do darcs <- doesDirectoryExist darcsdir-       if not darcs-        then return (NonRepository $ "Missing " ++ darcsdir ++ " directory")-        else do-        repoFormatOrError <- tryIdentifyRepoFormat "."-        here <- toPath `fmap` ioAbsoluteOrRemote "."-        case repoFormatOrError of-          Left err -> return $ NonRepository err-          Right rf ->-              case readProblem rf of-              Just err -> return $ BadRepository err-              Nothing -> do pris <- identifyPristine-                            cs <- getCaches useCache here-                            return $ GoodRepository $ Repo here rf pris cs-maybeIdentifyRepository useCache url' =- do url <- toPath `fmap` ioAbsoluteOrRemote url'-    repoFormatOrError <- tryIdentifyRepoFormat url-    case repoFormatOrError of-      Left e -> return $ NonRepository e-      Right rf -> case readProblem rf of-                  Just err -> return $ BadRepository err-                  Nothing ->  do cs <- getCaches useCache url-                                 return $ GoodRepository $ Repo url rf NoPristine cs--identifyPristine :: IO Pristine-identifyPristine =-    do pristine <- doesDirectoryExist $ darcsdir++"/pristine"-       current  <- doesDirectoryExist $ darcsdir++"/current"-       hashinv  <- doesFileExist      $ darcsdir++"/hashed_inventory"-       case (pristine || current, hashinv) of-           (False, False) -> return NoPristine-           (True,  False) -> return PlainPristine-           (False, True ) -> return HashedPristine-           _ -> fail "Multiple pristine trees."---- | identifyRepository identifies the repo at 'url'. Warning:--- you have to know what kind of patches are found in that repo.-identifyRepository :: forall rt p wR wU wT. UseCache -> String-                           -> IO (Repository rt p wR wU wT)-identifyRepository useCache url =-    do er <- maybeIdentifyRepository useCache url-       case er of-         BadRepository s -> fail s-         NonRepository s -> fail s-         GoodRepository r -> return r---- | @identifyRepositoryFor repo url@ identifies (and returns) the repo at 'url',--- but fails if it is not compatible for reading from and writing to.-identifyRepositoryFor :: forall rt p wR wU wT vR vU vT. RepoPatch p-                      => Repository rt p wR wU wT-                      -> UseCache-                      -> String-                      -> IO (Repository rt p vR vU vT)-identifyRepositoryFor (Repo _ source _ _) useCache url =-    do Repo absurl target x c <- identifyRepository useCache url-       case transferProblem target source of-         Just e -> fail $ "Incompatibility with repository " ++ url ++ ":\n" ++ e-         Nothing -> return $ Repo absurl target x c--amInRepository :: WorkRepo -> IO (Either String ())-amInRepository (WorkRepoDir d) = do-       setCurrentDirectory d `catchall` fail ("can't set directory to "++d)-       status <- maybeIdentifyRepository YesUseCache "."-       case status of-         GoodRepository _ -> return (Right ())-         BadRepository  e -> return (Left $ "While " ++ d ++ " looks like a repository directory, we have a problem with it:\n" ++ e)-         NonRepository  _ -> return (Left "You need to be in a repository directory to run this command.")-amInRepository _ =-       fromMaybe (Left "You need to be in a repository directory to run this command.") <$> seekRepo--amInHashedRepository :: WorkRepo -> IO (Either String ())-amInHashedRepository wd- = do inrepo <- amInRepository wd-      case inrepo of-       Right _ -> do pristine <- identifyPristine-                     case pristine of-                       HashedPristine -> return (Right ())-                       _ -> return (Left Old.oldRepoFailMsg)-       left    -> return left--repoPatchType :: Repository rt p wR wU wT -> PatchType rt p-repoPatchType _ = PatchType---- | hunt upwards for the darcs repository--- This keeps changing up one parent directory, testing at each--- step if the current directory is a repository or not.  $--- The result is:---   Nothing, if no repository found---   Just (Left errorMessage), if bad repository found---   Just (Right ()), if good repository found.--- WARNING this changes the current directory for good if matchFn succeeds-seekRepo :: IO (Maybe (Either String ()))-seekRepo = getCurrentDirectory >>= helper where-   helper startpwd = do-    status <- maybeIdentifyRepository YesUseCache "."-    case status of-      GoodRepository _ -> return . Just $ Right ()-      BadRepository e  -> return . Just $ Left e-      NonRepository _ ->-            do cd <- toFilePath `fmap` getCurrentDirectory-               setCurrentDirectory ".."-               cd' <- toFilePath `fmap` getCurrentDirectory-               if cd' /= cd-                  then helper startpwd-                  else do setCurrentDirectory startpwd-                          return Nothing---- The performGC in this function is a workaround for a library/GHC bug,--- http://hackage.haskell.org/trac/ghc/ticket/2924 -- (doesn't seem to be a--- problem on fast machines, but virtual ones trip this from time to time)-amNotInRepository :: WorkRepo -> IO (Either String ())-amNotInRepository (WorkRepoDir d) = do-    createDirectoryIfMissing False d-       `catchall` (performGC >> createDirectoryIfMissing False d)-    -- note that the above could always fail-    setCurrentDirectory d-    amNotInRepository WorkRepoCurrentDir-amNotInRepository _ = do-       status <- maybeIdentifyRepository YesUseCache "."-       case status of-         GoodRepository _ -> return (Left "You may not run this command in a repository.")-         BadRepository e  -> return (Left $ "You may not run this command in a repository.\nBy the way, we have a problem with it:\n" ++ e)-         NonRepository _  -> return (Right ())--findRepository :: WorkRepo -> IO (Either String ())-findRepository (WorkRepoPossibleURL d) | isValidLocalPath d =-    do setCurrentDirectory d `catchall` fail ("can't set directory to "++d)-       findRepository WorkRepoCurrentDir-findRepository (WorkRepoDir d) =-    do setCurrentDirectory d `catchall` fail ("can't set directory to "++d)-       findRepository WorkRepoCurrentDir-findRepository _ = fromMaybe (Right ()) <$> seekRepo---- TODO: see also Repository.State.readPendingLL ... to be removed after GHC 7.2-readNewPendingLL :: (RepoPatch p, ApplyState p ~ Tree)-              => Repository rt p wR wU wT -> IO (Sealed ((FL p) wT))-readNewPendingLL repo = mapSeal (mapFL_FL fromPrim) `fmap` readNewPending repo----- | @makeNewPending repo YesUpdateWorking pendPs@ verifies that the---   @pendPs@ could be applied to pristine if we wanted to, and if so---   writes it to disk.  If it can't be applied, @pendPs@ must---   be somehow buggy, so we save it for forensics and crash.-makeNewPending :: forall rt p wR wU wT wY. (RepoPatch p, ApplyState p ~ Tree)-                 => Repository rt p wR wU wT-                 -> UpdateWorking-                 -> FL (PrimOf p) wT wY-                 -> IO ()-makeNewPending _                  NoUpdateWorking _ = return ()-makeNewPending repo@(Repo r _ _ _) YesUpdateWorking origp =-    withCurrentDirectory r $-    do let newname = pendingName ++ ".new"-       debugMessage $ "Writing new pending:  " ++ newname-       Sealed sfp <- return $ siftForPending origp-       writeNewPending repo sfp-       cur <- readRecorded repo-       Sealed p <- readNewPendingLL repo -- :: IO (Sealed (FL (PrimOf p) wT))-       -- We don't ever use the resulting tree.-       _ <- catch (applyToTree p cur) $ \(err :: IOException) -> do-         let buggyname = pendingName ++ "_buggy"-         renameFile newname buggyname-         bugDoc $ text ("There was an attempt to write an invalid pending! " ++ show err)-                    $$ text "If possible, please send the contents of"-                    <+> text buggyname-                    $$ text "along with a bug report."-       renameFile newname pendingName-       debugMessage $ "Finished writing new pending:  " ++ newname---- | @siftForPending ps@ simplifies the candidate pending patch @ps@---   through a combination of looking for self-cancellations---   (sequences of patches followed by their inverses), coalescing,---   and getting rid of any hunk/binary patches we can commute out---   the back------   The visual image of sifting can be quite helpful here.  We are---   repeatedly tapping (shrinking) the patch sequence and---   shaking it (sift). Whatever falls out is the pending we want---   to keep. We do this until the sequence looks about as clean as---   we can get it-siftForPending :: forall prim wX wY . PrimPatch prim => FL prim wX wY -> Sealed (FL prim wX)-siftForPending simple_ps =-    if allFL (\p -> primIsAddfile p || primIsAdddir p) oldps-       then seal oldps-       else fromJust $ do-           Sealed x <- return $ sift NilFL $ reverseFL oldps-           return $ case tryToShrink x of-               ps | lengthFL ps < lengthFL oldps -> siftForPending ps-                  | otherwise -> seal ps-  where-    oldps = fromMaybe simple_ps $ tryShrinkingInverse $ crudeSift simple_ps-    -- get rid of any hunk/binary patches that we can commute out the-    -- back (ie. we work our way backwards, pushing the patches down-    -- to the very end and popping them off; so in (addfile f :> hunk)-    -- we can nuke the hunk, but not so in (hunk :> replace)-    sift :: FL prim wA wB -> RL prim wC wA -> Sealed (FL prim wC)-    sift sofar NilRL = seal sofar-    sift sofar (ps:<:p) | primIsHunk p || primIsBinary p =-        case commuteFLorComplain (p :> sofar) of-            Right (sofar' :> _) -> sift sofar'      ps-            Left _              -> sift (p:>:sofar) ps-    sift sofar (ps:<:p) = sift (p:>:sofar) ps--readTentativeRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                  => Repository rt p wR wU wT-                  -> IO (PatchSet rt p Origin wT)-readTentativeRepo repo@(Repo r rf _ _)-    | formatHas HashedInventory rf = HashedRepo.readTentativeRepo repo r-    | otherwise = fail Old.oldRepoFailMsg--readRepoUsingSpecificInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                               => String-                               -> Repository rt p wR wU wT-                               -> IO (PatchSet rt p Origin wT)-readRepoUsingSpecificInventory invPath repo@(Repo r rf _ _)-    | formatHas HashedInventory rf =-        HashedRepo.readRepoUsingSpecificInventory invPath repo r-    | otherwise = fail Old.oldRepoFailMsg--prefsUrl :: Repository rt p wR wU wT -> String-prefsUrl (Repo r _ _ _) = r ++ "/"++darcsdir++"/prefs"--unrevertUrl :: Repository rt p wR wU wT -> String-unrevertUrl (Repo r _ _ _) = r ++ "/"++darcsdir++"/patches/unrevert"--applyToWorking :: (ApplyState (PrimOf p) ~ Tree, RepoPatch p)-               => Repository rt p wR wU wT -> Verbosity -> FL (PrimOf p) wU wY-               -> IO (Repository rt p wR wY wT)-applyToWorking (Repo r rf t c) verb patch =-  do-    unless (formatHas NoWorkingDir rf) $-      withCurrentDirectory r $ if verb == Quiet-                               then runSilently $ apply patch-                               else runTolerantly $ apply patch-    return (Repo r rf t c)---- | @tentativelyRemoveFromPending p@ is used by Darcs whenever it---   adds a patch to the repository (eg. with apply or record).---   Think of it as one part of transferring patches from pending to---   somewhere else.------   Question (Eric Kow): how do we detect patch equivalence?-tentativelyRemoveFromPending :: forall rt p wR wU wT wX wY. (RepoPatch p)-                 => Repository rt p wR wU wT-                 -> UpdateWorking-                 -> PatchInfoAnd rt p wX wY-                 -> IO ()-tentativelyRemoveFromPending _    NoUpdateWorking  _ = return ()-tentativelyRemoveFromPending repo YesUpdateWorking p = do-    Sealed pend <- readTentativePending repo-    -- Question (Eric Kow): why does pending being all simple matter for-    -- changepref patches in p? isSimple includes changepref, so what do-    -- adddir/etc have to do with it?  Why don't we we systematically-    -- crudeSift/not?-    let effectp = if isSimple pend-                     then crudeSift $ effect p-                     else effect p-    Sealed newpend <- return $ rmpend (progressFL "Removing from pending:" effectp)-                               (unsafeCoercePStart pend)-    writeTentativePending repo (unsafeCoercePStart newpend)-  where-    -- @rmpend effect pending@ removes as much of @effect@ from @pending@-    -- as possible-    ---    -- Note that @effect@ and @pending@ must start from the same context-    -- This is not a bad thing to assume because @effect@ is a patch we want to-    -- add to the repository anyway so it'd kind of have to start from wR anyway-    ---    -- Question (Eric Kow), ok then why not-    -- @PatchInfoAnd p wR wY@ in the type signature above?-    rmpend :: FL (PrimOf p) wA wB -> FL (PrimOf p) wA wC -> Sealed (FL (PrimOf p) wB)-    rmpend NilFL x = Sealed x-    rmpend _ NilFL = Sealed NilFL-    rmpend (x:>:xs) xys | Just ys <- removeFL x xys = rmpend xs ys-    rmpend (x:>:xs) ys =-        case commuteWhatWeCanFL (x:>xs) of-            a:>x':>b -> case rmpend a ys of-                Sealed ys' -> case commute (invert (x':>:b) :> ys') of-                    Just (ys'' :> _) -> seal ys''-                    Nothing          -> seal $ invert (x':>:b)+>+ys'-                    -- DJR: I don't think this last case should be-                    -- reached, but it also shouldn't lead to corruption.---- | A sequence of primitive patches (candidates for the pending patch)---   is considered simple if we can reason about their continued status as---   pending patches solely on the basis of them being hunk/binary patches.------   Simple here seems to mean that all patches are either hunk/binary---   patches, or patches that cannot (indirectly) depend on hunk/binary---   patches.  For now, the only other kinds of patches in this category---   are changepref patches.------   It might be tempting to add, say, adddir patches but it's probably not a---   good idea because Darcs also inverts patches a lot in its reasoning so an---   innocent addir may be inverted to a rmdir which in turn may depend on---   a rmfile, which in turn depends on a hunk/binary. Likewise, we would---   not want to add move patches to this category for similar reasons of---   a potential dependency chain forming.-isSimple :: PrimPatch prim => FL prim wX wY -> Bool-isSimple =-    allFL isSimp-  where-    isSimp x = primIsHunk x || primIsBinary x || primIsSetpref x---- | 'crudeSift' can be seen as a first pass approximation of 'siftForPending'---    that works without having to do any commutation.  It either returns a---    sifted pending (if the input is simple enough for this crude approach)---    or has no effect.-crudeSift :: forall prim wX wY . PrimPatch prim => FL prim wX wY -> FL prim wX wY-crudeSift xs =-    if isSimple xs then filterOutFLFL ishunkbinary xs else xs-  where-    ishunkbinary :: prim wA wB -> EqCheck wA wB-    ishunkbinary x | primIsHunk x || primIsBinary x = unsafeCoerceP IsEq-                   | otherwise = NotEq--data HashedVsOld a = HvsO { old, hashed :: a }--decideHashedOrNormal :: Monad m => RepoFormat -> HashedVsOld (m a) -> m a-decideHashedOrNormal rf (HvsO { hashed = h, old = o })-    | formatHas HashedInventory rf = h-    | otherwise = o--data MakeChanges = MakeChanges | DontMakeChanges deriving ( Eq )--announceMergeConflicts :: (PrimPatch p, PatchInspect p)-                       => String-                       -> AllowConflicts-                       -> ExternalMerge-                       -> FL p wX wY-                       -> IO Bool-announceMergeConflicts cmd allowConflicts externalMerge resolved_pw =-  case nubSort $ listTouchedFiles resolved_pw of-    [] -> return False-    cfs -> if allowConflicts `elem` [YesAllowConflicts,YesAllowConflictsAndMark]-              || externalMerge /= NoExternalMerge-           then do putDocLnWith fancyPrinters $-                     redText "We have conflicts in the following files:" $$ text (unlines cfs)-                   return True-           else do putDocLnWith fancyPrinters $-                     redText "There are conflicts in the following files:" $$ text (unlines cfs)-                   fail $ "Refusing to "++cmd++" patches leading to conflicts.\n"++-                          "If you would rather apply the patch and mark the conflicts,\n"++-                          "use the --mark-conflicts or --allow-conflicts options to "++cmd++"\n"++-                          "These can set as defaults by adding\n"++-                          " "++cmd++" mark-conflicts\n"++-                          "to "++darcsdir++"/prefs/defaults in the target repo. "--checkUnrecordedConflicts :: forall rt p wT wY. RepoPatch p-                         => UpdateWorking-                         -> FL (WrappedNamed rt p) wT wY-                         -> IO Bool-checkUnrecordedConflicts NoUpdateWorking _- = return False -- because we are called by `darcs convert` hence we don't care-checkUnrecordedConflicts _ pc =-    do repository <- identifyRepository NoUseCache "."-       cuc repository-    where cuc :: Repository rt p wR wU wT -> IO Bool-          cuc r = do Sealed (mpend :: FL (PrimOf p) wT wX) <- readPending r :: IO (Sealed (FL (PrimOf p) wT))-                     case mpend of-                       NilFL -> return False-                       pend ->-                           case merge (fromPrims_ pend :\/: fromPrims_ (concatFL $ mapFL_FL effect pc)) of-                           _ :/\: pend' ->-                               case listConflictedFiles pend' of-                               [] -> return False-                               fs -> do putStrLn ("You have conflicting local changes to:\n"-                                                 ++ unwords fs)-                                        confirmed <- promptYorn "Proceed?"-                                        unless confirmed $-                                             do putStrLn "Cancelled."-                                                exitSuccess-                                        return True-          fromPrims_ :: FL (PrimOf p) wA wB -> FL p wA wB-          fromPrims_ = fromPrims--tentativelyAddPatch :: (RepoPatch p, ApplyState p ~ Tree)-                    => Repository rt p wR wU wT-                    -> Compression-                    -> Verbosity-                    -> UpdateWorking-                    -> PatchInfoAnd rt p wT wY-                    -> IO (Repository rt p wR wU wY)-tentativelyAddPatch = tentativelyAddPatch_ UpdatePristine--data UpdatePristine = UpdatePristine -                    | DontUpdatePristine-                    | DontUpdatePristineNorRevert deriving Eq--tentativelyAddPatches_-                     :: forall rt p wR wU wT wY-                      . (RepoPatch p, ApplyState p ~ Tree)-                     => UpdatePristine-                     -> Repository rt p wR wU wT-                     -> Compression-                     -> Verbosity-                     -> UpdateWorking-                     -> FL (PatchInfoAnd rt p) wT wY-                     -> IO (Repository rt p wR wU wY)-tentativelyAddPatches_ _up r _compr _verb _uw NilFL = return r-tentativelyAddPatches_ up r compr verb uw (p:>:ps) = do-    r' <- tentativelyAddPatch_ up r compr verb uw p-    tentativelyAddPatches_ up r' compr verb uw ps---- TODO re-add a safety catch for --dry-run? Maybe using a global, like dryRun--- :: Bool, with dryRun = unsafePerformIO $ readIORef ...-tentativelyAddPatch_ :: forall rt p wR wU wT wY-                      . (RepoPatch p, ApplyState p ~ Tree)-                     => UpdatePristine-                     -> Repository rt p wR wU wT-                     -> Compression-                     -> Verbosity-                     -> UpdateWorking-                     -> PatchInfoAnd rt p wT wY-                     -> IO (Repository rt p wR wU wY)--tentativelyAddPatch_ up r@(Repo dir rf t c) compr verb uw p =-    withCurrentDirectory dir $ do-       decideHashedOrNormal rf HvsO {-          hashed = void $ HashedRepo.addToTentativeInventory c compr p,-          old = fail Old.oldRepoFailMsg}-       when (up == UpdatePristine) $ do debugMessage "Applying to pristine cache..."-                                        applyToTentativePristine r verb p-                                        debugMessage "Updating pending..."-                                        tentativelyRemoveFromPending r uw p-       return (Repo dir rf t c)--applyToTentativePristine :: (ApplyState q ~ Tree, Effect q, Patchy q, ShowPatch q, PrimPatchBase q)-                         => Repository rt p wR wU wT-                         -> Verbosity-                         -> q wT wY-                         -> IO ()-applyToTentativePristine (Repo dir rf _ _) verb p =-    withCurrentDirectory dir $-    do when (verb == Verbose) $ putDocLn $ text "Applying to pristine..." <+> description p-       decideHashedOrNormal rf HvsO {hashed = HashedRepo.applyToTentativePristine p,-                                     old = fail Old.oldRepoFailMsg}---- | @tentativelyAddToPending repo NoDryRun YesUpdateWorking pend ps@---   appends @ps@ to the pending patch.------   It has no effect with @NoUpdateWorking@.------   This fuction is unsafe because it accepts a patch that works on the---   tentative pending and we don't currently track the state of the---   tentative pending.-tentativelyAddToPending :: forall rt p wR wU wT wX wY. RepoPatch p-                        => Repository rt p wR wU wT-                        -> UpdateWorking-                        -> FL (PrimOf p) wX wY-                        -> IO ()-tentativelyAddToPending _                   NoUpdateWorking  _     = return ()-tentativelyAddToPending repo@(Repo dir _ _ _) YesUpdateWorking patch =-    withCurrentDirectory dir $ do-        Sealed pend <- readTentativePending repo-        FlippedSeal newpend_ <- return $-            newpend (unsafeCoerceP pend :: FL (PrimOf p) wA wX) patch-        writeTentativePending repo (unsafeCoercePStart newpend_)-  where-    newpend :: FL prim wA wB -> FL prim wB wC -> FlippedSeal (FL prim) wC-    newpend NilFL patch_ = flipSeal patch_-    newpend p     patch_ = flipSeal $ p +>+ patch_---- | setTentativePending is basically unsafe.  It overwrites the pending---   state with a new one, not related to the repository state.-setTentativePending :: forall rt p wR wU wT wX wY. RepoPatch p-                    => Repository rt p wR wU wT-                    -> UpdateWorking-                    -> FL (PrimOf p) wX wY-                    -> IO ()-setTentativePending _                   NoUpdateWorking  _ = return ()-setTentativePending repo@(Repo dir _ _ _) YesUpdateWorking patch = do-    Sealed prims <- return $ siftForPending patch-    withCurrentDirectory dir $ writeTentativePending repo (unsafeCoercePStart prims)---- | @prepend repo YesUpdateWorking ps@ prepends @ps@ to the pending patch---   It's used right before removing @ps@ from the repo.  This ensures that---   the pending patch can still be applied on top of the recorded state.------   This function is basically unsafe.  It overwrites the pending state---   with a new one, not related to the repository state.-prepend :: forall rt p wR wU wT wX wY. RepoPatch p-        => Repository rt p wR wU wT-        -> UpdateWorking-        -> FL (PrimOf p) wX wY-        -> IO ()-prepend _    NoUpdateWorking  _     = return ()-prepend repo YesUpdateWorking patch = do-    Sealed pend <- readTentativePending repo-    Sealed newpend_ <- return $ newpend (unsafeCoerceP pend) patch-    writeTentativePending repo (unsafeCoercePStart $ crudeSift newpend_)-  where-    newpend :: FL prim wB wC -> FL prim wA wB -> Sealed (FL prim wA)-    newpend NilFL patch_ = seal patch_-    newpend p     patch_ = seal $ patch_ +>+ p--tentativelyRemovePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                         => Repository rt p wR wU wT-                         -> Compression-                         -> UpdateWorking-                         -> FL (PatchInfoAnd rt p) wX wT-                         -> IO (Repository rt p wR wU wX)-tentativelyRemovePatches = tentativelyRemovePatches_ UpdatePristine--tentativelyRemovePatches_ :: forall rt p wR wU wT wX-                           . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                          => UpdatePristine-                          -> Repository rt p wR wU wT-                          -> Compression-                          -> UpdateWorking-                          -> FL (PatchInfoAnd rt p) wX wT-                          -> IO (Repository rt p wR wU wX)-tentativelyRemovePatches_ up repository@(Repo dir rf t c) compr uw ps =-    withCurrentDirectory dir $ do-      when (up == UpdatePristine) $ do debugMessage "Adding changes to pending..."-                                       prepend repository uw $ effect ps-      unless (up == DontUpdatePristineNorRevert) $ removeFromUnrevertContext repository ps-      debugMessage "Removing changes from tentative inventory..."-      if formatHas HashedInventory rf-        then do HashedRepo.removeFromTentativeInventory repository compr ps-                when (up == UpdatePristine) $-                     HashedRepo.applyToTentativePristine $-                     progressFL "Applying inverse to pristine" $ invert ps-        else fail Old.oldRepoFailMsg-      return (Repo dir rf t c)---- FIXME this is a rather weird API. If called with a patch that isn't already--- in the repo, it fails with an obscure error from 'commuteToEnd'. It also--- ends up redoing the work that the caller has already done - if it has--- already commuted these patches to the end, it must also know the commuted--- versions of the other patches in the repo.--- |Given a sequence of patches anchored at the end of the current repository,--- actually pull them to the end of the repository by removing any patches--- with the same name and then adding the passed in sequence.--- Typically callers will have obtained the passed in sequence using--- 'findCommon' and friends.-tentativelyReplacePatches :: forall rt p wR wU wT wX-                           . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                          => Repository rt p wR wU wT-                          -> Compression-                          -> UpdateWorking-                          -> Verbosity-                          -> FL (PatchInfoAnd rt p) wX wT-                          -> IO ()-tentativelyReplacePatches repository compr uw verb ps =-    do let ps' = filterOutFLFL (namedIsInternal . hopefully) ps-       repository' <- tentativelyRemovePatches_ DontUpdatePristineNorRevert repository compr uw ps'-       mapAdd repository' ps'-  where mapAdd :: Repository rt p wM wL wI-               -> FL (PatchInfoAnd rt p) wI wJ-               -> IO ()-        mapAdd _ NilFL = return ()-        mapAdd r (a:>:as) =-               do r' <- tentativelyAddPatch_ DontUpdatePristine r compr verb uw a-                  mapAdd r' as---- | Replace the pending patch with the tentative pending.---   If @NoUpdateWorking@, this merely deletes the tentative pending---   without replacing the current one.------   Question (Eric Kow): shouldn't this also delete the tentative---   pending if @YesUpdateWorking@?  I'm just puzzled by the seeming---   inconsistency of the @NoUpdateWorking@ doing deletion, but---   @YesUpdateWorking@ not bothering.-finalizePending :: (RepoPatch p, ApplyState p ~ Tree)-                => Repository rt p wR wU wT-                -> UpdateWorking-                -> IO ()-finalizePending (Repo dir _ _ _) NoUpdateWorking =-        withCurrentDirectory dir $ removeFileMayNotExist pendingName-finalizePending repository@(Repo dir _ _ _) updateWorking@YesUpdateWorking =-  withCurrentDirectory dir $ do-      Sealed tpend <- readTentativePending repository-      Sealed new_pending <- return $ siftForPending tpend-      makeNewPending repository updateWorking new_pending--finalizeRepositoryChanges :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                          => Repository rt p wR wU wT-                          -> UpdateWorking-                          -> Compression-                          -> IO ()-finalizeRepositoryChanges repository@(Repo dir rf _ _) updateWorking compr-    | formatHas HashedInventory rf =-        withCurrentDirectory dir $ do-            debugMessage "Finalizing changes..."-            withSignalsBlocked $ do-                 HashedRepo.finalizeTentativeChanges repository compr-                 finalizePending repository updateWorking-            debugMessage "Done finalizing changes..."-            doesPatchIndexExist dir >>= (`when` createOrUpdatePatchIndexDisk repository)-            updateIndex repository-    | otherwise = fail Old.oldRepoFailMsg---- TODO: rename this and document the transaction protocol (revert/finalize)--- clearly.--- |Slightly confusingly named: as well as throwing away any tentative--- changes, revertRepositoryChanges also re-initialises the tentative state.--- It's therefore used before makign any changes to the repo.-revertRepositoryChanges :: RepoPatch p-                        => Repository rt p wR wU wT-                        -> UpdateWorking-                        -> IO ()-revertRepositoryChanges r@(Repo dir rf _ _) uw =-    withCurrentDirectory dir $-    do removeFileMayNotExist (pendingName ++ ".tentative")-       Sealed x <- readPending r-       setTentativePending r uw x-       when (uw == NoUpdateWorking) $ removeFileMayNotExist pendingName-       decideHashedOrNormal rf HvsO { hashed = HashedRepo.revertTentativeChanges,-                                      old = Old.revertTentativeChanges }--removeFromUnrevertContext :: forall rt p wR wU wT wX-                           . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                          => Repository rt p wR wU wT-                          -> FL (PatchInfoAnd rt p) wX wT-                          -> IO ()-removeFromUnrevertContext repository ps = do-  Sealed bundle <- unrevert_patch_bundle `catchall` return (seal (PatchSet NilRL NilRL))-  remove_from_unrevert_context_ bundle-  where unrevert_impossible =-            do confirmed <- promptYorn "This operation will make unrevert impossible!\nProceed?"-               if confirmed then removeFileMayNotExist (unrevertUrl repository)-                            else fail "Cancelled."-        unrevert_patch_bundle :: IO (SealedPatchSet rt p Origin)-        unrevert_patch_bundle = do pf <- B.readFile (unrevertUrl repository)-                                   case scanBundle pf of-                                     Right foo -> return foo-                                     Left err -> fail $ "Couldn't parse unrevert patch:\n" ++ err-        remove_from_unrevert_context_ :: PatchSet rt p Origin wZ -> IO ()-        remove_from_unrevert_context_ (PatchSet NilRL NilRL) = return ()-        remove_from_unrevert_context_ bundle =-         do debugMessage "Adjusting the context of the unrevert changes..."-            debugMessage $ "Removing "++ show (lengthFL ps) ++-                                  " patches in removeFromUnrevertContext!"-            ref <- readTentativeRepo repository-            let withSinglet :: Sealed (FL ppp wXxx)-                            -> (forall wYyy . ppp wXxx wYyy -> IO ()) -> IO ()-                withSinglet (Sealed (x :>: NilFL)) j = j x-                withSinglet _ _ = return ()-            withSinglet (mergeThem ref bundle) $ \h_us ->-                  case commuteRL (reverseFL ps :> h_us) of-                    Nothing -> unrevert_impossible-                    Just (us' :> _) ->-                      case removeFromPatchSet ps ref of-                      Nothing -> unrevert_impossible-                      Just common ->-                          do debugMessage "Have now found the new context..."-                             bundle' <- makeBundleN Nothing common (hopefully us':>:NilFL)-                             writeDocBinFile (unrevertUrl repository) bundle'-            debugMessage "Done adjusting the context of the unrevert changes!"--cleanRepository :: RepoPatch p => Repository rt p wR wU wT -> IO ()-cleanRepository repository@(Repo _ rf _ _) =-    decideHashedOrNormal rf-    HvsO { hashed = cleanHashedRepo repository,-           old = fail Old.oldRepoFailMsg}-           where-            cleanHashedRepo r = do-              HashedRepo.cleanPristine r-              HashedRepo.cleanInventories r-              HashedRepo.cleanPatches r----- | grab the pristine hash of _darcs/hash_inventory, and retrieve whole pristine tree,---   possibly writing a clean working copy in the process.-createPristineDirectoryTree :: RepoPatch p => Repository rt p wR wU wT -> FilePath -> WithWorkingDir -> IO ()-createPristineDirectoryTree (Repo r rf _ c) reldir wwd-    | formatHas HashedInventory rf =-        do createDirectoryIfMissing True reldir-           withCurrentDirectory reldir $ HashedRepo.copyPristine c r (darcsdir++"/hashed_inventory") wwd-    | otherwise = fail Old.oldRepoFailMsg---- fp below really should be FileName--- | Used by the commands dist and diff-createPartialsPristineDirectoryTree :: (FilePathLike fp, RepoPatch p)-                                    => Repository rt p wR wU wT-                                    -> [fp]-                                    -> FilePath-                                    -> IO ()-createPartialsPristineDirectoryTree (Repo r rf _ c) prefs dir-    | formatHas HashedInventory rf =-        do createDirectoryIfMissing True dir-           withCurrentDirectory dir $-               HashedRepo.copyPartialsPristine c r (darcsdir++"/hashed_inventory") prefs-    | otherwise = fail Old.oldRepoFailMsg--withRecorded :: RepoPatch p-             => Repository rt p wR wU wT-             -> ((AbsolutePath -> IO a) -> IO a)-             -> (AbsolutePath -> IO a)-             -> IO a-withRecorded repository mk_dir f-    = mk_dir $ \d -> do createPristineDirectoryTree repository (toFilePath d) WithWorkingDir-                        f d--withTentative :: forall rt p a wR wU wT. (RepoPatch p, ApplyState p ~ Tree)-              => Repository rt p wR wU wT-              -> ((AbsolutePath -> IO a) -> IO a)-              -> (AbsolutePath -> IO a)-              -> IO a-withTentative (Repo dir rf _ c) mk_dir f-    | formatHas HashedInventory rf =-        mk_dir $ \d -> do HashedRepo.copyPristine-                              c-                              dir-                              (darcsdir++"/tentative_pristine")-                              WithWorkingDir-                          f d-withTentative repository@(Repo dir _ _ _) mk_dir f =-    withRecorded repository mk_dir $ \d ->-    do Sealed ps <- read_patches (dir ++ "/"++darcsdir++"/tentative_pristine")-       runDefault $ apply ps-       f d-    where read_patches :: FilePath -> IO (Sealed (FL p wX))-          read_patches fil = do ps <- B.readFile fil-                                return $ fromMaybe (seal NilFL) $ readPatch ps---- | Sets scripts in or below the current directory executable.---   A script is any file that starts with the bytes '#!'.---   This is used for --set-scripts-executable.-setScriptsExecutable_ :: PatchInspect p => Maybe (p wX wY) -> IO ()-setScriptsExecutable_ pw = do-    debugMessage "Making scripts executable"-    tree <- readWorking-    paths <- case pw of-          Just ps -> filterM doesFileExist $ listTouchedFiles ps-          Nothing -> return [ anchorPath "." p | (p, Tree.File _) <- Tree.list tree ]-    let setExecutableIfScript f =-              do contents <- B.readFile f-                 when (BC.pack "#!" `B.isPrefixOf` contents) $ do-                   debugMessage ("Making executable: " ++ f)-                   setExecutable f True-    mapM_ setExecutableIfScript paths--setScriptsExecutable :: IO ()-setScriptsExecutable = setScriptsExecutable_ (Nothing :: Maybe (FL DummyPatch wX wY))--setScriptsExecutablePatches :: PatchInspect p => p wX wY -> IO ()-setScriptsExecutablePatches = setScriptsExecutable_ . Just----- | Writes out a fresh copy of the inventory that minimizes the--- amount of inventory that need be downloaded when people pull from--- the repository.------ Specifically, it breaks up the inventory on the most recent tag.--- This speeds up most commands when run remotely, both because a--- smaller file needs to be transfered (only the most recent--- inventory).  It also gives a guarantee that all the patches prior--- to a given tag are included in that tag, so less commutation and--- history traversal is needed.  This latter issue can become very--- important in large repositories.-reorderInventory :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                 => Repository rt p wR wU wR-                 -> Compression-                 -> UpdateWorking-                 -> Verbosity-                 -> IO ()-reorderInventory repository@(Repo _ rf _ _) compr uw verb =-    decideHashedOrNormal rf HvsO {-    hashed = do-        debugMessage "Reordering the inventory."-        PatchSet _ ps <- misplacedPatches `fmap` readRepo repository-        tentativelyReplacePatches repository compr uw verb $ reverseRL ps-        HashedRepo.finalizeTentativeChanges repository compr-        debugMessage "Done reordering the inventory.",-    old = fail Old.oldRepoFailMsg }---- | Returns the patches that make the most recent tag dirty.-misplacedPatches :: forall rt p wS wX . RepoPatch p-                 => PatchSet rt p wS wX-                 -> PatchSet rt p wS wX-misplacedPatches ps = -        -- Filter the repository keeping only with the tags, ordered from the-        -- most recent.-        case filter isTag $ mapRL info $ newset2RL ps of-                [] -> ps-                (lt:_) -> -                    -- Take the most recent tag, and split the repository in,-                    -- the clean PatchSet "up to" the tag (ts), and a RL of-                    -- patches after the tag (r).-                    case splitOnTag lt ps of-                        Just (PatchSet ts xs :> r) -> PatchSet ts (xs+<+r)-                        _ -> impossible -- Because the tag is in ps.---- @todo: we should not have to open the result of HashedRepo and--- seal it.  Instead, update this function to work with type witnesses--- by fixing DarcsRepo to match HashedRepo in the handling of--- Repository state.-readRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-         => Repository rt p wR wU wT-         -> IO (PatchSet rt p Origin wR)-readRepo repo@(Repo r rf _ _)-    | formatHas HashedInventory rf = HashedRepo.readRepo repo r-    | otherwise = do Sealed ps <- Old.readOldRepo r-                     return $ unsafeCoerceP ps---- | XOR of all hashes of the patches' metadata.--- It enables to quickly see whether two repositories--- have the same patches, independently of their order.--- It relies on the assumption that the same patch cannot--- be present twice in a repository.--- This checksum is not cryptographically secure,--- see http://robotics.stanford.edu/~xb/crypto06b/ .-repoXor :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-        => Repository rt p wR wU wR -> IO SHA1-repoXor repo = do-  hashes <- mapRL (makePatchname . info) . newset2RL <$> readRepo repo-  return $ foldl' sha1Xor zero hashes
src/Darcs/Repository/InternalTypes.hs view
@@ -14,22 +14,31 @@ -- along with this program; if not, write to the Free Software Foundation, -- Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -{-# LANGUAGE CPP #-}---module Darcs.Repository.InternalTypes ( Repository(..), Pristine(..)-                                      , extractCache, modifyCache+module Darcs.Repository.InternalTypes ( Repository, PristineType(..)+                                      , repoCache, modifyCache+                                      , repoPatchType+                                      , repoFormat+                                      , repoLocation+                                      , withRepoLocation+                                      , repoPristineType+                                      , coerceR+                                      , coerceU+                                      , coerceT+                                      , mkRepo                                       ) where  import Prelude () import Darcs.Prelude +import Data.Coerce ( coerce ) import Data.List ( nub, sortBy ) import Darcs.Repository.Cache ( Cache (..) , compareByLocality ) import Darcs.Repository.Format ( RepoFormat )-import Darcs.Patch ( RepoPatch, RepoType )+import Darcs.Patch ( RepoType )+import Darcs.Patch.Type ( PatchType(..) )+import Darcs.Util.File ( withCurrentDirectory ) -data Pristine+data PristineType   = NoPristine   | PlainPristine   | HashedPristine@@ -42,14 +51,41 @@ -- and the tentative state, which represents work in progress that will -- eventually become the new recorded state unless something goes wrong. data Repository (rt :: RepoType) (p :: * -> * -> *) wRecordedstate wUnrecordedstate wTentativestate =-  Repo !String !RepoFormat !Pristine Cache deriving ( Show )+  Repo !String !RepoFormat !PristineType Cache deriving ( Show ) -extractCache :: Repository rt p wR wU wT -> Cache-extractCache (Repo _ _ _ c) = c+repoLocation :: Repository rt p wR wU wT -> String+repoLocation (Repo loc _ _ _) = loc +withRepoLocation :: Repository rt p wR wU wT -> IO a -> IO a+withRepoLocation repo = withCurrentDirectory (repoLocation repo)++repoFormat :: Repository rt p wR wU wT -> RepoFormat+repoFormat (Repo _ fmt _ _) = fmt++repoPristineType :: Repository rt p wR wU wT -> PristineType+repoPristineType (Repo _ _ pr _) = pr++repoCache :: Repository rt p wR wU wT -> Cache+repoCache (Repo _ _ _ c) = c+ -- | 'modifyCache' @repository function@ modifies the cache of --   @repository@ with @function@, remove duplicates and sort the results with 'compareByLocality'.-modifyCache :: forall rt p wR wU wT . (RepoPatch p)  => Repository rt p wR wU wT -> (Cache -> Cache) -> Repository rt p wR wU wT+modifyCache :: forall rt p wR wU wT . Repository rt p wR wU wT -> (Cache -> Cache) -> Repository rt p wR wU wT modifyCache (Repo dir rf pristine cache) f    = Repo dir rf pristine $ cmap ( sortBy compareByLocality . nub ) $ f cache   where cmap g (Ca c) = Ca (g c)++repoPatchType :: Repository rt p wR wU wT -> PatchType rt p+repoPatchType _ = PatchType++coerceR :: Repository rt p wR wU wT -> Repository rt p wR' wU wT+coerceR = coerce++coerceU :: Repository rt p wR wU wT -> Repository rt p wR wU' wT+coerceU = coerce++coerceT :: Repository rt p wR wU wT -> Repository rt p wR wU wT'+coerceT = coerce++mkRepo :: String -> RepoFormat -> PristineType -> Cache -> Repository rt p wR wU wT+mkRepo = Repo
+ src/Darcs/Repository/Inventory.hs view
@@ -0,0 +1,239 @@+module Darcs.Repository.Inventory+    ( Inventory(..)+    , HeadInventory+    , InventoryEntry+    , ValidHash(..)+    , InventoryHash+    , PatchHash+    , PristineHash+    , inventoryPatchNames+    , parseInventory+    , showInventory+    , showInventoryPatches+    , showInventoryEntry+    , emptyInventory+    , pokePristineHash+    , peekPristineHash+    , skipPristineHash+    , pristineName+    -- properties+    , prop_inventoryParseShow+    , prop_peekPokePristineHash+    , prop_skipPokePristineHash+    ) where++import Prelude ()+import Darcs.Prelude hiding ( take )++import Control.Applicative ( optional, many )+import Control.Monad ( guard )++import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC++import Darcs.Patch.Info ( PatchInfo, showPatchInfo, readPatchInfo )+import Darcs.Patch.ReadMonads+    ( ParserM, parseStrictly, string, skipSpace, take, takeTillChar )+import Darcs.Patch.Show ( ShowPatchFor(..) )+import Darcs.Repository.Cache ( okayHash )+import Darcs.Util.Hash ( sha256sum )+import Darcs.Util.Printer+    ( Doc, (<>), (<+>), ($$), hcat, text, invisiblePS, packedString, renderPS )++-- * Hash validation++-- TODO the ValidHash class and the newtypes for the various hashes+-- really don't belong here. They should be moved to D.R.Cache or+-- perhaps a separate module. Also, the validation should be extended+-- see D.R.Cache.checkHash.++class ValidHash a where+  getValidHash :: a -> String+  mkValidHash :: String -> a++newtype InventoryHash = InventoryHash String+  deriving (Eq, Show)++instance ValidHash InventoryHash where+  getValidHash (InventoryHash h) = h+  mkValidHash s+    | okayHash s = InventoryHash s+    | otherwise = error "Bad inventory hash!"++newtype PatchHash = PatchHash String+  deriving (Eq, Show)++instance ValidHash PatchHash where+  getValidHash (PatchHash h) = h+  mkValidHash s+    | okayHash s = PatchHash s+    | otherwise = error "Bad patch hash!"++newtype PristineHash = PristineHash String+  deriving (Eq, Show)++instance ValidHash PristineHash where+  getValidHash (PristineHash h) = h+  mkValidHash s+    | okayHash s = PristineHash s+    | otherwise = error "Bad pristine hash!"++-- * Inventories++-- Note: this type and the commented out parser combinators for it+-- aren't actually used (except for testing). They are left here to+-- serve as documentation for the API we would like to use but won't+-- because of efficiency: we want to be able to access the pristine+-- hash with forcing a complete parse of the head inventory. Thus we+-- retain the lower-level peek/poke/skip API for the pristine hash.+type HeadInventory = (PristineHash, Inventory)++data Inventory = Inventory+  { inventoryParent :: Maybe InventoryHash+  , inventoryPatches :: [InventoryEntry]+  } deriving (Eq, Show)++-- The 'String' is the (hashed) patch filename.+type InventoryEntry = (PatchInfo, PatchHash)++inventoryPatchNames :: Inventory -> [String]+inventoryPatchNames = map (getValidHash . snd) . inventoryPatches++emptyInventory :: Inventory+emptyInventory = Inventory Nothing []++-- * Parsing++{-+parseHeadInventory :: B.ByteString -> Maybe HeadInventory+parseHeadInventory = fmap fst . parse pHeadInv+-}++parseInventory :: B.ByteString -> Maybe Inventory+parseInventory = fmap fst . parseStrictly pInv++{-+pHeadInv :: ParserM m => m HeadInventory+pHeadInv = (,) <$> pInvPristine <*> pInv++pInvPristine :: ParserM m => m ValidHash+pInvPristine = do+  string pristineName+  skipSpace+  pHash+-}++pInv :: ParserM m => m Inventory+pInv = Inventory <$> pInvParent <*> pInvPatches++pInvParent :: ParserM m => m (Maybe InventoryHash)+pInvParent = optional $ do+  string parentName+  skipSpace+  pHash++pHash :: (ParserM m, ValidHash h) => m h+pHash = do+  hash <- BC.unpack <$> pLine+  guard (okayHash hash)+  return (mkValidHash hash)++pLine :: ParserM m => m B.ByteString+pLine = takeTillChar '\n' <* take 1++pInvPatches :: ParserM m => m [InventoryEntry]+pInvPatches = many pInvEntry++pInvEntry :: ParserM m => m InventoryEntry+pInvEntry = do+  info <- readPatchInfo+  skipSpace+  string hashName+  skipSpace+  hash <- pHash+  return (info, hash)++-- * Showing++showInventory :: Inventory -> Doc+showInventory inv =+  showParent (inventoryParent inv) <>+  showInventoryPatches (inventoryPatches inv)++showInventoryPatches :: [InventoryEntry] -> Doc+showInventoryPatches = hcat . map showInventoryEntry++showInventoryEntry :: InventoryEntry -> Doc+showInventoryEntry (pinf, hash) =+  showPatchInfo ForStorage pinf $$+  packedString hashName <+> text (getValidHash hash) <> packedString newline++showParent :: Maybe InventoryHash -> Doc+showParent (Just (InventoryHash hash)) =+  packedString parentName $$ text hash <> packedString newline+showParent Nothing = mempty++-- * Accessing the pristine hash++-- | Replace the pristine hash at the start of a raw, unparsed 'HeadInventory'+-- or add it if none is present.+pokePristineHash :: String -> B.ByteString -> Doc+pokePristineHash h inv =+  invisiblePS pristineName <> text h $$ invisiblePS (skipPristineHash inv)++takeHash :: B.ByteString -> Maybe (String, B.ByteString)+takeHash input = do+  let (hline,rest) = BC.breakSubstring newline input+  let hash = BC.unpack hline+  guard $ okayHash hash+  return (hash, rest)++peekPristineHash :: B.ByteString -> String+peekPristineHash inv =+  case tryDropPristineName inv of+    Just rest ->+      case takeHash rest of+        Just (h, _) -> h+        Nothing -> error $ "Bad hash in inventory!"+    Nothing -> sha256sum B.empty++-- |skipPristineHash drops the 'pristine: HASH' prefix line, if present.+skipPristineHash :: B.ByteString -> B.ByteString+skipPristineHash ps =+  case tryDropPristineName ps of+    Just rest -> B.drop 1 $ BC.dropWhile (/= '\n') rest+    Nothing -> ps++tryDropPristineName :: B.ByteString -> Maybe B.ByteString+tryDropPristineName input =+    if prefix == pristineName then Just rest else Nothing+  where+    (prefix, rest) = B.splitAt (B.length pristineName) input++-- * Key phrases++pristineName :: B.ByteString+pristineName = BC.pack "pristine:"++parentName :: B.ByteString+parentName = BC.pack "Starting with inventory:"++hashName :: B.ByteString+hashName = BC.pack "hash:"++newline :: B.ByteString+newline = BC.pack "\n"++-- * Properties++prop_inventoryParseShow :: Inventory -> Bool+prop_inventoryParseShow inv =+  Just inv == parseInventory (renderPS (showInventory inv))++prop_peekPokePristineHash :: (PristineHash, B.ByteString) -> Bool+prop_peekPokePristineHash (PristineHash hash, raw) =+  hash == peekPristineHash (renderPS (pokePristineHash hash raw))++prop_skipPokePristineHash :: (PristineHash, B.ByteString) -> Bool+prop_skipPokePristineHash (PristineHash hash, raw) =+  raw == skipPristineHash (renderPS (pokePristineHash hash raw))
src/Darcs/Repository/Job.hs view
@@ -16,15 +16,18 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, ScopedTypeVariables, Rank2Types, RankNTypes #-} {-# LANGUAGE ForeignFunctionInterface #-}  module Darcs.Repository.Job     ( RepoJob(..)+    , IsPrimV1(..)     , withRepoLock+    , withOldRepoLock     , withRepoLockCanFail     , withRepository-    , withRepositoryDirectory+    , withRepositoryLocation+    , checkRepoIsNoRebase+    , withUMaskFlag     ) where  import Prelude ()@@ -35,12 +38,15 @@ import Darcs.Patch.Apply ( ApplyState ) import Darcs.Patch.V1 ( RepoPatchV1 ) import Darcs.Patch.V2 ( RepoPatchV2 )-import Darcs.Patch.Prim.V1 ( Prim )+import qualified Darcs.Patch.V1.Prim as V1 ( Prim(..) )+import qualified Darcs.Patch.V2.Prim as V2 ( Prim(..) ) import Darcs.Patch.Prim ( PrimOf )+import Darcs.Patch.Prim.V1 ( Prim ) import Darcs.Patch.RepoPatch ( RepoPatch ) import Darcs.Patch.RepoType   ( RepoType(..), SRepoType(..), IsRepoType   , RebaseType(..), SRebaseType(..), IsRebaseType+  , singletonRepoType   )  import Darcs.Repository.Flags@@ -49,15 +55,18 @@ import Darcs.Repository.Format     ( RepoProperty( Darcs2                   , RebaseInProgress+                  , HashedInventory                   )     , formatHas     , writeProblem     )-import Darcs.Repository.Internal-    ( identifyRepository-    , revertRepositoryChanges+import Darcs.Repository.Identify ( identifyRepository )+import Darcs.Repository.Hashed( revertRepositoryChanges )+import Darcs.Repository.InternalTypes+    ( Repository+    , repoFormat+    , repoLocation     )-import Darcs.Repository.InternalTypes ( Repository(..) ) import Darcs.Repository.Rebase     ( RebaseJobFlags     , startRebaseJob@@ -70,6 +79,7 @@  import Control.Monad ( when ) import Control.Exception ( bracket_, finally )+import Data.Coerce ( coerce ) import Data.List ( intercalate )  import Foreign.C.String ( CString, withCString )@@ -78,8 +88,6 @@  import Darcs.Util.Tree ( Tree ) -#include "impossible.h"- getUMask :: UMask -> Maybe String getUMask (YesUMask s) = Just s getUMask NoUMask = Nothing@@ -114,23 +122,23 @@     =     -- |The most common @RepoJob@; the underlying action can accept any patch type that     -- a darcs repository may use.-      RepoJob (forall rt p wR wU . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+      RepoJob (forall rt p wR wU . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)                => Repository rt p wR wU wR -> IO a)     -- |A job that only works on darcs 1 patches-    | V1Job (forall wR wU . Repository ('RepoType 'NoRebase) (RepoPatchV1 Prim) wR wU wR -> IO a)+    | V1Job (forall wR wU . Repository ('RepoType 'NoRebase) (RepoPatchV1 V1.Prim) wR wU wR -> IO a)     -- |A job that only works on darcs 2 patches-    | V2Job (forall rt wR wU . Repository rt (RepoPatchV2 Prim) wR wU wR -> IO a)+    | V2Job (forall rt wR wU . IsRepoType rt => Repository rt (RepoPatchV2 V2.Prim) wR wU wR -> IO a)     -- |A job that works on any repository where the patch type @p@ has 'PrimOf' @p@ = 'Prim'.     --     -- This was added to support darcsden, which inspects the internals of V1 prim patches.     --     -- In future this should be replaced with a more abstract inspection API as part of 'PrimPatch'.-    | PrimV1Job (forall rt p wR wU . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, PrimOf p ~ Prim)+    | PrimV1Job (forall rt p wR wU . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, IsPrimV1 (PrimOf p))                => Repository rt p wR wU wR -> IO a)     -- A job that works on normal darcs repositories, but will want access to the rebase patch if it exists.-    | RebaseAwareJob RebaseJobFlags (forall rt p wR wU . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository rt p wR wU wR -> IO a)-    | RebaseJob RebaseJobFlags (forall p wR wU . (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository ('RepoType 'IsRebase) p wR wU wR -> IO a)-    | StartRebaseJob RebaseJobFlags (forall p wR wU . (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => Repository ('RepoType 'IsRebase) p wR wU wR -> IO a)+    | RebaseAwareJob RebaseJobFlags (forall rt p wR wU . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wR -> IO a)+    | RebaseJob RebaseJobFlags (forall p wR wU . (RepoPatch p, ApplyState p ~ Tree) => Repository ('RepoType 'IsRebase) p wR wU wR -> IO a)+    | StartRebaseJob RebaseJobFlags (forall p wR wU . (RepoPatch p, ApplyState p ~ Tree) => Repository ('RepoType 'IsRebase) p wR wU wR -> IO a)  onRepoJob :: RepoJob a           -> (forall rt p wR wU . (RepoPatch p, ApplyState p ~ Tree) => (Repository rt p wR wU wR -> IO a) -> Repository rt p wR wU wR -> IO a)@@ -145,38 +153,46 @@  -- | apply a given RepoJob to a repository in the current working directory withRepository :: UseCache -> RepoJob a -> IO a-withRepository useCache = withRepositoryDirectory useCache "."+withRepository useCache = withRepositoryLocation useCache "."  -- | This is just an internal type to Darcs.Repository.Job for -- calling runJob in a strongly-typed way data RepoPatchType p where-  RepoV1 :: RepoPatchType (RepoPatchV1 Prim)-  RepoV2 :: RepoPatchType (RepoPatchV2 Prim)+  RepoV1 :: RepoPatchType (RepoPatchV1 V1.Prim)+  RepoV2 :: RepoPatchType (RepoPatchV2 V2.Prim)  -- | This type allows us to check multiple patch types against the -- constraints required by most repository jobs data IsTree p where-  IsTree :: (ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree) => IsTree p+  IsTree :: (ApplyState p ~ Tree) => IsTree p  checkTree :: RepoPatchType p -> IsTree p checkTree RepoV1 = IsTree checkTree RepoV2 = IsTree +class ApplyState p ~ Tree => IsPrimV1 p where+  toPrimV1 :: p wX wY -> Prim wX wY+instance IsPrimV1 V1.Prim where+  toPrimV1 = V1.unPrim+instance IsPrimV1 V2.Prim where+  toPrimV1 = V2.unPrim+ -- | This type allows us to check multiple patch types against the -- constraints required by 'PrimV1Job' data UsesPrimV1 p where-  UsesPrimV1 :: (ApplyState p ~ Tree, PrimOf p ~ Prim) => UsesPrimV1 p+  UsesPrimV1 :: (ApplyState p ~ Tree, IsPrimV1 (PrimOf p)) => UsesPrimV1 p  checkPrimV1 :: RepoPatchType p -> UsesPrimV1 p checkPrimV1 RepoV1 = UsesPrimV1 checkPrimV1 RepoV2 = UsesPrimV1  -- | apply a given RepoJob to a repository in a given url-withRepositoryDirectory :: UseCache -> String -> RepoJob a -> IO a-withRepositoryDirectory useCache url repojob = do-    repo@(Repo _ rf _ _) <- identifyRepository useCache url+withRepositoryLocation :: UseCache -> String -> RepoJob a -> IO a+withRepositoryLocation useCache url repojob = do+    repo <- identifyRepository useCache url      let+        rf = repoFormat repo         startRebase =             case repojob of                 StartRebaseJob {} -> True@@ -204,13 +220,17 @@ runJob   :: forall rt p rtDummy pDummy wR wU a    . (IsRepoType rt, RepoPatch p)-  => RepoPatchType p -> SRepoType rt -> Repository rtDummy pDummy wR wU wR -> RepoJob a -> IO a-runJob patchType (SRepoType isRebase) (Repo dir rf t c) repojob = do+  => RepoPatchType p+  -> SRepoType rt+  -> Repository rtDummy pDummy wR wU wR+  -> RepoJob a+  -> IO a+runJob patchType (SRepoType isRebase) repo repojob = do    -- The actual type the repository should have is only known when   -- when this function is called, so we need to "cast" it to its proper type   let-    therepo = Repo dir rf t c :: Repository rt p wR wU wR+    therepo = coerce repo :: Repository rt p wR wU wR      patchTypeString :: String     patchTypeString =@@ -230,7 +250,8 @@         [] -> ""         _ -> " " ++ intercalate "+" repoAttributes -  debugMessage $ "Identified " ++ patchTypeString ++ repoAttributesString ++ " repo: " ++ dir+  debugMessage $ "Identified " ++ patchTypeString ++ repoAttributesString +++                 " repo: " ++ repoLocation repo    case repojob of     RepoJob job ->@@ -284,24 +305,47 @@ --   taking a lock withRepoLock :: DryRun -> UseCache -> UpdateWorking -> UMask -> RepoJob a -> IO a withRepoLock dry useCache uw um repojob =-    withRepository useCache $ onRepoJob repojob $ \job repository@(Repo _ rf _ _) ->-    do maybe (return ()) fail $ writeProblem rf+    withRepository useCache $ onRepoJob repojob $ \job repository ->+    do maybe (return ()) fail $ writeProblem (repoFormat repository)        let name = "./"++darcsdir++"/lock"        withUMaskFlag um $          if dry == YesDryRun            then job repository            else withLock name (revertRepositoryChanges repository uw >> job repository) --- | apply a given RepoJob to a repository in the current working directory,---   taking a lock. If lock not takeable, do nothing.-withRepoLockCanFail :: UseCache -> UpdateWorking -> UMask -> RepoJob () -> IO ()-withRepoLockCanFail useCache uw um repojob =-    withRepository useCache $ onRepoJob repojob $ \job repository@(Repo _ rf _ _) ->-    do maybe (return ()) fail $ writeProblem rf+-- | run a lock-taking job in an old-fashion repository.+--   only used by `darcs optimize upgrade`.+withOldRepoLock :: RepoJob a -> IO a+withOldRepoLock repojob =+    withRepository NoUseCache $ onRepoJob repojob $ \job repository ->+    do let name = "./"++darcsdir++"/lock"+       withLock name $ job repository++-- | Apply a given RepoJob to a repository in the current working directory,+-- taking a lock. If lock not takeable, do nothing. If old-fashioned+-- repository, do nothing. The job must not touch pending or pending.tentative,+-- because there is no call to revertRepositoryChanges. This entry point is+-- currently only used for attemptCreatePatchIndex.+withRepoLockCanFail :: UseCache -> RepoJob () -> IO ()+withRepoLockCanFail useCache repojob =+    withRepository useCache $ onRepoJob repojob $ \job repository ->+    let rf = repoFormat repository in+    if formatHas HashedInventory rf then do+       maybe (return ()) fail $ writeProblem rf        let name = "./"++darcsdir++"/lock"-       withUMaskFlag um $ do-         eitherDone <- withLockCanFail name (revertRepositoryChanges repository uw >> job repository)-         case eitherDone of-           Left  _ -> debugMessage "Lock could not be obtained, not doing the job."-           Right _ -> return ()+       eitherDone <- withLockCanFail name (job repository)+       case eitherDone of+         Left  _ -> debugMessage "Lock could not be obtained, not doing the job."+         Right _ -> return ()+      else debugMessage "Not doing the job because this is an old-fashioned repository." +-- | If the 'RepoType' of the given repo indicates that we have 'NoRebase',+-- then 'Just' the repo with the refined type, else 'Nothing'.+-- NB The amount of types we have to import to make this simple check is ridiculous!+checkRepoIsNoRebase :: forall rt p wR wU wT. IsRepoType rt+                    => Repository rt p wR wU wT+                    -> Maybe (Repository ('RepoType 'NoRebase) p wR wU wT)+checkRepoIsNoRebase repo =+  case singletonRepoType :: SRepoType rt of+    SRepoType SNoRebase -> Just repo+    SRepoType SIsRebase -> Nothing
src/Darcs/Repository/Match.hs view
@@ -15,12 +15,9 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, ScopedTypeVariables, MultiParamTypeClasses, FlexibleInstances, Rank2Types #-}- module Darcs.Repository.Match     (       getNonrangeMatch-    , getFirstMatch     , getOnePatchset     ) where @@ -29,7 +26,6 @@  import Darcs.Patch.Match     ( getNonrangeMatchS-    , getFirstMatchS     , nonrangeMatcherIsTag     , getMatchingTag     , matchAPatchset@@ -49,15 +45,14 @@ import Darcs.Repository.Flags     ( WithWorkingDir (WithWorkingDir) ) import Darcs.Repository.ApplyPatches ( DefaultIO, runDefault )-import Darcs.Repository.Internal-    ( Repository, readRepo, createPristineDirectoryTree )+import Darcs.Repository.InternalTypes ( Repository )+import Darcs.Repository.Hashed+    ( readRepo, createPristineDirectoryTree )  import Darcs.Util.Tree ( Tree )  import Darcs.Util.Path ( toFilePath ) -#include "impossible.h"- getNonrangeMatch :: (ApplyMonad (ApplyState p) DefaultIO, IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)                  => Repository rt p wR wU wT                  -> [MatchFlag]@@ -68,13 +63,7 @@                 | otherwise -> fail "Index range is not allowed for this command."     _ -> getNonrangeMatchS fs -getFirstMatch :: (ApplyMonad (ApplyState p) DefaultIO, IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-              => Repository rt p wR wU wT-              -> [MatchFlag]-              -> IO ()-getFirstMatch r fs = withRecordedMatch r (getFirstMatchS fs)--getOnePatchset :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+getOnePatchset :: (IsRepoType rt, RepoPatch p)                => Repository rt p wR wU wT                -> [MatchFlag]                -> IO (SealedPatchSet rt p Origin)@@ -89,7 +78,7 @@           context_f (Context f:_) = f           context_f (_:xs) = context_f xs -withRecordedMatch :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+withRecordedMatch :: (IsRepoType rt, RepoPatch p)                   => Repository rt p wR wU wT                   -> (PatchSet rt p Origin wR -> DefaultIO ())                   -> IO ()
src/Darcs/Repository/Merge.hs view
@@ -21,15 +21,34 @@ module Darcs.Repository.Merge     ( tentativelyMergePatches     , considerMergeToWorking+    , announceMergeConflicts     ) where  import Prelude () import Darcs.Prelude -import Control.Monad ( when )-import Darcs.Util.Tree( Tree )+import Control.Monad ( when, unless )+import Data.List.Ordered ( nubSort )+import System.Exit ( exitSuccess ) +import Darcs.Util.Tree( Tree ) import Darcs.Util.External ( backupByCopying )++import Darcs.Patch+    ( RepoPatch, IsRepoType, PrimOf, merge, listTouchedFiles+    , fromPrims, effect, WrappedNamed+    , listConflictedFiles )+import Darcs.Patch.Prim ( PrimPatch )+import Darcs.Patch.Apply ( ApplyState )+import Darcs.Patch.Depends( merge2FL )+import Darcs.Patch.Named.Wrapped ( activecontents, anonymous, namedIsInternal )+import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, n2pia, hopefully )+import Darcs.Patch.Progress( progressFL )+import Darcs.Patch.Witnesses.Ordered+    ( FL(..), (:\/:)(..), (:/\:)(..), (+>+),+    mapFL_FL, concatFL, filterOutFLFL )+import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed), seal )+ import Darcs.Repository.Flags     ( UseIndex     , ScanKnown@@ -41,32 +60,31 @@     , Compression (..)     , WantGuiPause (..)     , DiffAlgorithm (..)+    , UseCache(..)+    , LookForMoves(..)+    , LookForReplaces(..)     )-import Darcs.Patch ( RepoPatch, IsRepoType, PrimOf, merge, listTouchedFiles,-                     fromPrims, effect )-import Darcs.Patch.Apply ( ApplyState )-import Darcs.Patch.Depends( merge2FL )-import Darcs.Patch.Named.Wrapped ( activecontents, anonymous )-import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, n2pia, hopefully )-import Darcs.Patch.Progress( progressFL )-import Darcs.Patch.Witnesses.Ordered-    ( FL(..), (:\/:)(..), (:/\:)(..), (+>+),-    mapFL_FL, concatFL )-import Darcs.Patch.Witnesses.Sealed( Sealed(Sealed), seal )-import Darcs.Patch.Witnesses.Unsafe ( unsafeCoercePEnd )-import Darcs.Repository.InternalTypes( Repository(..) )-import Darcs.Repository.State( unrecordedChanges, readUnrecorded )+import Darcs.Repository.Hashed+    ( tentativelyAddPatches_+    , applyToTentativePristine+    , tentativelyRemovePatches_+    , UpdatePristine(..) )+import Darcs.Repository.Identify ( identifyRepository )+import Darcs.Repository.InternalTypes ( Repository )+import Darcs.Repository.Pending ( setTentativePending, readPending ) import Darcs.Repository.Resolution ( standardResolution, externalResolution )-import Darcs.Repository.Internal ( announceMergeConflicts,-                                   checkUnrecordedConflicts, MakeChanges(..),-                                   setTentativePending, tentativelyAddPatch_,-                                   applyToTentativePristine,-                                   tentativelyReplacePatches,-                                   UpdatePristine(..) )+import Darcs.Repository.State ( unrecordedChanges, readUnrecorded )++import Darcs.Util.Prompt ( promptYorn )+import Darcs.Util.Global ( darcsdir ) import Darcs.Util.Progress( debugMessage )+import Darcs.Util.Printer.Color (fancyPrinters)+import Darcs.Util.Printer ( text, ($$), redText, putDocLnWith, ($$) ) +data MakeChanges = MakeChanges | DontMakeChanges deriving ( Eq )+ tentativelyMergePatches_ :: forall rt p wR wU wT wY wX-                          . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+                          . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)                          => MakeChanges                          -> Repository rt p wR wU wT -> String                          -> AllowConflicts -> UpdateWorking@@ -76,16 +94,14 @@                          -> FL (PatchInfoAnd rt p) wX wT                          -> FL (PatchInfoAnd rt p) wX wY                          -> IO (Sealed (FL (PrimOf p) wU))-tentativelyMergePatches_ mc r cmd allowConflicts updateWorking externalMerge wantGuiPause-  compression verbosity reorder diffingOpts@(_, _, dflag) usi themi = do-    let us = mapFL_FL hopefully usi-        them = mapFL_FL hopefully themi-    ((pc :: FL (PatchInfoAnd rt p) wT wMerged) :/\: us_merged)-         <- return $ merge2FL (progressFL "Merging us" usi)-                              (progressFL "Merging them" themi)-    pend <- unrecordedChanges diffingOpts r Nothing+tentativelyMergePatches_ mc r cmd allowConflicts updateWorking externalMerge+  wantGuiPause compression verbosity reorder diffingOpts@(_, _, dflag) us them = do+    (them_merged :/\: us_merged)+         <- return $ merge2FL (progressFL "Merging us" us)+                              (progressFL "Merging them" them)+    pend <- unrecordedChanges diffingOpts NoLookForMoves NoLookForReplaces r Nothing     anonpend <- n2pia `fmap` anonymous (fromPrims pend)-    pend' :/\: pw <- return $ merge (pc :\/: anonpend :>: NilFL)+    pend' :/\: pw <- return $ merge (them_merged :\/: anonpend :>: NilFL)     let pwprim = concatFL $ progressFL "Examining patches for conflicts" $                                 mapFL_FL (activecontents . hopefully) pw     Sealed standard_resolved_pw <- return $ standardResolution pwprim@@ -93,10 +109,11 @@     when (allowConflicts == YesAllowConflictsAndMark) $         mapM_ backupByCopying $ listTouchedFiles standard_resolved_pw     debugMessage "Announcing conflicts..."-    have_conflicts <- announceMergeConflicts cmd allowConflicts externalMerge standard_resolved_pw+    have_conflicts <-+        announceMergeConflicts cmd allowConflicts externalMerge standard_resolved_pw     debugMessage "Checking for unrecorded conflicts..."     have_unrecorded_conflicts <- checkUnrecordedConflicts updateWorking $-                                     mapFL_FL hopefully pc+                                     mapFL_FL hopefully them_merged     debugMessage "Reading working directory..."     working <- readUnrecorded r Nothing     debugMessage "Working out conflicts in actual working directory..."@@ -111,47 +128,31 @@                                              (effect us +>+ pend) (effect them) pwprim     debugMessage "Applying patches to the local directories..."     when (mc == MakeChanges) $ do-        let doChanges :: FL (PatchInfoAnd rt p) wX wT -> IO (Repository rt p wR wU wMerged)-            -- This first case is a possible optimisation: if 'usi' is empty, then-            -- the merge2FL call above will return pc = themi, but the wMerged-            -- witness is quantified in the :/\: constructor so we lose the-            -- information that wX=wT => wMerged=wY so we have to coerce.-            -- TODO: it's not really clear why if this is an optimisation in-            -- practice, as pc would be trivial to calculate in this case and-            -- there aren't any obvious memory benefits.-            doChanges NilFL = applyps r (unsafeCoercePEnd themi)-            doChanges _     = applyps r pc-        r' <- doChanges usi+        -- these two cases result in the same trees (that's the idea of+        -- merging), so we only operate on the set of patches and do the+        -- adaption of pristine and pending in the common code below+        r' <- case reorder of+            NoReorder -> do+                tentativelyAddPatches_ DontUpdatePristine r+                    compression verbosity updateWorking them_merged+            Reorder -> do+                -- we do not actually remove any effect in the end, so+                -- it would be wrong to update the unrevert bundle or+                -- the working tree or pending+                r1 <- tentativelyRemovePatches_ DontUpdatePristineNorRevert r+                          compression NoUpdateWorking+                          (filterOutFLFL (namedIsInternal . hopefully) us)+                r2 <- tentativelyAddPatches_ DontUpdatePristine r1+                          compression verbosity NoUpdateWorking them+                tentativelyAddPatches_ DontUpdatePristine r2+                    compression verbosity NoUpdateWorking+                    (filterOutFLFL (namedIsInternal . hopefully) us_merged)+        -- must use the original r, not the updated one here:+        applyToTentativePristine r verbosity them_merged         setTentativePending r' updateWorking (effect pend' +>+ pw_resolution)-        when (reorder == Reorder) $-            -- TODO: we end up applying the merged remote patches on top of the unmerged-            -- local patches, then commuting out the unmerged local patches and finally-            -- adding the merged local patches.-            -- It would better to just remove the unmerged local patche, then apply the-            -- unmerged remote patches and then the merged local patches.-            -- The handling of 'unrecorded' might complicate this slightly so this-            -- refactoring may be better deferred until we have reliable witness tracking-            -- for repositories.-            tentativelyReplacePatches r' compression YesUpdateWorking verbosity us_merged     return $ seal (effect pwprim +>+ pw_resolution)-  where-    mapAdd :: Repository rt p wM wL wI -> FL (PatchInfoAnd rt p) wI wJ-           -> IO (Repository rt p wM wL wJ)-    mapAdd repo NilFL = return repo-    mapAdd repo (a:>:as) = do-        repo' <- tentativelyAddPatch_ DontUpdatePristine repo-                     compression verbosity updateWorking a-        mapAdd repo' as-    applyps :: Repository rt p wM wL wI -> FL (PatchInfoAnd rt p) wI wJ-            -> IO (Repository rt p wM wL wJ)-    applyps repo ps = do-        debugMessage "Adding patches to inventory..."-        repo' <- mapAdd repo ps-        debugMessage "Applying patches to pristine..."-        applyToTentativePristine repo verbosity ps-        return repo' -tentativelyMergePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+tentativelyMergePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)                         => Repository rt p wR wU wT -> String                         -> AllowConflicts -> UpdateWorking                         -> ExternalMerge -> WantGuiPause@@ -163,7 +164,7 @@ tentativelyMergePatches = tentativelyMergePatches_ MakeChanges  -considerMergeToWorking :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+considerMergeToWorking :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)                        => Repository rt p wR wU wT -> String                        -> AllowConflicts -> UpdateWorking                        -> ExternalMerge -> WantGuiPause@@ -173,4 +174,57 @@                        -> FL (PatchInfoAnd rt p) wX wY                        -> IO (Sealed (FL (PrimOf p) wU)) considerMergeToWorking = tentativelyMergePatches_ DontMakeChanges+++announceMergeConflicts :: (PrimPatch p)+                       => String+                       -> AllowConflicts+                       -> ExternalMerge+                       -> FL p wX wY+                       -> IO Bool+announceMergeConflicts cmd allowConflicts externalMerge resolved_pw =+  case nubSort $ listTouchedFiles resolved_pw of+    [] -> return False+    cfs -> if allowConflicts `elem` [YesAllowConflicts,YesAllowConflictsAndMark]+              || externalMerge /= NoExternalMerge+           then do putDocLnWith fancyPrinters $+                     redText "We have conflicts in the following files:" $$ text (unlines cfs)+                   return True+           else do putDocLnWith fancyPrinters $+                     redText "There are conflicts in the following files:" $$ text (unlines cfs)+                   fail $ "Refusing to "++cmd++" patches leading to conflicts.\n"+++                          "If you would rather apply the patch and mark the conflicts,\n"+++                          "use the --mark-conflicts or --allow-conflicts options to "++cmd++"\n"+++                          "These can set as defaults by adding\n"+++                          " "++cmd++" mark-conflicts\n"+++                          "to "++darcsdir++"/prefs/defaults in the target repo. "++checkUnrecordedConflicts :: forall rt p wT wY. RepoPatch p+                         => UpdateWorking+                         -> FL (WrappedNamed rt p) wT wY+                         -> IO Bool+checkUnrecordedConflicts NoUpdateWorking _+ = return False -- because we are called by `darcs convert` hence we don't care+checkUnrecordedConflicts _ pc =+    do repository <- identifyRepository NoUseCache "."+       cuc repository+    where cuc :: Repository rt p wR wU wT -> IO Bool+          cuc r = do Sealed (mpend :: FL (PrimOf p) wT wX) <- readPending r :: IO (Sealed (FL (PrimOf p) wT))+                     case mpend of+                       NilFL -> return False+                       pend ->+                           case merge (fromPrims_ pend :\/: fromPrims_ (concatFL $ mapFL_FL effect pc)) of+                           _ :/\: pend' ->+                               case listConflictedFiles pend' of+                               [] -> return False+                               fs -> do putStrLn ("You have conflicting local changes to:\n"+                                                 ++ unwords fs)+                                        confirmed <- promptYorn "Proceed?"+                                        unless confirmed $+                                             do putStrLn "Cancelled."+                                                exitSuccess+                                        return True+          fromPrims_ :: FL (PrimOf p) wA wB -> FL p wA wB+          fromPrims_ = fromPrims+ 
− src/Darcs/Repository/Motd.hs
@@ -1,46 +0,0 @@---  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.--module Darcs.Repository.Motd-    ( getMotd-    , showMotd-    ) where--import Prelude ()-import Darcs.Prelude--import Control.Monad ( unless )-import qualified Data.ByteString as B (null, hPut, empty, ByteString)-import System.IO ( stdout )--import Darcs.Util.External ( fetchFilePS, Cachable(..) )-import Darcs.Util.Global ( darcsdir )-import Darcs.Util.Exception ( catchall )---- | Fetch and return the message of the day for a given repository.-getMotd :: String -> IO B.ByteString-getMotd repo = fetchFilePS motdPath (MaxAge 600) `catchall` return B.empty-  where-    motdPath = repo ++ "/" ++ darcsdir ++ "/prefs/motd"---- | Display the message of the day for a given repository,-showMotd :: String -> IO ()-showMotd repo = do-    motd <- getMotd repo-    unless (B.null motd) $ do-        B.hPut stdout motd-        putStrLn $ replicate 22 '*'
src/Darcs/Repository/Old.hs view
@@ -15,11 +15,8 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, ScopedTypeVariables #-}-- module Darcs.Repository.Old ( readOldRepo,-                              revertTentativeChanges, oldRepoFailMsg ) where+                              oldRepoFailMsg ) where  import Prelude () import Darcs.Prelude@@ -33,62 +30,61 @@                          patchInfoAndPatch,                          actually, unavailable ) -import qualified Data.ByteString.Char8 as BC (break, pack)+import qualified Data.ByteString as B ( ByteString, null )+import qualified Data.ByteString.Char8 as BC ( break, pack, unpack )  import Darcs.Patch ( RepoPatch, IsRepoType, WrappedNamed,                      readPatch )-+import Darcs.Patch.ReadMonads as RM ( parseStrictly ) import Darcs.Patch.Witnesses.Ordered ( RL(..) ) import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed), seal, unseal, mapSeal )-import Darcs.Patch.Info ( PatchInfo, makeFilename, readPatchInfos, showPatchInfo )+import Darcs.Patch.Info ( PatchInfo(..), makePatchname, readPatchInfo, displayPatchInfo ) import Darcs.Patch.Set ( PatchSet(..), Tagged(..), SealedPatchSet, Origin ) import Darcs.Util.External     ( gzFetchFilePS     , Cachable(..)-    , cloneFile     )-import Darcs.Util.Lock ( writeBinFile )-import Darcs.Util.Printer ( renderString, RenderMode(..) )+import Darcs.Util.Printer ( renderString ) import Darcs.Util.Global ( darcsdir )+import Darcs.Util.Hash ( sha1PS )+import Darcs.Util.IsoDate ( readUTCDateOldFashioned, showIsoDateTime )  import Control.Exception ( catch, IOException ) -#include "impossible.h"- readOldRepo :: (IsRepoType rt, RepoPatch p) => String -> IO (SealedPatchSet rt p Origin)-readOldRepo d = do-  realdir <- toPath `fmap` ioAbsoluteOrRemote d-  let k = "Reading inventory of repository "++d-  beginTedious k-  readRepoPrivate k realdir "inventory" `catch`+readOldRepo repo_dir = do+  realdir <- toPath `fmap` ioAbsoluteOrRemote repo_dir+  let task = "Reading inventory of repository "++repo_dir+  beginTedious task+  readRepoPrivate task realdir "inventory" `catch`                         (\e -> do hPutStrLn stderr ("Invalid repository:  " ++ realdir)                                   ioError e)  readRepoPrivate :: (IsRepoType rt, RepoPatch p)                 => String -> FilePath -> FilePath -> IO (SealedPatchSet rt p Origin)-readRepoPrivate k d iname = do-    i <- gzFetchFilePS (d </> darcsdir </> iname) Uncachable-    finishedOneIO k iname-    let parse inf = parse2 inf $ d </> darcsdir </> "patches" </> makeFilename inf-        (mt, is) = case BC.break ('\n' ==) i of+readRepoPrivate task repo_dir inventory_name = do+    inventory <- gzFetchFilePS (repo_dir </> darcsdir </> inventory_name) Uncachable+    finishedOneIO task inventory_name+    let parse inf = parse2 inf $ repo_dir </> darcsdir </> "patches" </> makeFilename inf+        (mt, is) = case BC.break ('\n' ==) inventory of                    (swt,pistr) | swt == BC.pack "Starting with tag:" ->                                      case readPatchInfos pistr of                                      (t:ids) -> (Just t,reverse ids)                                      [] -> bug "bad inventory in readRepoPrivate"-                   _ -> (Nothing, reverse $ readPatchInfos i)+                   _ -> (Nothing, reverse $ readPatchInfos inventory)     Sealed ts <- unseal seal `fmap` unsafeInterleaveIO (read_ts parse mt)     Sealed ps <- unseal seal `fmap` unsafeInterleaveIO (read_patches parse is)     return $ seal (PatchSet ts ps)     where read_ts :: RepoPatch p =>                      (forall wB . PatchInfo -> IO (Sealed (PatchInfoAnd rt p wB)))                   -> Maybe PatchInfo -> IO (Sealed (RL (Tagged rt p) Origin))-          read_ts _ Nothing = do endTedious k+          read_ts _ Nothing = do endTedious task                                  return $ seal NilRL           read_ts parse (Just tag0) =-              do debugMessage $ "Looking for inventory for:\n"++ renderString Encode (showPatchInfo tag0)+              do debugMessage $ "Looking for inventory for:\n"++ renderString (displayPatchInfo tag0)                  i <- unsafeInterleaveIO $-                      do x <- gzFetchFilePS (d </> darcsdir </> "inventories" </> makeFilename tag0) Uncachable-                         finishedOneIO k (renderString Encode (showPatchInfo tag0))+                      do x <- gzFetchFilePS (repo_dir </> darcsdir </> "inventories" </> makeFilename tag0) Uncachable+                         finishedOneIO task (renderString (displayPatchInfo tag0))                          return x                  let (mt, is) = case BC.break ('\n' ==) i of                                 (swt,pistr) | swt == BC.pack "Starting with tag:" ->@@ -128,12 +124,30 @@                                      Sealed y <- unseal seal `fmap` unsafeInterleaveIO ioy                                      return $ seal $ f y x --revertTentativeChanges :: IO ()-revertTentativeChanges =-    do cloneFile (darcsdir++"/inventory") (darcsdir++"/tentative_inventory")-       writeBinFile (darcsdir++"/tentative_pristine") ""- oldRepoFailMsg :: String oldRepoFailMsg = "ERROR: repository upgrade required, try `darcs optimize upgrade`\n"               ++ "See http://wiki.darcs.net/OF for more details."++-- | This makes darcs-1 (non-hashed repos) filenames.+--+-- The name consists of three segments:+--+--  * timestamp (ISO8601-compatible yyyymmmddHHMMSS;+--    note that the old-fashioned (non-hashed) format expects this date to+--    be exactly as in the patch, /ignoring/ any timezone info,+--    which is why we use 'readUTCDateOldFashioned' here)+--+--  * SHA1 hash of the author+--+--  * SHA1 hash of the patch name, author, date, log, and \"inverted\"+--    flag.+makeFilename :: PatchInfo -> String+makeFilename pi = showIsoDateTime d++"-"++sha1_a++"-"++ (show $ makePatchname pi) ++ ".gz"+    where d = readUTCDateOldFashioned $ BC.unpack $ _piDate pi+          sha1_a = take 5 $ show $ sha1PS $ _piAuthor pi++readPatchInfos :: B.ByteString -> [PatchInfo]+readPatchInfos inv | B.null inv = []+readPatchInfos inv = case parseStrictly readPatchInfo inv of+                     Just (pinfo,r) -> pinfo : readPatchInfos r+                     _ -> []
src/Darcs/Repository/Packs.hs view
@@ -1,26 +1,50 @@+{-|+License : GPL-2++Packs are an optimization that enable faster repository cloning over HTTP.+A pack is actually a @tar.gz@ file that contains many files that would otherwise+have to be transfered one by one (which is much slower over HTTP).++Two packs are created at the same time by 'createPacks':++  1. The basic pack, contains the latest recorded version of the working tree.+  2. The patches pack, contains the set of patches of the repository.++The paths of these files are @_darcs\/packs\/basic.tar.gz@ and+@_darcs\/packs\/patches.tar.gz@. There is also @_darcs\/packs\/pristine@ which+indicates the pristine hash at the moment of the creation of the packs. This+last file is useful to determine whether the basic pack is in sync with the+current pristine of the repository.+-}+ module Darcs.Repository.Packs     ( fetchAndUnpackBasic     , fetchAndUnpackPatches     , packsDir+    , createPacks     ) where  import qualified Codec.Archive.Tar as Tar+import Codec.Archive.Tar.Entry ( fileEntry, toTarPath ) import Codec.Compression.GZip as GZ ( compress, decompress )- import Control.Concurrent.Async ( withAsync )-import Control.Exception ( Exception, IOException, throwIO, catch )-import Control.Monad ( void )+import Control.Exception ( Exception, IOException, throwIO, catch, finally )+import Control.Monad ( void, when, unless ) import System.IO.Error ( isAlreadyExistsError )+import System.IO.Unsafe ( unsafeInterleaveIO ) -import qualified Data.ByteString.Lazy.Char8 as BL-import Data.List ( isPrefixOf )+import qualified Data.ByteString.Lazy.Char8 as BLC+import Data.List ( isPrefixOf, sort ) import Data.Maybe( catMaybes, listToMaybe )  import System.Directory ( createDirectoryIfMissing                         , renameFile+                        , removeFile                         , doesFileExist+                        , getModificationTime                         ) import System.FilePath ( (</>)+                       , (<.>)                        , takeFileName                        , splitPath                        , joinPath@@ -28,8 +52,22 @@                        ) import System.Posix.Files ( createLink ) +import Darcs.Util.ByteString ( gzReadFilePS ) import Darcs.Util.Lock ( withTemp ) import Darcs.Util.External ( Cachable(..), fetchFileLazyPS )+import Darcs.Util.Global ( darcsdir )+import Darcs.Util.Progress ( debugMessage )++import Darcs.Patch ( IsRepoType, RepoPatch )+import Darcs.Patch.PatchInfoAnd ( extractHash )+import Darcs.Patch.Witnesses.Ordered ( mapFL )+import Darcs.Patch.Set ( patchSet2FL )++import Darcs.Repository.InternalTypes ( Repository )+import qualified Darcs.Repository.Hashed as HashedRepo+import Darcs.Repository.Hashed ( filterDirContents, readRepo, readHashedPristineRoot )+import Darcs.Repository.Format+    ( identifyRepoFormat, formatHas, RepoProperty ( HashedInventory ) ) import Darcs.Repository.Cache ( fetchFileUsingCache                               , HashedDir(..)                               , Cache(..)@@ -39,12 +77,12 @@                               , bucketFolder                               , CacheType(Directory)                               )--import Darcs.Util.Global ( darcsdir )-import Darcs.Util.Progress ( debugMessage )+import Darcs.Repository.Old ( oldRepoFailMsg ) -packsDir :: String-packsDir = "packs"+packsDir, basicPack, patchesPack :: String+packsDir     = "packs"+basicPack    = "basic.tar.gz"+patchesPack  = "patches.tar.gz"  fetchAndUnpack :: FilePath                -> HashedDir@@ -60,11 +98,11 @@   -- Patches pack can miss some new patches of the repository.   -- So we download pack asynchonously and alway do a complete pass   -- of individual patch files.-  withAsync (fetchAndUnpack "patches.tar.gz" HashedInventoriesDir cache remote) $ \_ -> do+  withAsync (fetchAndUnpack patchesPack HashedInventoriesDir cache remote) $ \_ -> do   fetchFilesUsingCache cache HashedPatchesDir paths  fetchAndUnpackBasic :: Cache -> FilePath -> IO ()-fetchAndUnpackBasic = fetchAndUnpack "basic.tar.gz" HashedPristineDir+fetchAndUnpackBasic = fetchAndUnpack basicPack HashedPristineDir  unpackTar :: Exception e => Cache -> HashedDir -> Tar.Entries e -> IO () unpackTar _ _   Tar.Done = return ()@@ -87,7 +125,7 @@   _ -> fail "Unexpected non-file tar entry"  where   writeFile' Nothing path content = withTemp $ \tmp -> do-    BL.writeFile tmp content+    BLC.writeFile tmp content     renameFile tmp path   writeFile' (Just ca) path content = do     let fileFullPath = case splitPath path of@@ -115,3 +153,58 @@ cacheDir (Ca cs) = listToMaybe . catMaybes .flip map cs $ \x -> case x of   Cache Directory Writable x' -> Just x'   _ -> Nothing++-- | Create packs from the current recorded version of the repository.+createPacks :: (IsRepoType rt, RepoPatch p)+            => Repository rt p wR wU wT -> IO ()+createPacks repo = flip finally (mapM_ removeFileIfExists+  [ darcsdir </> "meta-filelist-inventories"+  , darcsdir </> "meta-filelist-pristine"+  , basicTar <.> "part"+  , patchesTar <.> "part"+  ]) $ do+  rf <- identifyRepoFormat "."+  -- function is exposed in API so could be called on non-hashed repo+  unless (formatHas HashedInventory rf) $ fail oldRepoFailMsg+  createDirectoryIfMissing False (darcsdir </> packsDir)+  -- pristine hash+  Just hash <- readHashedPristineRoot repo+  writeFile ( darcsdir </> packsDir </> "pristine" ) hash+  -- pack patchesTar+  ps <- mapFL hashedPatchFileName . patchSet2FL <$> readRepo repo+  is <- map ((darcsdir </> "inventories") </>) <$> HashedRepo.listInventories+  writeFile (darcsdir </> "meta-filelist-inventories") . unlines $+    map takeFileName is+  -- Note: tinkering with zlib's compression parameters does not make+  -- any noticeable difference in generated archive size;+  -- switching to bzip2 would provide ~25% gain OTOH.+  BLC.writeFile (patchesTar <.> "part") . GZ.compress . Tar.write =<<+    mapM fileEntry' ((darcsdir </> "meta-filelist-inventories") : ps +++    reverse is)+  renameFile (patchesTar <.> "part") patchesTar+  -- pack basicTar+  pr <- sortByMTime =<< dirContents "pristine.hashed"+  writeFile (darcsdir </> "meta-filelist-pristine") . unlines $+    map takeFileName pr+  BLC.writeFile (basicTar <.> "part") . GZ.compress . Tar.write =<< mapM fileEntry' (+    [ darcsdir </> "meta-filelist-pristine"+    , darcsdir </> "hashed_inventory"+    ] ++ reverse pr)+  renameFile (basicTar <.> "part") basicTar+ where+  basicTar = darcsdir </> packsDir </> basicPack+  patchesTar = darcsdir </> packsDir </> patchesPack+  fileEntry' x = unsafeInterleaveIO $ do+    content <- BLC.fromChunks . return <$> gzReadFilePS x+    tp <- either fail return $ toTarPath False x+    return $ fileEntry tp content+  dirContents d = map ((darcsdir </> d) </>) <$>+    filterDirContents d (const True)+  hashedPatchFileName x = case extractHash x of+    Left _ -> fail "unexpected unhashed patch"+    Right h -> darcsdir </> "patches" </> h+  sortByMTime xs = map snd . sort <$> mapM (\x -> (\t -> (t, x)) <$>+    getModificationTime x) xs+  removeFileIfExists x = do+    ex <- doesFileExist x+    when ex $ removeFile x
src/Darcs/Repository/PatchIndex.hs view
@@ -1,41 +1,42 @@-{-# LANGUAGE CPP, NamedFieldPuns #-}+{-# LANGUAGE NamedFieldPuns #-} --- Copyright (C) 2009-2010 Benedikt Schmidt------ 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.+{-|+License : GPL-2 +The patch-index stores additional information that is extracted from+the PatchSet for the repository to speed up certain commands (namely+@log@ and @annotate@). More precisely, for every file tracked by the+repository, it stores the list of patches that touch it.++When created, patch-index lives in @_darcs\/patch_index\/@, and it+should be automatically maintained each time the set of patches of+the repository is updated.++Patch-index can also be explicitely disabled by creating a file+@_darcs\/no_patch_index@. "Explicitely disabed" means that no command+should attempt to automatically create the patch-index.++See <http://darcs.net/Internals/PatchIndex> for more information.+-} module Darcs.Repository.PatchIndex (   doesPatchIndexExist,   isPatchIndexDisabled,   isPatchIndexInSync,   canUsePatchIndex,-  canCreatePI,   createPIWithInterrupt,   createOrUpdatePatchIndexDisk,   deletePatchIndex,-  dumpPatchIndex,-  filterPatches,+  attemptCreatePatchIndex,   PatchFilter,   maybeFilterPatches,   getRelevantSubsequence,-  piTest,-  attemptCreatePatchIndex+  dumpPatchIndex,+  piTest ) where -import Prelude hiding ( pi, (<$>) )+import Prelude ()+import Darcs.Prelude+ import Data.Binary ( encodeFile, decodeFile ) import Data.Word ( Word32 ) import Data.Int ( Int8 )@@ -51,44 +52,28 @@ import Control.Applicative ( (<$>) ) import System.Directory ( createDirectory, renameDirectory, doesFileExist, doesDirectoryExist ) import Darcs.Repository.Format ( formatHas, RepoProperty( HashedInventory ) )-import Darcs.Repository.InternalTypes ( Repository(..) )-import Darcs.Repository.HashedRepo ( readRepo )+import Darcs.Repository.InternalTypes ( Repository, repoLocation, repoFormat ) import Darcs.Patch.Witnesses.Ordered ( mapFL, RL(..), FL(..), reverseRL ) import Darcs.Patch.Witnesses.Sealed ( Sealed2(..), Sealed(..), seal, seal2, unsafeUnseal ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd(..), info ) import Darcs.Util.Lock ( withPermDir, rmRecursive )-import Darcs.Patch ( RepoPatch, IsRepoType, listTouchedFiles )+import Darcs.Patch ( RepoPatch, listTouchedFiles ) import Darcs.Util.Path ( FileName, fp2fn, fn2fp, toFilePath )-import Darcs.Patch.Apply ( applyToFileMods, ApplyState(..) )-import Darcs.Patch.Set ( newset2FL, Origin, newset2FL )-import Darcs.Patch.Patchy ( Commute )+import Darcs.Patch.Apply ( ApplyState(..) )+import Darcs.Patch.Set ( PatchSet(..), patchSet2FL, Origin, patchSet2FL ) import Darcs.Patch.Inspect ( PatchInspect ) import Darcs.Util.Global ( darcsdir ) import Darcs.Util.Progress ( debugMessage ) import Darcs.Patch.Index.Types+import Darcs.Patch.Index.Monad ( applyToFileMods, makePatchID ) import System.FilePath( (</>) ) import System.IO (openFile, IOMode(WriteMode), hClose) import qualified Data.ByteString as B-import Darcs.Util.Crypt.SHA256 (sha256sum )-import Darcs.Util.Crypt.SHA1 ( SHA1(..), showAsHex )+import Darcs.Util.Hash ( sha256sum, showAsHex ) import Darcs.Util.Tree ( Tree(..) ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP ) import Darcs.Util.SignalHandler ( catchInterrupt )-#include "impossible.h" -{- ------------------------------------------------------------------------------   The patch index stores additional information that is extracted from-   the PatchSet for the repository to speed up certain commands.--  createPatchIndexDisk:-     Create the on-disk patch-index index from scratch.-   updatePatchIndexDisk:-     Update the on-disk patch-index index.-  ----------------------------------------------------------------------------- -}---- ------------------------------------------------------------------------ Data structures for the patch-index- data FileIdSpan = FidSpan                     !FileId           -- the fileid has some fixed name in the                     !PatchId          -- span starting here@@ -128,26 +113,13 @@         infom::InfoMap     } --- | an empty patch-index-emptyPatchIndex :: PatchIndex-emptyPatchIndex = PatchIndex [] M.empty M.empty M.empty- -- | On-disk version of patch index --   version 1 is the one introduced in darcs 2.10 --           2 changes the pids order to newer-to-older version :: Int8 version = 2 --- ------------------------------------------------------------------------ Query the patch-index--getInventoryHash :: FilePath -> IO String-getInventoryHash repodir = do-  inv <- B.readFile (repodir </> darcsdir </> "hashed_inventory")-  return $ sha256sum inv---- ------------------------------------------------------------------------ create patch-index+type PIM a = State PatchIndex a  -- | 'applyPatchMods pmods pindex' applies a list of PatchMods to the given --   patch index pindex@@ -155,12 +127,12 @@ applyPatchMods pmods pindex =   flip execState pindex $ mapM_ goList pmods  where goList :: (PatchId, [PatchMod FileName]) -> PIM ()-       -- nubSeq handles invalid patch in darcs repo:-       --   move with identical target name "rename darcs_patcher to darcs-patcher."        goList (pid, mods) = do            modify (\pind -> pind{pids = pid:pids pind})            mapM_ (curry go pid) (nubSeq mods)-+       -- nubSeq handles invalid patch in darcs repo:+       --   move with identical target name "rename darcs_patcher to darcs-patcher."+       nubSeq = map head . group        go :: (PatchId, PatchMod FileName) -> PIM ()        go (pid, PCreateFile fn) = do          fid <- createFidStartSpan fn pid@@ -196,11 +168,6 @@            Just [] -> error $ "applyPatchMods: impossible, no entry for "++show fn                               ++" in FileIdSpans in duplicate, empty list" --- ------------------------------------------------------------------------ Update and query patch index--type PIM a = State PatchIndex a- -- | create new filespan for created file createFidStartSpan :: FileName -> PatchId -> PIM FileId createFidStartSpan fn pstart = do@@ -309,24 +276,18 @@                   Nothing -> error "lookupFids' : could not find file"               else return [] --- | remove sequential duplicates-nubSeq :: Eq a => [a] -> [a]-nubSeq = map head . group---- ------------------------------------------------------------------------ Create/Update patch-index on disk---- | create patch index that corresponds to all patches in repo+-- | Creates patch index that corresponds to all patches in repo. createPatchIndexDisk-  :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-  => Repository rt p wR wU wT -> IO ()-createPatchIndexDisk repository@(Repo r _ _ _) = do-  rawpatches <- newset2FL `fmap` readRepo repository r-  let patches = mapFL Sealed2 rawpatches+  :: (RepoPatch p, ApplyState p ~ Tree)+  => Repository rt p wR wU wT+  -> PatchSet rt p Origin wR+  -> IO ()+createPatchIndexDisk repository ps = do+  let patches = mapFL Sealed2 $ patchSet2FL ps   createPatchIndexFrom repository $ patches2patchMods patches S.empty  -- | convert patches to patchmods-patches2patchMods :: (Apply p, Commute p, PatchInspect p, ApplyState p ~ Tree)+patches2patchMods :: (Apply p, PatchInspect p, ApplyState p ~ Tree)                   => [Sealed2 (PatchInfoAnd rt p)] -> Set FileName -> [(PatchId, [PatchMod FileName])] patches2patchMods patches fns = snd $ mapAccumL go fns patches   where@@ -387,20 +348,22 @@  -- | update the patch index to the current state of the repository updatePatchIndexDisk-    :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-    => Repository rt p wR wU wT -> IO ()-updatePatchIndexDisk repo@(Repo repodir _ _ _) = do+    :: (RepoPatch p, ApplyState p ~ Tree)+    => Repository rt p wR wU wT+    -> PatchSet rt p Origin wR+    -> IO ()+updatePatchIndexDisk repo patches = do+    let repodir = repoLocation repo     (_,_,pid2idx,pindex) <- loadPatchIndex repodir     -- check that patch index is up to date-    patches <- newset2FL `fmap` readRepo repo repodir-    let pidsrepo = mapFL (makePatchID . info) patches+    let flpatches = patchSet2FL patches+    let pidsrepo = mapFL (makePatchID . info) flpatches         (oldpids,_,len_common) = uncommon (reverse $ pids pindex) pidsrepo         pindex' = removePidSuffix pid2idx oldpids pindex         filenames = fpSpans2fileNames (fpspans pindex')         cdir = repodir </> indexDir     -- reread to prevent holding onto patches for too long-    rawpatches <- newset2FL `fmap` readRepo repo repodir-    let newpatches = drop len_common $ mapFL seal2 rawpatches+    let newpatches = drop len_common $ mapFL seal2 flpatches         newpmods = patches2patchMods newpatches filenames     inv_hash <- getInventoryHash repodir     storePatchIndex repodir cdir inv_hash (applyPatchMods newpmods pindex')@@ -414,18 +377,21 @@  -- | 'createPatchIndexFrom repo pmods' creates a patch index from the given --   patchmods.-createPatchIndexFrom :: RepoPatch p => Repository rt p wR wU wT+createPatchIndexFrom :: Repository rt p wR wU wT                      -> [(PatchId, [PatchMod FileName])] -> IO ()-createPatchIndexFrom (Repo repodir _ _ _) pmods = do+createPatchIndexFrom repo pmods = do     inv_hash <- getInventoryHash repodir     storePatchIndex repodir cdir inv_hash (applyPatchMods pmods emptyPatchIndex)-  where cdir = repodir </> indexDir-+  where repodir = repoLocation repo+        cdir = repodir </> indexDir+        emptyPatchIndex = PatchIndex [] M.empty M.empty M.empty --- ------------------------------------------------------------------------ Load/Store patch-Index+getInventoryHash :: FilePath -> IO String+getInventoryHash repodir = do+  inv <- B.readFile (repodir </> darcsdir </> "hashed_inventory")+  return $ sha256sum inv --- | load patch-index from disk+-- | Load patch-index from disk along with some meta data. loadPatchIndex :: FilePath -> IO (Int8, String, Map PatchId Int, PatchIndex) loadPatchIndex repodir = do   let pindex_dir = repodir </> indexDir@@ -437,65 +403,66 @@   fpspans <- loadFpMap (pindex_dir </> fpMapFile)   return (v, inv_hash, pid2idx, PatchIndex pids fidspans fpspans infom) --- | load patch-index,--- | ensuring that whenever loaded, the patch-index--- | can actually be read by the current version of darcs,--- | and up to date.-loadSafePatchIndex :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+-- | If patch-index is useful as it is now, read it. If not, create or update it, then read it.+loadSafePatchIndex :: (RepoPatch p, ApplyState p ~ Tree)                    => Repository rt p wR wU wT-                   -> IO (Map PatchId Int, PatchIndex)-loadSafePatchIndex repo@(Repo repodir _ _ _) = do+                   -> PatchSet rt p Origin wR     -- ^ PatchSet of the repository, used if we need to create the patch-index.+                   -> IO PatchIndex+loadSafePatchIndex repo ps = do+   let repodir = repoLocation repo    can_use <- isPatchIndexInSync repo-   (_,_,pid2idx,pi) <-+   (_,_,_,pi) <-      if can_use        then loadPatchIndex repodir-       else do createOrUpdatePatchIndexDisk repo+       else do createOrUpdatePatchIndexDisk repo ps                loadPatchIndex repodir-   return (pid2idx, pi)+   return pi --- | check if patch-index exits for this repository+-- | Read-only. Checks if patch-index exists for this repository+--   it works by checking if:+--+--     1. @_darcs\/patch_index\/@ and its corresponding files are all present+--     2. patch index version is the one handled by this version of Darcs doesPatchIndexExist :: FilePath -> IO Bool doesPatchIndexExist repodir = do- filesArePresent <- fmap and $ mapM (doesFileExist . (pindex_dir </>))+ filesArePresent <- and <$> mapM (doesFileExist . (pindex_dir </>))                     [repoStateFile, pidsFile, touchMapFile, fidMapFile, fpMapFile]  if filesArePresent-  then do (v, _, _, _) <- loadPatchIndex repodir+  then do v <- piVersion           return (v == version)   -- consider PI only of on-disk format is the current one   else return False    where pindex_dir = repodir </> indexDir+         piVersion = fst <$> loadRepoState (pindex_dir </> repoStateFile) --- | check if noPatchIndex exists+-- | Read-only. Checks if @_darcs\/noPatchIndex@ exists, that is, if patch-index is explicitely disabled. isPatchIndexDisabled :: FilePath -> IO Bool isPatchIndexDisabled repodir = doesFileExist (repodir </> darcsdir  </> noPatchIndex) --- | create or update patch index-createOrUpdatePatchIndexDisk :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                             => Repository rt p wR wU wT -> IO ()-createOrUpdatePatchIndexDisk repo@(Repo repodir _ _ _)= do+-- | Create or update patch index+--+--   1. if @_darcs\/no_patch_index@ exists, delete it+--   2. if patch index exists, update it+--   3. if not, create it from scratch+createOrUpdatePatchIndexDisk :: (RepoPatch p, ApplyState p ~ Tree)+                             => Repository rt p wR wU wT -> PatchSet rt p Origin wR -> IO ()+createOrUpdatePatchIndexDisk repo ps = do+   let repodir = repoLocation repo    rmRecursive (repodir </> darcsdir </> noPatchIndex) `catch` \(_ :: IOError) -> return ()    dpie <- doesPatchIndexExist repodir    if dpie-      then updatePatchIndexDisk repo-      else createPatchIndexDisk repo---- | Checks whether a patch index can (and should) be created. If we are not in--- an old-fashioned repo, and if we haven't been told not to, then we should--- create a patch index if it doesn't already exist.-canCreatePI :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT-            -> IO Bool-canCreatePI (Repo repodir format _ _) =-    (not . or) <$> sequence [ doesntHaveHashedInventory format-                            , isPatchIndexDisabled repodir-                            , doesPatchIndexExist repodir-                            ]-  where-    doesntHaveHashedInventory = return . not . formatHas HashedInventory+      then updatePatchIndexDisk repo ps+      else createPatchIndexDisk repo ps --- | see if the default is to use patch index or not--- | creates Patch index, if it does not exist, and noPatchIndex is not set-canUsePatchIndex :: (RepoPatch p, ApplyState p ~ Tree)-                 => Repository rt p wR wU wT -> IO Bool-canUsePatchIndex (Repo repodir _ _ _) = do+-- | Read-only. Checks the two following things:+--+--   1. 'doesPatchIndexExist'+--   2. 'isPatchIndexDisabled'+--+-- Then only if it exists and it is not explicitely disabled, returns @True@, else returns @False@+-- (or an error if it exists and is explicitely disabled at the same time).+canUsePatchIndex :: Repository rt p wR wU wT -> IO Bool+canUsePatchIndex repo = do+     let repodir = repoLocation repo      piExists <- doesPatchIndexExist repodir      piDisabled <- isPatchIndexDisabled repodir      case (piExists, piDisabled) of@@ -504,18 +471,22 @@         (True, True) -> error "patch index exists, and patch index is disabled. run optimize enable-patch-index or disable-patch-index to rectify."         (False, False) -> return False -createPIWithInterrupt :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                      => Repository rt p wR wU wT -> IO ()-createPIWithInterrupt repo@(Repo repodir _ _ _) = do-            putStrLn "Creating a patch index, please wait. To stop press Ctrl-C"-            (do-              createPatchIndexDisk repo-              putStrLn "Created patch index.") `catchInterrupt` (putStrLn "Patch Index Disabled" >> deletePatchIndex repodir)+-- | Creates patch-index (ignoring whether it is explicitely disabled).+--   If it is ctrl-c'ed, then aborts, delete patch-index and mark it as disabled.+createPIWithInterrupt :: (RepoPatch p, ApplyState p ~ Tree)+                      => Repository rt p wR wU wT -> PatchSet rt p Origin wR -> IO ()+createPIWithInterrupt repo ps = do+    let repodir = repoLocation repo+    putStrLn "Creating a patch index, please wait. To stop press Ctrl-C"+    (do+      createPatchIndexDisk repo ps+      putStrLn "Created patch index.") `catchInterrupt` (putStrLn "Patch Index Disabled" >> deletePatchIndex repodir) --- | check if patch-index is in sync with repository-isPatchIndexInSync :: (RepoPatch p, ApplyState p ~ Tree)-                   => Repository rt p wR wU wT -> IO Bool-isPatchIndexInSync (Repo repodir _ _ _) = do+-- | Checks if patch-index exists and is in sync with repository (more precisely with @_darcs\/hashed_inventory@).+--   That is, checks if patch-index can be used as it is now.+isPatchIndexInSync :: Repository rt p wR wU wT -> IO Bool+isPatchIndexInSync repo = do+   let repodir = repoLocation repo    dpie <- doesPatchIndexExist repodir    if dpie     then do@@ -524,7 +495,7 @@       return (inv_hash == inv_hash_pindex)     else return False --- | store patch-index on disk+-- | Stores patch-index on disk. storePatchIndex :: FilePath -> FilePath -> String -> PatchIndex -> IO () storePatchIndex repodir cdir inv_hash (PatchIndex pids fidspans fpspans infom) = do   createDirectory cdir `catch` \(_ :: IOError) -> return ()@@ -556,7 +527,7 @@ storeFidMap :: FilePath -> FileIdSpans -> IO () storeFidMap fp fidm =   encodeFile fp $ M.map (map (\(FidSpan a b c) -> (a, b, toIdxM c))) fidm- where toIdxM (Nothing) = zero+ where toIdxM Nothing = zero        toIdxM (Just pid) = pid  loadFidMap :: FilePath -> IO FileIdSpans@@ -567,7 +538,7 @@ storeFpMap :: FilePath -> FilePathSpans -> IO () storeFpMap fp fidm =   encodeFile fp $ M.map (map (\(FpSpan a b c) -> (a, b, toIdxM c))) fidm- where toIdxM (Nothing) = zero+ where toIdxM Nothing = zero        toIdxM (Just pid) = pid  loadFpMap :: FilePath -> IO FilePathSpans@@ -575,9 +546,6 @@   where toPidM pid | pid == zero = Nothing                    | otherwise   = Just pid -zero :: PatchId-zero = PID $ SHA1 0 0 0 0 0- storeInfoMap :: FilePath -> InfoMap -> IO () storeInfoMap fp infom =   encodeFile fp $ M.map (\fi -> (isFile fi, touching fi)) infom@@ -585,30 +553,17 @@ loadInfoMap :: FilePath -> IO InfoMap loadInfoMap fp = M.map (\(isF,pids) -> FileInfo isF pids) <$> decodeFile fp --- | Base directory for the patch index-indexDir :: String+indexDir, repoStateFile, pidsFile, fidMapFile, fpMapFile,+  touchMapFile, noPatchIndex :: String indexDir = darcsdir </> "patch_index"--repoStateFile :: String repoStateFile = "repo_state"--pidsFile :: String pidsFile = "patch_ids"--fidMapFile :: String fidMapFile = "fid_map"--fpMapFile :: String fpMapFile = "fp_map"--touchMapFile :: String touchMapFile = "touch_map"--noPatchIndex :: String noPatchIndex = "no_patch_index" --------------------------------------------------------------------------- Delete patch index+-- | Deletes patch-index (@_darcs\/patch_index\/@ and its contents) and mark repository as disabled (creates @_darcs\/no_patch_index@). deletePatchIndex :: FilePath -> IO () deletePatchIndex repodir = do     exists <- doesDirectoryExist indexDir@@ -618,9 +573,6 @@     (openFile (repodir </> darcsdir </> noPatchIndex) WriteMode >>= hClose)             `catch` \(e :: IOError) -> error $ "Error: Could not disable patch index\n" ++ show e --------------------------------------------------------------------------- Dump information in patch index- dumpRepoState :: [PatchId] -> String dumpRepoState = unlines . map pid2string @@ -648,34 +600,38 @@ fpSpans2filePaths' :: FileIdSpans -> [FilePath] fpSpans2filePaths' fidSpans = [fn2fp fp | (fp, _)  <- M.toList fidSpans] -dumpPatchIndex :: FilePath -> IO ()-dumpPatchIndex repodir = do-  (_,inv_hash,_,PatchIndex pids fidspans fpspans infom) <- loadPatchIndex repodir-  putStrLn $ "Inventory hash:" ++ inv_hash-  putStrLn "================="-  putStrLn "Repo state:"-  putStrLn "==========="-  putStrLn $ dumpRepoState pids-  putStrLn "Fileid spans:"-  putStrLn "============="-  putStrLn $ dumpFileIdSpans fidspans-  putStrLn "Filepath spans:"-  putStrLn "=============="-  putStrLn $ dumpFilePathSpans fpspans-  putStrLn "Info Map:"-  putStrLn "========="-  putStrLn $ dumpTouchingMap infom-  putStrLn "Files:"-  putStrLn "=============="-  putStrLn $ unlines $ fpSpans2filePaths fpspans infom+-- | Checks if patch index can be created and build it with interrupt.+attemptCreatePatchIndex+  :: (RepoPatch p, ApplyState p ~ Tree)+  => Repository rt p wR wU wT -> PatchSet rt p Origin wR -> IO ()+attemptCreatePatchIndex repo ps = do+  canCreate <- canCreatePI repo+  when canCreate $ createPIWithInterrupt repo ps --------------------------------------------------------------------------- Filtering functions based on FilePaths--- returns an RL in which the order of patches matters, for annotate to use-getRelevantSubsequence :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, a ~ PatchInfoAnd rt p)-                       => Sealed ((RL a) wK) -> Repository rt p wR wU wR -> [FileName] -> IO (Sealed ((RL a) Origin))-getRelevantSubsequence pxes repository fns = do-   (_, pi@(PatchIndex _ _ _ infom)) <- loadSafePatchIndex repository+-- | Checks whether a patch index can (and should) be created. If we are not in+-- an old-fashioned repo, and if we haven't been told not to, then we should+-- create a patch index if it doesn't already exist.+canCreatePI :: Repository rt p wR wU wT -> IO Bool+canCreatePI repo =+    (not . or) <$> sequence [ doesntHaveHashedInventory (repoFormat repo)+                            , isPatchIndexDisabled repodir+                            , doesPatchIndexExist repodir+                            ]+  where+    repodir = repoLocation repo+    doesntHaveHashedInventory = return . not . formatHas HashedInventory++-- | Returns an RL in which the order of patches matters. Useful for the @annotate@ command.+--   If patch-index does not exist and is not explicitely disabled, silently create it.+--   (Also, if it is out-of-sync, which should not happen, silently update it).+getRelevantSubsequence :: (RepoPatch p, ApplyState p ~ Tree, a ~ PatchInfoAnd rt p)+                       => Sealed ((RL a) wK)          -- ^ Sequence of patches you want to filter+                       -> Repository rt p wR wU wR    -- ^ The repository (to attempt loading patch-index from its path)+                       -> PatchSet rt p Origin wR     -- ^ PatchSet of repository (in case we need to create patch-index)+                       -> [FileName]                  -- ^ File(s) about which you want patches from given sequence+                       -> IO (Sealed ((RL a) Origin)) -- ^ Filtered sequence of patches.+getRelevantSubsequence pxes repository ps fns = do+   pi@(PatchIndex _ _ _ infom) <- loadSafePatchIndex repository ps    let fids = map (\fn -> evalState (lookupFid fn) pi) fns        pidss = map ((\(FileInfo _ a) -> a).fromJust.(`M.lookup` infom)) fids        pids = S.unions pidss@@ -686,38 +642,58 @@                   => FL a wX wY -> RL a wB wX -> S.Set Word32 -> RL a wP wQ         keepElems NilFL acc _ = unsafeCoerceP acc         keepElems (x:>:xs) acc pids-          | (short $ makePatchID $ info x) `S.member` pids = keepElems xs (acc:<:x) pids-          | otherwise                                      = keepElems (unsafeCoerceP xs) acc pids---- | filter given patches so as to keep only the patches that modify the given files-filterPatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, a ~ PatchInfoAnd rt p) => Repository rt p wR wU wT -> [FilePath] -> [Sealed2 a] -> IO [Sealed2 a]-filterPatches repository fps ops = do-   (_, pi@(PatchIndex _ _ _ infom)) <- loadSafePatchIndex repository-   let fids = concatMap ((\fn -> evalState (lookupFids' fn) pi). fp2fn) fps-       npids = S.unions $ map (touching.fromJust.(`M.lookup` infom)) fids-   return $ filter (flip S.member npids . (\(Sealed2 (PIAP pin _)) -> short $ makePatchID pin)) ops+          | short (makePatchID $ info x) `S.member` pids = keepElems xs (acc:<:x) pids+          | otherwise                                    = keepElems (unsafeCoerceP xs) acc pids  type PatchFilter rt p = [FilePath] -> [Sealed2 (PatchInfoAnd rt p)] -> IO [Sealed2 (PatchInfoAnd rt p)] --- | If a patch index is available, filter given patches so as to keep only the patches that--- modify the given files. If none is available, return the original input.+-- | If a patch index is available, returns a filter that takes a list of files and returns+--   a @PatchFilter@ that only keeps patches that modify the given list of files.+--   If patch-index cannot be used, return the original input.+--   If patch-index does not exist and is not explicitely disabled, silently create it.+--   (Also, if it is out-of-sync, which should not happen, silently update it). maybeFilterPatches-    :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-    => Repository rt p wR wU wT-    -> PatchFilter rt p-maybeFilterPatches repo fps ops = do+    :: (RepoPatch p, ApplyState p ~ Tree)+    => Repository rt p wR wU wT  -- ^ The repository+    -> PatchSet rt p Origin wR   -- ^ PatchSet of patches of repository (in case patch-index needs to be created)+    -> PatchFilter rt p          -- ^ PatchFilter ready to be used by SelectChanges.+maybeFilterPatches repo ps fps ops = do     usePI <- canUsePatchIndex repo-    -- in theory we could change the type signature to make this function staged,-    -- but it doesn't seem worth it.-    if usePI then filterPatches repo fps ops else return ops-+    if usePI+      then do+        pi@(PatchIndex _ _ _ infom) <- loadSafePatchIndex repo ps+        let fids = concatMap ((\fn -> evalState (lookupFids' fn) pi). fp2fn) fps+            npids = S.unions $ map (touching.fromJust.(`M.lookup` infom)) fids+        return $ filter (flip S.member npids . (\(Sealed2 (PIAP pin _)) -> short $ makePatchID pin)) ops+      else return ops --------------------------------------------------------------------------- Test patch index+-- | Dump information in patch index. Patch-index should be checked to exist beforehand. Read-only.+dumpPatchIndex :: FilePath -> IO ()+dumpPatchIndex repodir = do+  (_,inv_hash,_,PatchIndex pids fidspans fpspans infom) <- loadPatchIndex repodir+  putStrLn $ unlines $+    [ "Inventory hash:" ++ inv_hash+    , "================="+    , "Repo state:"+    , "==========="+    , dumpRepoState pids+    , "Fileid spans:"+    , "============="+    , dumpFileIdSpans fidspans+    , "Filepath spans:"+    , "=============="+    , dumpFilePathSpans fpspans+    , "Info Map:"+    , "========="+    , dumpTouchingMap infom+    , "Files:"+    , "=============="+    ] ++ fpSpans2filePaths fpspans infom -piTest :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO ()-piTest repository = do-   (_, PatchIndex rpids fidspans fpspans infom) <- loadSafePatchIndex repository+-- | Read-only sanity check on patch-index. Patch-index should be checked to exist beforehand. It may not be in sync with repository.+piTest :: FilePath -> IO ()+piTest repodir = do+   (_,_,_,PatchIndex rpids fidspans fpspans infom) <- loadPatchIndex repodir    let pids = reverse rpids     -- test fidspans@@ -760,9 +736,4 @@           isInOrder [] _ = True           isInOrder _ [] = False --- | Check if patch index can be created and build it with interrupt.-attemptCreatePatchIndex-  :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO ()-attemptCreatePatchIndex repo = do-  canCreate <- canCreatePI repo-  when canCreate $ createPIWithInterrupt repo+
src/Darcs/Repository/Pending.hs view
@@ -16,15 +16,16 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.Repository.Pending     ( readPending-    , readTentativePending-    , writeTentativePending+    , siftForPending+    , tentativelyRemoveFromPending+    , finalizePending+    , makeNewPending+    , tentativelyAddToPending+    , setTentativePending+    , prepend     -- deprecated interface:-    , readNewPending-    , writeNewPending     , pendingName     ) where @@ -32,21 +33,57 @@ import Darcs.Prelude  import Control.Applicative-import qualified Data.ByteString as BS ( empty )+import qualified Data.ByteString as B ( empty ) +import Control.Exception ( catch, IOException )+import Data.Maybe ( fromMaybe )++import Darcs.Util.Printer ( errorDoc ) import Darcs.Util.Global ( darcsdir )-import Darcs.Util.Lock ( writeDocBinFile )-import Darcs.Repository.InternalTypes ( Repository(..) )-import Darcs.Patch ( readPatch, RepoPatch, PrimOf )+import Darcs.Util.Lock+    ( writeDocBinFile+    , removeFileMayNotExist+    )+import Darcs.Repository.InternalTypes ( Repository, withRepoLocation )+import Darcs.Repository.Flags+    ( UpdateWorking (..))+import Darcs.Patch+    ( readPatch, RepoPatch, PrimOf, tryToShrink+    , primIsHunk, primIsBinary, commute, invert+    , primIsAddfile, primIsAdddir, commuteFLorComplain+    , effect, primIsSetpref, applyToTree )+import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd )+import Darcs.Patch.Progress (progressFL)+import Darcs.Patch.Permutations ( commuteWhatWeCanFL+                                , removeFL+                                )++import Darcs.Patch.Prim ( tryShrinkingInverse+                        , PrimPatch+                        ) import Darcs.Patch.Read ( ReadPatch(..), bracketedFL ) import Darcs.Patch.ReadMonads ( ParserM )-import Darcs.Patch.Show ( ShowPatchBasic(..) )-import Darcs.Util.Exception ( catchall )-import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed), mapSeal )-import Darcs.Patch.Witnesses.Ordered ( FL(..), mapFL )+import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatchFor(ForStorage) )+import Darcs.Patch.Apply ( ApplyState ) +import Darcs.Util.Tree ( Tree )+import Darcs.Util.Exception ( catchall )+import Darcs.Util.Workaround ( renameFile )+import Darcs.Patch.Witnesses.Eq ( EqCheck(..) )+import Darcs.Patch.Witnesses.Sealed+    ( Sealed(Sealed), mapSeal, seal+    , FlippedSeal(FlippedSeal)+    , flipSeal+    )+import Darcs.Patch.Witnesses.Unsafe+    ( unsafeCoerceP, unsafeCoercePStart )+import Darcs.Patch.Witnesses.Ordered+    ( FL(..), RL(..), (:>)(..), (+>+)+    , lengthFL, allFL, filterOutFLFL+    , reverseFL, mapFL ) import Darcs.Util.ByteString ( gzReadFilePS )-import Darcs.Util.Printer ( Doc, ($$), (<>), text, vcat )+import Darcs.Util.Printer ( Doc, ($$), (<>), text, vcat, (<+>) )+import Darcs.Util.Progress ( debugMessage )  pendingName :: String pendingName = darcsdir ++ "/patches/pending"@@ -77,21 +114,22 @@ readPendingFile :: ReadPatch prim => String -> Repository rt p wR wU wT                 -> IO (Sealed (FL prim wX)) readPendingFile suffix _ = do-    pend <- gzReadFilePS (pendingName ++ suffix) `catchall` return BS.empty+    pend <- gzReadFilePS (pendingName ++ suffix) `catchall` return B.empty     return . maybe (Sealed NilFL) (mapSeal unFLM) . readPatch $ pend  -- Wrapper around FL where printed format uses { } except around singletons. -- Now that the Show behaviour of FL p can be customised (using--- showFLBehavior), we could instead change the general behaviour of FL Prim;+-- showFLBehavior (*)), we could instead change the general behaviour of FL Prim; -- but since the pending code can be kept nicely compartmentalised, it's nicer -- to do it this way.+-- (*) bf: This function does not exist. newtype FLM p wX wY = FLM { unFLM :: FL p wX wY }  instance ReadPatch p => ReadPatch (FLM p) where     readPatch' = mapSeal FLM <$> readMaybeBracketedFL readPatch' '{' '}'  instance ShowPatchBasic p => ShowPatchBasic (FLM p) where-    showPatch = showMaybeBracketedFL showPatch '{' '}' . unFLM+    showPatch f = showMaybeBracketedFL (showPatch f) '{' '}' . unFLM  readMaybeBracketedFL :: forall m p wX . ParserM m                      => (forall wY . m (Sealed (p wY))) -> Char -> Char@@ -126,4 +164,228 @@     name = pendingName ++ suffix  writePatch :: ShowPatchBasic p => FilePath -> p wX wY -> IO ()-writePatch f p = writeDocBinFile f $ showPatch p <> text "\n"+writePatch f p = writeDocBinFile f $ showPatch ForStorage p <> text "\n"++-- | @siftForPending ps@ simplifies the candidate pending patch @ps@+--   through a combination of looking for self-cancellations+--   (sequences of patches followed by their inverses), coalescing,+--   and getting rid of any hunk/binary patches we can commute out+--   the back+--+--   The visual image of sifting can be quite helpful here.  We are+--   repeatedly tapping (shrinking) the patch sequence and+--   shaking it (sift). Whatever falls out is the pending we want+--   to keep. We do this until the sequence looks about as clean as+--   we can get it+siftForPending :: forall prim wX wY . PrimPatch prim => FL prim wX wY -> Sealed (FL prim wX)+siftForPending simple_ps =+    if allFL (\p -> primIsAddfile p || primIsAdddir p) oldps+       then seal oldps+       else fromJust $ do+           Sealed x <- return $ sift NilFL $ reverseFL oldps+           return $ case tryToShrink x of+               ps | lengthFL ps < lengthFL oldps -> siftForPending ps+                  | otherwise -> seal ps+  where+    oldps = fromMaybe simple_ps $ tryShrinkingInverse $ crudeSift simple_ps+    -- get rid of any hunk/binary patches that we can commute out the+    -- back (ie. we work our way backwards, pushing the patches down+    -- to the very end and popping them off; so in (addfile f :> hunk)+    -- we can nuke the hunk, but not so in (hunk :> replace)+    sift :: FL prim wA wB -> RL prim wC wA -> Sealed (FL prim wC)+    sift sofar NilRL = seal sofar+    sift sofar (ps:<:p) | primIsHunk p || primIsBinary p =+        case commuteFLorComplain (p :> sofar) of+            Right (sofar' :> _) -> sift sofar'      ps+            Left _              -> sift (p:>:sofar) ps+    sift sofar (ps:<:p) = sift (p:>:sofar) ps++-- | 'crudeSift' can be seen as a first pass approximation of 'siftForPending'+--    that works without having to do any commutation.  It either returns a+--    sifted pending (if the input is simple enough for this crude approach)+--    or has no effect.+crudeSift :: forall prim wX wY . PrimPatch prim => FL prim wX wY -> FL prim wX wY+crudeSift xs =+    if isSimple xs then filterOutFLFL ishunkbinary xs else xs+  where+    ishunkbinary :: prim wA wB -> EqCheck wA wB+    ishunkbinary x | primIsHunk x || primIsBinary x = unsafeCoerceP IsEq+                   | otherwise = NotEq++-- | @tentativelyRemoveFromPending p@ is used by Darcs whenever it+--   adds a patch to the repository (eg. with apply or record).+--   Think of it as one part of transferring patches from pending to+--   somewhere else.+--+--   Question (Eric Kow): how do we detect patch equivalence?+tentativelyRemoveFromPending :: forall rt p wR wU wT wX wY. (RepoPatch p)+                 => Repository rt p wR wU wT+                 -> UpdateWorking+                 -> PatchInfoAnd rt p wX wY+                 -> IO ()+tentativelyRemoveFromPending _    NoUpdateWorking  _ = return ()+tentativelyRemoveFromPending repo YesUpdateWorking p = do+    Sealed pend <- readTentativePending repo+    -- Question (Eric Kow): why does pending being all simple matter for+    -- changepref patches in p? isSimple includes changepref, so what do+    -- adddir/etc have to do with it?  Why don't we we systematically+    -- crudeSift/not?+    let effectp = if isSimple pend+                     then crudeSift $ effect p+                     else effect p+    Sealed newpend <- return $ rmpend (progressFL "Removing from pending:" effectp)+                               (unsafeCoercePStart pend)+    writeTentativePending repo (unsafeCoercePStart newpend)+  where+    -- @rmpend effect pending@ removes as much of @effect@ from @pending@+    -- as possible+    --+    -- Note that @effect@ and @pending@ must start from the same context+    -- This is not a bad thing to assume because @effect@ is a patch we want to+    -- add to the repository anyway so it'd kind of have to start from wR anyway+    --+    -- Question (Eric Kow), ok then why not+    -- @PatchInfoAnd p wR wY@ in the type signature above?+    rmpend :: FL (PrimOf p) wA wB -> FL (PrimOf p) wA wC -> Sealed (FL (PrimOf p) wB)+    rmpend NilFL x = Sealed x+    rmpend _ NilFL = Sealed NilFL+    rmpend (x:>:xs) xys | Just ys <- removeFL x xys = rmpend xs ys+    rmpend (x:>:xs) ys =+        case commuteWhatWeCanFL (x:>xs) of+            a:>x':>b -> case rmpend a ys of+                Sealed ys' -> case commute (invert (x':>:b) :> ys') of+                    Just (ys'' :> _) -> seal ys''+                    Nothing          -> seal $ invert (x':>:b)+>+ys'+                    -- DJR: I don't think this last case should be+                    -- reached, but it also shouldn't lead to corruption.++-- | A sequence of primitive patches (candidates for the pending patch)+--   is considered simple if we can reason about their continued status as+--   pending patches solely on the basis of them being hunk/binary patches.+--+--   Simple here seems to mean that all patches are either hunk/binary+--   patches, or patches that cannot (indirectly) depend on hunk/binary+--   patches.  For now, the only other kinds of patches in this category+--   are changepref patches.+--+--   It might be tempting to add, say, adddir patches but it's probably not a+--   good idea because Darcs also inverts patches a lot in its reasoning so an+--   innocent addir may be inverted to a rmdir which in turn may depend on+--   a rmfile, which in turn depends on a hunk/binary. Likewise, we would+--   not want to add move patches to this category for similar reasons of+--   a potential dependency chain forming.+isSimple :: PrimPatch prim => FL prim wX wY -> Bool+isSimple =+    allFL isSimp+  where+    isSimp x = primIsHunk x || primIsBinary x || primIsSetpref x++-- | @makeNewPending repo YesUpdateWorking pendPs@ verifies that the+--   @pendPs@ could be applied to pristine if we wanted to, and if so+--   writes it to disk.  If it can't be applied, @pendPs@ must+--   be somehow buggy, so we save it for forensics and crash.+makeNewPending :: (RepoPatch p, ApplyState p ~ Tree)+                 => Repository rt p wR wU wT+                 -> UpdateWorking+                 -> FL (PrimOf p) wT wY+                 -> Tree IO  -- ^recorded state of the repository, to check if pending can be applied+                 -> IO ()+makeNewPending _                  NoUpdateWorking _ _ = return ()+makeNewPending repo YesUpdateWorking origp recordedState =+    withRepoLocation repo $+    do let newname = pendingName ++ ".new"+       debugMessage $ "Writing new pending:  " ++ newname+       Sealed sfp <- return $ siftForPending origp+       writeNewPending repo sfp+       Sealed p <- readNewPending repo+       -- We don't ever use the resulting tree.+       _ <- catch (applyToTree p recordedState) $ \(err :: IOException) -> do+         let buggyname = pendingName ++ "_buggy"+         renameFile newname buggyname+         errorDoc $ text ("There was an attempt to write an invalid pending! " ++ show err)+                    $$ text "If possible, please send the contents of"+                    <+> text buggyname+                    $$ text "along with a bug report."+       renameFile newname pendingName+       debugMessage $ "Finished writing new pending:  " ++ newname++-- | Replace the pending patch with the tentative pending.+--   If @NoUpdateWorking@, this merely deletes the tentative pending+--   without replacing the current one.+--+--   Question (Eric Kow): shouldn't this also delete the tentative+--   pending if @YesUpdateWorking@?  I'm just puzzled by the seeming+--   inconsistency of the @NoUpdateWorking@ doing deletion, but+--   @YesUpdateWorking@ not bothering.+finalizePending :: (RepoPatch p, ApplyState p ~ Tree)+                => Repository rt p wR wU wT+                -> UpdateWorking+                -> Tree IO+                -> IO ()+finalizePending repo NoUpdateWorking _ =+  withRepoLocation repo $ removeFileMayNotExist pendingName+finalizePending repo updateWorking@YesUpdateWorking recordedState =+  withRepoLocation repo $ do+      Sealed tpend <- readTentativePending repo+      Sealed new_pending <- return $ siftForPending tpend+      makeNewPending repo updateWorking new_pending recordedState++-- | @tentativelyAddToPending repo NoDryRun YesUpdateWorking pend ps@+--   appends @ps@ to the pending patch.+--+--   It has no effect with @NoUpdateWorking@.+--+--   This fuction is unsafe because it accepts a patch that works on the+--   tentative pending and we don't currently track the state of the+--   tentative pending.+tentativelyAddToPending :: forall rt p wR wU wT wX wY. RepoPatch p+                        => Repository rt p wR wU wT+                        -> UpdateWorking+                        -> FL (PrimOf p) wX wY+                        -> IO ()+tentativelyAddToPending _                   NoUpdateWorking  _     = return ()+tentativelyAddToPending repo YesUpdateWorking patch =+    withRepoLocation repo $ do+        Sealed pend <- readTentativePending repo+        FlippedSeal newpend_ <- return $+            newpend (unsafeCoerceP pend :: FL (PrimOf p) wA wX) patch+        writeTentativePending repo (unsafeCoercePStart newpend_)+  where+    newpend :: FL prim wA wB -> FL prim wB wC -> FlippedSeal (FL prim) wC+    newpend NilFL patch_ = flipSeal patch_+    newpend p     patch_ = flipSeal $ p +>+ patch_++-- | setTentativePending is basically unsafe.  It overwrites the pending+--   state with a new one, not related to the repository state.+setTentativePending :: forall rt p wR wU wT wX wY. RepoPatch p+                    => Repository rt p wR wU wT+                    -> UpdateWorking+                    -> FL (PrimOf p) wX wY+                    -> IO ()+setTentativePending _                   NoUpdateWorking  _ = return ()+setTentativePending repo YesUpdateWorking patch = do+    Sealed prims <- return $ siftForPending patch+    withRepoLocation repo $ writeTentativePending repo (unsafeCoercePStart prims)++-- | @prepend repo YesUpdateWorking ps@ prepends @ps@ to the pending patch+--   It's used right before removing @ps@ from the repo.  This ensures that+--   the pending patch can still be applied on top of the recorded state.+--+--   This function is basically unsafe.  It overwrites the pending state+--   with a new one, not related to the repository state.+prepend :: forall rt p wR wU wT wX wY. RepoPatch p+        => Repository rt p wR wU wT+        -> UpdateWorking+        -> FL (PrimOf p) wX wY+        -> IO ()+prepend _    NoUpdateWorking  _     = return ()+prepend repo YesUpdateWorking patch = do+    Sealed pend <- readTentativePending repo+    Sealed newpend_ <- return $ newpend (unsafeCoerceP pend) patch+    writeTentativePending repo (unsafeCoercePStart $ crudeSift newpend_)+  where+    newpend :: FL prim wB wC -> FL prim wA wB -> Sealed (FL prim wA)+    newpend NilFL patch_ = seal patch_+    newpend p     patch_ = seal $ patch_ +>+ p++
src/Darcs/Repository/Prefs.hs view
@@ -15,9 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. --{-# LANGUAGE CPP #-}- module Darcs.Repository.Prefs     ( addToPreflist     , deleteSources@@ -39,12 +36,15 @@     , FileType(..)     , filetypeFunction     , getCaches-    , binariesFileHelp-    , boringFileHelp     , globalCacheDir     , globalPrefsDirDoc     , globalPrefsDir-    , oldGlobalCacheDir+    , getMotd+    , showMotd+    , prefsUrl+    , prefsDirPath+    -- * documentation of prefs files+    , prefsFilesHelp     ) where  import Prelude ()@@ -56,28 +56,28 @@ import Data.List ( nub, isPrefixOf, union, sortBy, lookup ) import Data.Maybe ( isJust, fromMaybe, mapMaybe, catMaybes, maybeToList ) import qualified Control.Exception as C-import qualified Data.ByteString       as B  ( empty )+import qualified Data.ByteString       as B  ( empty, null, hPut, ByteString ) import qualified Data.ByteString.Char8 as BC ( unpack ) import System.Directory ( getAppUserDataDirectory, doesDirectoryExist,                           createDirectory, doesFileExist ) import System.Environment ( getEnvironment ) import System.FilePath.Posix ( normalise, dropTrailingPathSeparator, (</>) ) import System.IO.Error ( isDoesNotExistError )-import System.IO ( stderr )+import System.IO ( stdout, stderr ) import System.Info ( os ) import Text.Regex ( Regex, mkRegex, matchRegex )  import Darcs.Repository.Cache ( Cache(..), CacheType(..), CacheLoc(..),                                 WritableOrNot(..), compareByLocality )-import Darcs.Util.External ( gzFetchFilePS , Cachable( Cachable ))+import Darcs.Util.External ( gzFetchFilePS , fetchFilePS, Cachable(..)) import Darcs.Repository.Flags( UseCache (..), DryRun (..), SetDefault (..),                                RemoteRepos (..) )-import Darcs.Util.Lock( readBinFile, writeBinFile )+import Darcs.Util.Lock( readTextFile, writeTextFile ) import Darcs.Util.Exception ( catchall ) import Darcs.Util.Global ( darcsdir ) import Darcs.Util.Path ( AbsolutePath, ioAbsolute, toFilePath,                          getCurrentDirectory )-import Darcs.Util.Printer( hPutDocLn, text, RenderMode(..) )+import Darcs.Util.Printer( hPutDocLn, text ) import Darcs.Util.URL ( isValidLocalPath ) import Darcs.Util.File ( osxCacheDir, xdgCacheDir, removeFileMayNotExist ) @@ -91,9 +91,8 @@     setPreflist "binaries" defaultBinaries     setPreflist "motd" [] -{-# NOINLINE defaultBoring #-} defaultBoring :: [String]-defaultBoring = map ("# " ++) boringFileHelp +++defaultBoring = map ("# " ++) boringFileInternalHelp ++     [ ""     , "### compiler and interpreter intermediate files"     , "# haskell (ghc) interfaces"@@ -156,8 +155,6 @@     , "(^|/)SCCS($|/)"     , "# darcs"     , "(^|/)"++darcsdir++"($|/)", "(^|/)\\.darcsrepo($|/)"-    , "^\\.darcs-temp-mail$"-    , "-darcs-backup[[:digit:]]+$"     , "# gnu arch"     , "(^|/)(\\+|,)"     , "(^|/)vssver\\.scc$"@@ -191,12 +188,12 @@     , "(^|.*/)\\.emacs\\.desktop(\\.lock)?$"     ] -boringFileHelp :: [String]-boringFileHelp =+boringFileInternalHelp :: [String]+boringFileInternalHelp =     [ "This file contains a list of extended regular expressions, one per"     , "line. A file path matching any of these expressions will be filtered"-    , "out during `darcs add', or when the `--look-for-adds' flag is passed"-    , "to `darcs whatsnew' and `record'. The entries in "+    , "out during `darcs add`, or when the `--look-for-adds` flag is passed"+    , "to `darcs whatsnew` and `record`. The entries in "         ++ globalPrefsDirDoc ++ "boring (if"     , "it exists) supplement those in this file."     , ""@@ -252,18 +249,6 @@                | osx       = ((</> "darcs") `fmap`) `fmap` osxCacheDir                | otherwise = ((</> "darcs") `fmap`) `fmap` xdgCacheDir --- |oldGlobalCacheDir is the old cache path @~/.darcs/cache@--- now ony used with read-only access.-oldGlobalCacheDir :: IO (Maybe FilePath)-oldGlobalCacheDir-    = do dir <- ((</> "cache") `fmap`) `fmap` globalPrefsDir-         case dir of-           Nothing -> return Nothing-           Just d  -> do exists <- doesDirectoryExist d-                         if exists-                          then return $ Just d-                          else return Nothing- -- |tryMakeBoringRegexp attempts to create a Regex from a given String. The -- evaluation is forced, to ensure any malformed exceptions are thrown here, -- and not later.@@ -273,7 +258,7 @@     regex = C.evaluate (Just $! mkRegex input)      handleBadRegex :: C.SomeException -> IO (Maybe Regex)-    handleBadRegex _ = hPutDocLn Encode stderr warning >> return Nothing+    handleBadRegex _ = hPutDocLn stderr warning >> return Nothing      warning = text $ "Warning: Ignored invalid boring regex: " ++ input @@ -302,10 +287,10 @@     nonComment _ = True  getPrefLines :: FilePath -> IO [String]-getPrefLines f = removeCRsCommentsAndConflicts `fmap` readBinFile f+getPrefLines f = removeCRsCommentsAndConflicts `fmap` readTextFile f   where     removeCRsCommentsAndConflicts =-        filter notconflict . noncomments . map stripCr . lines+        filter notconflict . noncomments . map stripCr     startswith [] _ = True     startswith (x : xs) (y : ys) = x == y && startswith xs ys     startswith _ _ = False@@ -325,7 +310,6 @@               | TextFile               deriving (Eq) -{-# NOINLINE defaultBinaries #-} -- | The lines that will be inserted into @_darcs/prefs/binaries@ when -- @darcs init@ is run.  Hence, a list of comments, blank lines and -- regular expressions (ERE dialect).@@ -333,7 +317,7 @@ -- Note that while this matches .gz and .GZ, it will not match .gZ, -- i.e. it is not truly case insensitive. defaultBinaries :: [String]-defaultBinaries = map ("# "++) binariesFileHelp +++defaultBinaries = map ("# "++) binariesFileInternalHelp ++     [ "\\." ++ regexToMatchOrigOrUpper e ++ "$" | e <- extensions ]   where     regexToMatchOrigOrUpper e = "(" ++ e ++ "|" ++ map toUpper e ++ ")"@@ -363,8 +347,8 @@         , "zip"         ] -binariesFileHelp :: [String]-binariesFileHelp =+binariesFileInternalHelp :: [String]+binariesFileInternalHelp =     [ "This file contains a list of extended regular expressions, one per"     , "line.  A file path matching any of these expressions is assumed to"     , "contain binary data (not text). The entries in "@@ -402,7 +386,7 @@     hasprefs <- doesDirectoryExist prefs     unless hasprefs $ createDirectory prefs     pl <- getPreflist pref-    writeBinFile (prefs ++ pref) . unlines $ union [value] pl+    writeTextFile (prefs ++ pref) . unlines $ union [value] pl  getPreflist :: String -> IO [String] getPreflist p = findPrefsDirectory >>=@@ -417,14 +401,14 @@ setPreflist p ls = withPrefsDirectory $ \prefs -> do     haspref <- doesDirectoryExist prefs     when haspref $-        writeBinFile (prefs ++ p) (unlines ls)+        writeTextFile (prefs ++ p) (unlines ls)  defPrefval :: String -> String -> IO String defPrefval p d = fromMaybe d `fmap` getPrefval p  getPrefval :: String -> IO (Maybe String) getPrefval p = do-    pl <- getPreflist "prefs"+    pl <- getPreflist prefsDir     return $ case map snd $ filter ((== p) . fst) $ map (break (== ' ')) pl of                  [val] -> case words val of                     [] -> Nothing@@ -433,8 +417,8 @@  setPrefval :: String -> String -> IO () setPrefval p v = do-    pl <- getPreflist "prefs"-    setPreflist "prefs" $ updatePrefVal pl p v+    pl <- getPreflist prefsDir+    setPreflist prefsDir $ updatePrefVal pl p v  updatePrefVal :: [String] -> String -> String -> [String] updatePrefVal prefList p newVal =@@ -442,10 +426,10 @@  changePrefval :: String -> String -> String -> IO () changePrefval p f t = do-    pl <- getPreflist "prefs"+    pl <- getPreflist prefsDir     ov <- getPrefval p     let newval = maybe t (\old -> if old == f then t else old) ov-    setPreflist "prefs" $ updatePrefVal pl p newval+    setPreflist prefsDir $ updatePrefVal pl p newval  fixRepoPath :: String -> IO FilePath fixRepoPath p@@ -513,12 +497,7 @@              `fmap`              (gzFetchFilePS (repodir </> sourcesFile) Cachable               `catchall` return B.empty)-    oldGlobalcachedir <- oldGlobalCacheDir     globalcachedir <- globalCacheDir-    let oldGlobalcache = if nocache then []-                        else case oldGlobalcachedir of-                              Nothing -> []-                              Just d -> [Cache Directory NotWritable d]     let globalcache = if nocache                           then []                           else case globalcachedir of@@ -530,7 +509,6 @@         thatrepo = [Cache Repo NotWritable repodir]         tempCache = nub $ thisrepo ++ globalcache ++ globalsources ++ here                           ++ thatrepo ++ filterExternalSources there-                          ++ oldGlobalcache     return $ Ca $ sortBy compareByLocality tempCache   where     sourcesFile = darcsdir ++ "/prefs/sources"@@ -551,3 +529,158 @@         if isValidLocalPath repodir             then there             else filter (not . isValidLocalPath . cacheSource) there++-- | Fetch and return the message of the day for a given repository.+getMotd :: String -> IO B.ByteString+getMotd repo = fetchFilePS motdPath (MaxAge 600) `catchall` return B.empty+  where+    motdPath = repo ++ "/" ++ darcsdir ++ "/prefs/motd"++-- | Display the message of the day for a given repository,+showMotd :: String -> IO ()+showMotd repo = do+    motd <- getMotd repo+    unless (B.null motd) $ do+        B.hPut stdout motd+        putStrLn $ replicate 22 '*'++prefsUrl :: FilePath -> String+prefsUrl r = r ++ "/"++darcsdir++"/prefs"++prefsDir :: FilePath+prefsDir = "prefs"++prefsDirPath :: FilePath+prefsDirPath = darcsdir </> prefsDir++prefsFilesHelp :: [(String,String)]+prefsFilesHelp  =+    [ ("motd", unlines+      [ "The `_darcs/prefs/motd` file may contain a 'message of the day' which"+      , "will be displayed to users who clone or pull from the repository without"+      , "the `--quiet` option."])+    , ("email", unlines+      [ "The `_darcs/prefs/email` file is used to provide the e-mail address for"+      , "your repository that others will use when they `darcs send` a patch back"+      , "to you. The contents of the file should simply be an e-mail address."])+    , ("post", unlines+      [ "If `_darcs/prefs/post` exists in the target repository, `darcs send ` will"+      , "upload to the URL contained in that file, which may either be a `mailto:`"+      , "URL, or an `http://` URL. In the latter case, the patch is posted to that URL."])+    , ("author", unlines+      [ "The `_darcs/prefs/author` file contains the email address (or name) to"+      , "be used as the author when patches are recorded in this repository,"+      , "e.g. `David Roundy <droundy@abridgegame.org>`. This file overrides the"+      , "contents of the environment variables `$DARCS_EMAIL` and `$EMAIL`."])+    , ("defaults", unlines+      [ "Default values for darcs commands. Each line of this file has the"+      , "following form:"+      , ""+      , "    COMMAND FLAG VALUE"+      , ""+      , "where `COMMAND` is either the name of the command to which the default"+      , "applies, or `ALL` to indicate that the default applies to all commands"+      , "accepting that flag. The `FLAG` term is the name of the long argument"+      , "option without the `--`, i.e. `verbose` rather than `--verbose`."+      , "Finally, the `VALUE` option can be omitted if the flag does not involve"+      , "a value. If the value has spaces in it, use single quotes, not double"+      , "quotes, to surround it. Each line only takes one flag. To set multiple"+      , "defaults for the same command (or for `ALL` commands), use multiple lines."+      , ""+      , "Note that the use of `ALL` easily can have unpredicted consequences,"+      , "especially if commands in newer versions of darcs accepts flags that"+      , "they did not in previous versions. Only use safe flags with `ALL`."+      , ""+      , "For example, if your system clock is bizarre, you could instruct darcs to"+      , "always ignore the file modification times by adding the following line:"+      , ""+      , "    ALL ignore-times"+      , ""+      , "There are some options which are meant specifically for use in"+      , "`_darcs/prefs/defaults`. One of them is `--disable`. As the name"+      , "suggests, this option will disable every command that got it as"+      , "argument. So, if you are afraid that you could damage your repositories"+      , "by inadvertent use of a command like amend, add the following line:"+      , ""+      , "    amend disable"+      , ""+      , "Also, a global preferences file can be created with the name"+      , "`.darcs/defaults` in your home directory. Options present there will be"+      , "added to the repository-specific preferences if they do not conflict."])+    , ("sources", unlines+      [ "The `_darcs/prefs/sources` file is used to indicate alternative locations"+      , "from which to download patches. This file contains lines such as:"+      , ""+      , "    cache:/home/droundy/.cache/darcs"+      , "    readonly:/home/otheruser/.cache/darcs"+      , "    repo:http://darcs.net"+      , ""+      , "This would indicate that darcs should first look in"+      , "`/home/droundy/.cache/darcs` for patches that might be missing, and if"+      , "the patch is not there, it should save a copy there for future use."+      , "In that case, darcs will look in `/home/otheruser/.cache/darcs` to see if"+      , "that user might have downloaded a copy, but will not try to save a copy"+      , "there, of course. Finally, it will look in `http://darcs.net`. Note that"+      , "the `sources` file can also exist in `~/.darcs/`. Also note that the"+      , "sources mentioned in your `sources` file will be tried *before* the"+      , "repository you are pulling from. This can be useful in avoiding"+      , "downloading patches multiple times when you pull from a remote"+      , "repository to more than one local repository."+      , ""+      , "A global cache is enabled by default in your home directory. The cache"+      , "allows darcs to avoid re-downloading patches (for example, when doing a"+      , "second darcs clone of the same repository), and also allows darcs to use"+      , "hard links to reduce disk usage."+      , ""+      , "Note that the cache directory should reside on the same filesystem as"+      , "your repositories, so you may need to vary this. You can also use"+      , "multiple cache directories on different filesystems, if you have several"+      , "filesystems on which you use darcs."])+    , ("boring", unlines+      [ "The `_darcs/prefs/boring` file may contain a list of regular expressions"+      , "describing files, such as object files, that you do not expect to add to"+      , "your project. A newly created repository has a boring file that includes"+      , "many common source control, backup, temporary, and compiled files."+      , ""+      , "You may want to have the boring file under version control. To do this"+      , "you can use darcs setpref to set the value 'boringfile' to the name of"+      , "your desired boring file (e.g. `darcs setpref boringfile .boring`, where"+      , "`.boring` is the repository path of a file that has been darcs added to"+      , "your repository). The boringfile preference overrides"+      , "`_darcs/prefs/boring`, so be sure to copy that file to the boringfile."+      , ""+      , "You can also set up a 'boring' regexps file in your home directory, named"+      , "`~/.darcs/boring`, which will be used with all of your darcs repositories."+      , ""+      , "Any file not already managed by darcs and whose repository path"+      , "matches any of the boring regular expressions is"+      , "considered boring. The boring file is used to filter the files provided"+      , "to darcs add, to allow you to use a simple `darcs add newdir newdir/*`"+      , "without accidentally adding a bunch of object files. It is also used"+      , "when the `--look-for-adds` flag is given to whatsnew or record. Note"+      , "that once a file has been added to darcs, it is not considered boring,"+      , "even if it matches the boring file filter."])+    , ("binaries", unlines+      [ "The `_darcs/prefs/binaries` file may contain a list of regular"+      , "expressions describing files that should be treated as binary files rather"+      , "than text files. Darcs automatically treats files containing characters"+      , "`^Z` or `NULL` within the first 4096 bytes as being binary files."+      , "You probably will want to have the binaries file under version control."+      , "To do this you can use `darcs setpref` to set the value 'binariesfile'"+      , "to the name of your desired binaries file"+      , "(e.g. `darcs setpref binariesfile ./.binaries`, where `.binaries` is a"+      , "file that has been darcs added to your repository). As with the boring"+      , "file, you can also set up a `~/.darcs/binaries` file if you like."])+    , ("defaultrepo", unlines+      [ "Contains the URL of the default remote repository used by commands `pull`,"+      , "`push`, `send` and `optimize relink`. Darcs edits this file automatically"+      , "or when the flag `--set-default` is used."])+    , ("tmpdir", unlines+      [ "By default temporary directories are created in `/tmp`, or if that doesn't"+      , "exist, in `_darcs` (within the current repo).  This can be overridden by"+      , "specifying some other directory in the file `_darcs/prefs/tmpdir` or the"+      , "environment variable `$DARCS_TMPDIR` or `$TMPDIR`."])+    , ("prefs", unlines+      [ "Contains the preferences set by the command `darcs setprefs`."+      , "Do not edit manually."])+    ]
src/Darcs/Repository/Rebase.hs view
@@ -1,7 +1,6 @@ --  Copyright (C) 2009-2012 Ganesh Sittampalam -- --  BSD3-{-# LANGUAGE CPP #-} module Darcs.Repository.Rebase     ( RebaseJobFlags(..)     , withManualRebaseUpdate@@ -52,7 +51,7 @@     , removeFromFormat     , writeRepoFormat     )-import Darcs.Repository.Internal+import Darcs.Repository.Hashed     ( tentativelyAddPatch     , tentativelyAddPatch_     , tentativelyAddPatches_@@ -64,19 +63,17 @@     , readRepo     , UpdatePristine(..)     )-import Darcs.Repository.InternalTypes ( Repository(..) )+import Darcs.Repository.InternalTypes ( Repository, repoFormat, repoLocation )  import qualified Darcs.Util.Diff as D ( DiffAlgorithm(MyersDiff) )+import Darcs.Util.Printer ( ePutDocLn, text ) import Darcs.Util.Progress ( debugMessage )- import Darcs.Util.Tree ( Tree )  import Control.Exception ( finally )  import System.FilePath.Posix ( (</>) ) -#include "impossible.h"- -- | Some common flags that are needed to run rebase jobs. -- Normally flags are captured directly by the implementation of the specific -- job's function, but the rebase infrastructure needs to do work on the repository@@ -98,7 +95,7 @@    -> IO (Repository rt p wR wU wT2, x) withManualRebaseUpdate (RebaseJobFlags compr verb uw) r subFunc  | SRepoType SIsRebase <- singletonRepoType :: SRepoType rt- = do patches <- readTentativeRepo r+ = do patches <- readTentativeRepo r (repoLocation r)       let go :: PatchSet rt p wS wT1 -> IO (Repository rt p wR wU wT2, x)           go (PatchSet _ NilRL) = bug "trying to recontext rebase without rebase patch at head (tag)"           go (PatchSet _ (_ :<: q)) =@@ -151,9 +148,8 @@                      => Repository ('RepoType 'IsRebase) p wR wU wR                      -> RebaseJobFlags                      -> IO ()-checkSuspendedStatus repo@(Repo _ rf _ _) flags@(RebaseJobFlags compr _verb uw) = do-    allpatches <- readRepo repo-    (_, Sealed2 ps) <- return $ takeAnyRebase allpatches+checkSuspendedStatus repo flags@(RebaseJobFlags compr _verb uw) = do+    (_, Sealed2 ps) <- takeAnyRebase <$> readRepo repo     case countToEdit ps of          0 -> do                debugMessage "Removing the rebase patch file..."@@ -168,9 +164,11 @@                (rebase, _, _) <- takeHeadRebase <$> readRepo repo'                repo'' <- tentativelyRemovePatches repo' compr uw (rebase :>: NilFL)                finalizeRepositoryChanges repo'' uw compr-               writeRepoFormat (removeFromFormat RebaseInProgress rf) (darcsdir </> "format")+               writeRepoFormat+                  (removeFromFormat RebaseInProgress (repoFormat repo))+                  (darcsdir </> "format")                putStrLn "Rebase finished!"-         n -> putStrLn $ "Rebase in progress: " ++ show n ++ " suspended patches"+         n -> ePutDocLn $ text $ "Rebase in progress: " ++ show n ++ " suspended patches"  moveRebaseToEnd :: (RepoPatch p, ApplyState p ~ Tree)                 => Repository ('RepoType 'IsRebase) p wR wU wR@@ -191,14 +189,13 @@             finalizeRepositoryChanges repo'''' uw compr             return repo'''' -displaySuspendedStatus :: (RepoPatch p, ApplyState p ~ Tree) => Repository ('RepoType 'IsRebase) p wR wU wR -> IO ()+displaySuspendedStatus :: RepoPatch p => Repository ('RepoType 'IsRebase) p wR wU wR -> IO () displaySuspendedStatus repo = do-    allpatches <- readRepo repo-    (_, Sealed2 ps) <- return $ takeAnyRebase allpatches-    putStrLn $ "Rebase in progress: " ++ show (countToEdit ps) ++ " suspended patches"+    (_, Sealed2 ps) <- takeAnyRebase <$> readRepo repo+    ePutDocLn $ text $ "Rebase in progress: " ++ show (countToEdit ps) ++ " suspended patches"  maybeDisplaySuspendedStatus-  :: (RepoPatch p, ApplyState p ~ Tree)+  :: RepoPatch p   => SRebaseType rebaseType -> Repository ('RepoType rebaseType) p wR wU wR -> IO () maybeDisplaySuspendedStatus SIsRebase repo = displaySuspendedStatus repo maybeDisplaySuspendedStatus SNoRebase _    = return ()@@ -207,7 +204,9 @@                        => Repository ('RepoType 'IsRebase) p wR wU wT                        -> RebaseJobFlags                        -> IO (Repository ('RepoType 'IsRebase) p wR wU wT)-startRebaseIfNecessary repo@(Repo _ rf _ _) (RebaseJobFlags compr verb uw) =+startRebaseIfNecessary repo (RebaseJobFlags compr verb uw) =+  let rf = repoFormat repo+  in     if formatHas RebaseInProgress rf     then return repo     else do -- TODO this isn't under the repo lock, and it should be
src/Darcs/Repository/Repair.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE CPP, PatternGuards #-}- module Darcs.Repository.Repair ( replayRepository, checkIndex,                                  replayRepositoryInTemp,                                  RepositoryConsistency(..) )@@ -26,8 +24,8 @@ import Darcs.Patch.Witnesses.Sealed ( Sealed2(..), Sealed(..), unFreeLeft ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.Repair ( Repair(applyAndTryToFix) )-import Darcs.Patch.Info ( showPatchInfoUI )-import Darcs.Patch.Set ( Origin, PatchSet(..), newset2FL, newset2RL )+import Darcs.Patch.Info ( displayPatchInfo )+import Darcs.Patch.Set ( Origin, PatchSet(..), patchSet2FL, patchSet2RL ) import Darcs.Patch ( RepoPatch, IsRepoType, PrimOf, isInconsistent )  import Darcs.Repository.Flags@@ -36,10 +34,10 @@                                  RepoProperty ( HashedInventory ), formatHas ) import Darcs.Repository.Cache ( HashedDir( HashedPristineDir ) ) import Darcs.Repository.HashedIO ( cleanHashdir )-import Darcs.Repository.HashedRepo ( readHashedPristineRoot, writeAndReadPatch )-import Darcs.Repository.InternalTypes ( Repository(..), extractCache )+import Darcs.Repository.Hashed ( readHashedPristineRoot, writeAndReadPatch )+import Darcs.Repository.InternalTypes ( Repository, repoCache, repoLocation ) import Darcs.Repository.Prefs ( filetypeFunction )-import Darcs.Repository.Internal ( readRepo )+import Darcs.Repository.Hashed ( readRepo ) import Darcs.Repository.State     ( readRecorded     , readIndex@@ -52,7 +50,7 @@ import Darcs.Util.Exception ( catchall ) import Darcs.Util.Global ( darcsdir ) import Darcs.Util.Lock( rmRecursive, withTempDir )-import Darcs.Util.Printer ( Doc, putDocLn, text, RenderMode(..) )+import Darcs.Util.Printer ( Doc, putDocLn, text ) import Darcs.Util.Printer.Color ( showDoc )  import Darcs.Util.Hash( Hash(NoHash), encodeBase16 )@@ -62,9 +60,7 @@ import Darcs.Util.Tree.Plain( readPlainTree ) import Darcs.Util.Index( updateIndex ) -import qualified Data.ByteString.Char8 as BS--#include "impossible.h"+import qualified Data.ByteString.Char8 as BC  replaceInFL :: FL (PatchInfoAnd rt a) wX wY             -> [Sealed2 (WPatchInfo :||: PatchInfoAnd rt a)]@@ -79,12 +75,12 @@             => Repository rt p wR wU wT -> Compression -> FL (PatchInfoAnd rt p) Origin wR             -> TreeIO (FL (PatchInfoAnd rt p) Origin wR, Bool) applyAndFix _ _ NilFL = return (NilFL, True)-applyAndFix r@(Repo r' _ _ c) compr psin =+applyAndFix r compr psin =     do liftIO $ beginTedious k        liftIO $ tediousSize k $ lengthFL psin        (repaired, ok) <- aaf psin        liftIO $ endTedious k-       orig <- liftIO $ newset2FL `fmap` readRepo r+       orig <- liftIO $ patchSet2FL `fmap` readRepo r        return (replaceInFL orig repaired, ok)     where k = "Replaying patch"           aaf :: FL (PatchInfoAnd rt p) wW wZ -> TreeIO ([Sealed2 (WPatchInfo :||: PatchInfoAnd rt p)], Bool)@@ -95,28 +91,30 @@               Just err -> liftIO $ putDocLn err               Nothing -> return ()             let !winfp = winfo p -- assure that 'p' can be garbage collected.-            liftIO $ finishedOneIO k $ showDoc Encode $ showPatchInfoUI $ unWPatchInfo winfp+            liftIO $ finishedOneIO k $ showDoc $ displayPatchInfo $ unWPatchInfo winfp             (ps', restok) <- aaf ps             case mp' of               Nothing -> return (ps', restok)-              Just (e,pp) -> liftIO $ do putStrLn e-                                         p' <- withCurrentDirectory r' $ writeAndReadPatch c compr pp-                                         return (Sealed2 (winfp :||: p'):ps', False)+              Just (e,pp) -> liftIO $ do+                putStrLn e+                p' <- withCurrentDirectory (repoLocation r) $+                  writeAndReadPatch (repoCache r) compr pp+                return (Sealed2 (winfp :||: p'):ps', False)  data RepositoryConsistency rt p wX =     RepositoryConsistent   | BrokenPristine (Tree IO)   | BrokenPatches (Tree IO) (PatchSet rt p Origin wX) -checkUniqueness :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+checkUniqueness :: (IsRepoType rt, RepoPatch p)                 => (Doc -> IO ()) -> (Doc -> IO ()) -> Repository rt p wR wU wT -> IO () checkUniqueness putVerbose putInfo repository =     do putVerbose $ text "Checking that patch names are unique..."        r <- readRepo repository-       case hasDuplicate $ mapRL info $ newset2RL r of+       case hasDuplicate $ mapRL info $ patchSet2RL r of          Nothing -> return ()          Just pinf -> do putInfo $ text "Error! Duplicate patch name:"-                         putInfo $ showPatchInfoUI pinf+                         putInfo $ displayPatchInfo pinf                          fail "Duplicate patches found."  hasDuplicate :: Ord a => [a] -> Maybe a@@ -139,7 +137,7 @@   putVerbose $ text "Applying patches..."   patches <- readRepo repo   debugMessage "Fixing any broken patches..."-  let psin = newset2FL patches+  let psin = patchSet2FL patches       repair = applyAndFix repo compr psin    ((ps, patches_ok), newpris) <- hashedTreeIO repair emptyTree whereToReplay@@ -161,7 +159,7 @@  cleanupRepositoryReplay :: Repository rt p wR wU wT -> IO () cleanupRepositoryReplay r = do-  let c = extractCache r+  let c = repoCache r   rf <- identifyRepoFormat "."   unless (formatHas HashedInventory rf) $          rmRecursive $ darcsdir ++ "/pristine.hashed"@@ -207,8 +205,8 @@        format paths = unlines $ map (("  " ++) . anchorPath "") paths       mismatches_disp = unlines [ anchorPath "" p ++-                                    "\n    index: " ++ BS.unpack (encodeBase16 h1) ++-                                    "\n  working: " ++ BS.unpack (encodeBase16 h2)+                                    "\n    index: " ++ BC.unpack (encodeBase16 h1) +++                                    "\n  working: " ++ BC.unpack (encodeBase16 h2)                                   | (p, h1, h2) <- mismatches ]   unless (quiet || null index_extra) $          putStrLn $ "Extra items in index!\n" ++ format index_extra
src/Darcs/Repository/Resolution.hs view
@@ -15,9 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}-- module Darcs.Repository.Resolution     ( standardResolution     , externalResolution
src/Darcs/Repository/State.hs view
@@ -25,7 +25,7 @@     ( restrictSubpaths, restrictBoring, TreeFilter(..), restrictDarcsdir     , maybeRestrictSubpaths     -- * Diffs-    , unrecordedChanges, unrecordedChangesWithPatches, readPending+    , unrecordedChanges, readPending     -- * Trees     , readRecorded, readUnrecorded, readRecordedAndPending, readWorking     , readPendingAndWorking, readUnrecordedFiltered@@ -33,16 +33,17 @@     , readIndex, updateIndex, invalidateIndex, UseIndex(..), ScanKnown(..)     -- * Utilities     , filterOutConflicts-    -- * Detection of changes-    , getMovesPs, getReplaces+    -- * Pending-related functions that depend on repo state+    , addPendingDiffToPending, addToPending     ) where  import Prelude () import Darcs.Prelude -import Control.Monad( when, foldM )+import Control.Monad ( when, foldM, forM )+import Control.Monad.State ( StateT, runStateT, get, put, liftIO ) import Control.Exception ( catch, IOException )-import Data.Maybe ( isJust, fromJust )+import Data.Maybe ( isJust ) import Data.Ord ( comparing ) import Data.List ( sortBy, union, delete ) import Text.Regex( matchRegex )@@ -50,45 +51,46 @@ import System.Directory( removeFile, doesFileExist, doesDirectoryExist, renameFile ) import System.FilePath ( (</>) ) import qualified Data.ByteString as B-    ( readFile, drop, writeFile, empty, concat )+    ( ByteString, readFile, drop, writeFile, empty, concat ) import qualified Data.ByteString.Char8 as BC     ( pack, unpack, split ) import qualified Data.ByteString.Lazy as BL ( toChunks ) -import Darcs.Patch ( effect, RepoPatch, PrimOf, sortCoalesceFL, fromPrim, fromPrims-                   , PrimPatch, primIsHunk, maybeApplyToTree+import Darcs.Patch ( RepoPatch, PrimOf, sortCoalesceFL, fromPrims+                   , PrimPatch, maybeApplyToTree                    , tokreplace, forceTokReplace, move ) import Darcs.Patch.Named.Wrapped ( anonymous ) import Darcs.Patch.Apply ( ApplyState, applyToTree, effectOnFilePaths )-import Darcs.Patch.Witnesses.Ordered ( RL(..), FL(..), (+>+), mapFL_FL+import Darcs.Patch.Witnesses.Ordered ( RL(..), FL(..), (+>+)                                      , (:>)(..), reverseRL, reverseFL-                                     , mapFL, concatFL, toFL )+                                     , mapFL, concatFL, toFL, nullFL ) import Darcs.Patch.Witnesses.Eq ( EqCheck(IsEq, NotEq) )-import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )+import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP, unsafeCoercePEnd ) import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed), seal, unFreeLeft, mapSeal                                     , freeGap, emptyGap, joinGap, FreeLeft, Gap(..) )-import Darcs.Patch.Commute ( selfCommuter )+import Darcs.Patch.Commute ( selfCommuter, commuteFL ) import Darcs.Patch.CommuteFn ( commuterIdRL )-import Darcs.Patch.Permutations ( partitionConflictingFL, partitionRL )+import Darcs.Patch.Permutations ( partitionConflictingFL, genCommuteWhatWeCanRL ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, n2pia )-import Darcs.Patch.Prim.V1 () -- instances Commute Prim and PrimPatch Prim-import Darcs.Patch.Prim.V1.Core ( FilePatchType( Hunk ), Prim(..) )-import Darcs.Patch.Prim.Class ( PrimConstruct, PrimCanonize )+import Darcs.Patch.FileHunk ( FileHunk(..), IsHunk(..) ) import Darcs.Patch.TokenReplace ( breakToTokens, defaultToks ) -import Darcs.Repository.Flags ( UseIndex(..), ScanKnown(..), DiffAlgorithm(..) )+import Darcs.Repository.Flags ( UseIndex(..), ScanKnown(..), DiffAlgorithm(..)+                              , UpdateWorking(..), LookForMoves(..), LookForReplaces(..) ) import Darcs.Util.Global ( darcsdir ) -import Darcs.Repository.InternalTypes ( Repository(..) )+import Darcs.Repository.InternalTypes ( Repository, repoFormat ) import Darcs.Repository.Format(formatHas, RepoProperty(NoWorkingDir)) import qualified Darcs.Repository.Pending as Pending import Darcs.Repository.Prefs ( filetypeFunction, boringRegexps ) import Darcs.Repository.Diff ( treeDiff ) -import Darcs.Util.Path( AnchoredPath(..), anchorPath, floatPath, Name(..), fn2fp,-                   SubPath, sp2fn, filterPaths-                 , parents, replacePrefixPath, anchoredRoot-                 , toFilePath, simpleSubPath, normPath, floatSubPath )+import Darcs.Util.Path+    ( AnchoredPath(..), anchorPath, floatPath, fn2fp+    , SubPath, sp2fn, filterPaths, FileName+    , parents, replacePrefixPath, anchoredRoot+    , toFilePath, simpleSubPath, normPath, floatSubPath, makeName+    ) import Darcs.Util.Hash( Hash( NoHash ) ) import Darcs.Util.Tree( Tree, restrict, FilterTree, expand, emptyTree, overlay, find                       , ItemType(..), itemType, readBlob, modifyTree, findFile, TreeItem(..)@@ -101,23 +103,26 @@  newtype TreeFilter m = TreeFilter { applyTreeFilter :: forall tr . FilterTree tr m => tr m -> tr m } --- TODO: We wrap the pending patch inside RepoPatch here, to avoid the--- requirement to propagate an (ApplyState (PrimOf p) ~ ApplyState p)--- constraint everywhere. When we have GHC 7.2 as a minimum requirement, we can--- lift this constraint into RepoPatch superclass context and remove this hack.-readPendingLL :: (RepoPatch p, ApplyState p ~ Tree)-              => Repository rt p wR wU wT -> IO (Sealed ((FL p) wT))-readPendingLL repo = mapSeal (mapFL_FL fromPrim) `fmap` Pending.readPending repo- -- | From a repository and a list of SubPath's, construct a filter that can be -- used on a Tree (recorded or unrecorded state) of this repository. This -- constructed filter will take pending into account, so the subpaths will be -- translated correctly relative to pending move patches.-restrictSubpaths :: forall rt p m wR wU wT. (RepoPatch p, ApplyState p ~ Tree)+restrictSubpaths :: (RepoPatch p, ApplyState p ~ Tree)                  => Repository rt p wR wU wT -> [SubPath]                  -> IO (TreeFilter m) restrictSubpaths repo subpaths = do-  Sealed pending <- readPendingLL repo+  Sealed pending <- Pending.readPending repo+  restrictSubpathsAfter pending repo subpaths++-- | Like 'restrictSubpaths' but with the pending patch passed as a parameter.+-- The 'Repository' parameter is not used, we need it only to avoid+-- abiguous typing of @p@.+restrictSubpathsAfter :: (RepoPatch p, ApplyState p ~ Tree)+                      => FL (PrimOf p) wT wP+                      -> Repository rt p wR wU wT+                      -> [SubPath]+                      -> IO (TreeFilter m)+restrictSubpathsAfter pending _repo subpaths = do   let paths = map (fn2fp . sp2fn) subpaths       paths' = paths `union` effectOnFilePaths pending paths       anchored = map floatPath paths'@@ -125,28 +130,26 @@       restrictPaths = Tree.filter (filterPaths anchored)   return (TreeFilter restrictPaths) -maybeRestrictSubpaths :: forall rt p m wR wU wT. (RepoPatch p, ApplyState p ~ Tree)-                      => Repository rt p wR wU wT+maybeRestrictSubpaths :: (RepoPatch p, ApplyState p ~ Tree)+                      => FL (PrimOf p) wT wP+                      -> Repository rt p wR wU wT                       -> Maybe [SubPath]                       -> IO (TreeFilter m)-maybeRestrictSubpaths repo = maybe (return $ TreeFilter id) (restrictSubpaths repo)+maybeRestrictSubpaths pending repo =+  maybe (return $ TreeFilter id) (restrictSubpathsAfter pending repo)  -- |Is the given path in (or equal to) the _darcs metadata directory? inDarcsDir :: AnchoredPath -> Bool-inDarcsDir (AnchoredPath (Name x:_)) | x == BC.pack darcsdir = True+inDarcsDir (AnchoredPath (x:_)) | x == makeName darcsdir = True inDarcsDir _ = False --- | Construct a Tree filter that removes any boring files the Tree might have--- contained. Additionally, you should (in most cases) pass an (expanded) Tree--- that corresponds to the recorded content of the repository. This is--- important in the cases when the repository contains files that would be--- boring otherwise. (If you pass emptyTree instead, such files will simply be--- discarded by the filter, which is usually not what you want.)+-- | Construct a 'TreeFilter' that removes any boring files that are not also+-- contained in the argument 'Tree'. ----- This function is most useful when you have a plain Tree corresponding to the--- full working copy of the repository, including untracked--- files. Cf. whatsnew, record --look-for-adds.-restrictBoring :: forall m . Tree m -> IO (TreeFilter m)+-- The standard use case is for the argument to be the recorded state, possibly+-- with further patches applied, so as not to discard any files already known+-- to darcs. The result is usually applied to the full working state.+restrictBoring :: Tree m -> IO (TreeFilter m) restrictBoring guide = do   boring <- boringRegexps   let boring' p | inDarcsDir p = False@@ -160,99 +163,120 @@  -- | Construct a Tree filter that removes any darcs metadata files the -- Tree might have contained.-restrictDarcsdir :: forall m . TreeFilter m+restrictDarcsdir :: TreeFilter m restrictDarcsdir = TreeFilter $ Tree.filter $ \p _ -> not (inDarcsDir p) --- | For a repository and an optional list of paths (when Nothing, take--- everything) compute a (forward) list of prims (i.e. a patch) going from the--- recorded state of the repository (pristine) to the unrecorded state of the--- repository (the working copy + pending). When a list of paths is given, at--- least the files that live under any of these paths in either recorded or--- unrecorded will be included in the resulting patch. NB. More patches may be--- included in this list, eg. the full contents of the pending patch. This is--- usually not a problem, since selectChanges will properly filter the results--- anyway.------ This also depends on the options given: with LookForAdds, we will include--- any non-boring files (i.e. also those that do not exist in the "recorded"--- state) in the working in the "unrecorded" state, and therefore they will--- show up in the patches as addfiles.------ The IgnoreTimes option disables index usage completely -- for each file, we--- read both the unrecorded and the recorded copy and run a diff on them. This--- is very inefficient, although in extremely rare cases, the index could go--- out of sync (file is modified, index is updated and file is modified again--- within a single second).-unrecordedChanges :: forall rt p wR wU wT . (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)-                  => (UseIndex, ScanKnown, DiffAlgorithm) -> Repository rt p wR wU wT-                  -> Maybe [SubPath] -> IO (FL (PrimOf p) wT wU)-unrecordedChanges = unrecordedChangesWithPatches NilFL NilFL+{- |+For a repository and an optional list of paths (when 'Nothing', take+everything) compute a (forward) list of prims (i.e. a patch) going from the+recorded state of the repository (pristine) to the unrecorded state of the+repository (the working copy + pending). When a list of paths is given, at+least the files that live under any of these paths in either recorded or+unrecorded will be included in the resulting patch. NB. More patches may be+included in this list, eg. the full contents of the pending patch. This is+usually not a problem, since selectChanges will properly filter the results+anyway. -unrecordedChangesWithPatches :: forall rt p wR wU wT wX. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)-                  => FL (PrimOf p) wX wT -- look-for-moves patches-                  -> FL (PrimOf p) wT wT -- look-for-replaces patches-                  -> (UseIndex, ScanKnown, DiffAlgorithm) -> Repository rt p wR wU wT-                  -> Maybe [SubPath]-                  -> IO (FL (PrimOf p) wT wU)-unrecordedChangesWithPatches movPs replPs opts r paths = do-    (pending :> working) <- readPendingAndWorkingWithPatches movPs replPs opts r paths-    return $ sortCoalesceFL (pending +>+ unsafeCoerceP (movPs +>+ replPs) +>+ working)+This also depends on the options given: --- | Mostly a helper function to 'unrecordedChangesWithPatches', returning the pending---   patch plus `patches` and the subsequent diff from working as two different patches-readPendingAndWorkingWithPatches :: forall rt p wR wU wT wZ. (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)-                                 => FL (PrimOf p) wZ wT  -- look-for-moves patches-                                 -> FL (PrimOf p) wT wT  -- look-for-replaces patches-                                 -> (UseIndex, ScanKnown, DiffAlgorithm)-                                 -> Repository rt p wR wU wT-                                 -> Maybe [SubPath]-                                 -> IO ((FL (PrimOf p) :> FL (PrimOf p)) wT wU)-readPendingAndWorkingWithPatches _ _ _ r@(Repo _ rf _ _) _ | formatHas NoWorkingDir rf = do-    IsEq <- return $ workDirLessRepoWitness r-    return (NilFL :> NilFL)-readPendingAndWorkingWithPatches movPs replPs (useidx', scan, dflag) repo mbpaths = do-  let allPatches = movPs +>+ replPs-  let useidx = case allPatches of-                 NilFL -> useidx'-                 _ -> IgnoreIndex-  (all_current, Sealed (pending :: FL p wT wX)) <- readPending repo-  all_current_with_patches <- applyToTree allPatches all_current+--look-for-moves: Detect pending file moves using the index. The resulting+  patches are added to pending and taken into consideration, when filtering+  the tree according to the given path list. -  relevant <- maybeRestrictSubpaths repo mbpaths-  let getIndex = applyToTree movPs =<< I.updateIndex =<< (applyTreeFilter relevant <$> readIndex repo)-      current = applyTreeFilter relevant all_current_with_patches+--look-for-adds: Include files in the working state that do not exist in the+  recorded + pending state. -  working <- filteredWorking useidx scan relevant getIndex current-  ft <- filetypeFunction-  Sealed (diff :: FL (PrimOf p) wX wY) <- (unFreeLeft `fmap` treeDiff dflag ft current working) :: IO (Sealed (FL (PrimOf p) wX))-  IsEq <- return (unsafeCoerceP IsEq) :: IO (EqCheck wY wU)-  return (effect pending :> diff)+--include-boring: Include even boring files. -readPendingAndWorking :: forall rt p wR wU wT . (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+--look-for-replaces: Detect pending replace patches. Like detected moves,+  these are added to the pending patch. Note that, like detected moves,+  these are mere proposals for the user to consider or reject.++--ignore-times: Disables index usage completely -- for each file, we read+  both the unrecorded and the recorded copy and run a diff on them. This is+  very inefficient, although in extremely rare cases, the index could go out+  of sync (file is modified, index is updated and file is modified again+  within a single second).++  Note that use of the index is also disabled when we detect moves or+  replaces, since this implies that the index is out of date.+-}+unrecordedChanges :: (RepoPatch p, ApplyState p ~ Tree)+                  => (UseIndex, ScanKnown, DiffAlgorithm)+                  -> LookForMoves+                  -> LookForReplaces+                  -> Repository rt p wR wU wT+                  -> Maybe [SubPath] -> IO (FL (PrimOf p) wT wU)+unrecordedChanges dopts lfm lfr r paths = do+  (pending :> working) <- readPendingAndWorking dopts lfm lfr r paths+  return $ sortCoalesceFL (pending +>+ working)++-- Implementation note: it is important to do things in the right order: we+-- first have to read the pending patch, then detect moves, then detect adds,+-- then detect replaces.+readPendingAndWorking :: forall rt p wR wU wT. (RepoPatch p, ApplyState p ~ Tree)                       => (UseIndex, ScanKnown, DiffAlgorithm)+                      -> LookForMoves+                      -> LookForReplaces                       -> Repository rt p wR wU wT                       -> Maybe [SubPath]                       -> IO ((FL (PrimOf p) :> FL (PrimOf p)) wT wU)-readPendingAndWorking = readPendingAndWorkingWithPatches NilFL NilFL+readPendingAndWorking _ _ _ r _ | formatHas NoWorkingDir (repoFormat r) = do+  IsEq <- return $ workDirLessRepoWitness r+  return (NilFL :> NilFL)+readPendingAndWorking (useidx, scan, diffalg) lfm lfr repo mbpaths = do+  (pending_tree, working_tree, pending) <-+    readPendingAndMovesAndUnrecorded repo useidx scan lfm mbpaths+  (pending_tree_with_replaces, Sealed replaces) <-+    getReplaces lfr diffalg repo pending_tree working_tree+  ft <- filetypeFunction+  wrapped_diff <- treeDiff diffalg ft pending_tree_with_replaces working_tree+  case unFreeLeft wrapped_diff of+    Sealed diff -> do+      return (pending +>+ unsafeCoercePEnd replaces :> unsafeCoercePEnd diff) --- | @filteredWorking useidx scan relevant getIndex pending_tree@ reads the+readPendingAndMovesAndUnrecorded+  :: (RepoPatch p, ApplyState p ~ Tree)+  => Repository rt p wR wU wT+  -> UseIndex+  -> ScanKnown+  -> LookForMoves+  -> Maybe [SubPath]+  -> IO ( Tree IO             -- pristine with (pending + moves)+        , Tree IO             -- working+        , FL (PrimOf p) wT wU -- pending + moves+        )+readPendingAndMovesAndUnrecorded repo useidx scan lfm mbpaths = do+  (pending_tree, Sealed pending) <- readPending repo+  moves <- getMoves lfm repo mbpaths+  let pending' = pending +>+ moves+  relevant <- maybeRestrictSubpaths pending' repo mbpaths+  pending_tree' <-+    applyTreeFilter relevant <$> applyToTree moves pending_tree+  let useidx' = if nullFL moves then useidx else IgnoreIndex+  index <-+    applyToTree moves =<< I.updateIndex =<<+    applyTreeFilter relevant <$> readIndex repo+  working_tree <- filteredWorking useidx' scan relevant index pending_tree'+  return (pending_tree', working_tree, unsafeCoercePEnd pending')++-- | @filteredWorking useidx scan relevant index pending_tree@ reads the -- working tree and filters it according to options and @relevant@ file paths. -- The @pending_tree@ is understood to have @relevant@ already applied and is -- used (only) if @useidx == 'IgnoreIndex'@ and @scan == 'ScanKnown'@ to act as -- a guide for filtering the working tree.---- TODO: untangle the arguments and make this more orthogonal+-- Note that even if @useidx '==' 'IgnoreIndex'@, the index is still used+-- to avoid filtering boring files that darcs knows about (see 'restrictBoring'). filteredWorking :: UseIndex-              -> ScanKnown-              -> TreeFilter IO-              -> IO (Tree IO)-              -> Tree IO-              -> IO (Tree IO)-filteredWorking useidx scan relevant getIndex pending_tree = do-  index <- getIndex+                -> ScanKnown+                -> TreeFilter IO+                -> Tree IO+                -> Tree IO+                -> IO (Tree IO)+filteredWorking useidx scan relevant index pending_tree = do   applyTreeFilter restrictDarcsdir <$> case scan of     ScanKnown -> case useidx of-      UseIndex -> getIndex+      UseIndex -> return index       IgnoreIndex -> do         guide <- expand pending_tree         applyTreeFilter relevant . restrict guide <$> readPlainTree "."@@ -271,14 +295,14 @@ -- | Witnesses the fact that in the absence of a working directory, we -- pretend that the working dir updates magically to the tentative state. workDirLessRepoWitness :: Repository rt p wR wU wT -> EqCheck wU wT-workDirLessRepoWitness (Repo _ rf _ _)- | formatHas NoWorkingDir rf = unsafeCoerceP IsEq- | otherwise                 = NotEq+workDirLessRepoWitness r+ | formatHas NoWorkingDir (repoFormat r) = unsafeCoerceP IsEq+ | otherwise                             = NotEq  -- | Obtains a Tree corresponding to the "recorded" state of the repository: -- this is the same as the pristine cache, which is the same as the result of -- applying all the repository's patches to an empty directory.-readRecorded :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO (Tree IO)+readRecorded :: Repository rt p wR wU wT -> IO (Tree IO) readRecorded _repo = do   let h_inventory = darcsdir </> "hashed_inventory"   hashed <- doesFileExist h_inventory@@ -290,7 +314,8 @@                (pris_line:_) -> do                           let hash = decodeDarcsHash $ B.drop 9 pris_line                               size = decodeDarcsSize $ B.drop 9 pris_line-                          when (hash == NoHash) $ fail $ "Bad pristine root: " ++ show pris_line+                          when (hash == NoHash) $+                              fail $ "Bad pristine root: " ++ show pris_line                           readDarcsHashed (darcsdir </> "pristine.hashed") (size, hash)      else do have_pristine <- doesDirectoryExist $ darcsdir </> "pristine"              have_current <- doesDirectoryExist $ darcsdir </> "current"@@ -309,7 +334,8 @@ readUnrecorded :: (RepoPatch p, ApplyState p ~ Tree)                => Repository rt p wR wU wT -> Maybe [SubPath] -> IO (Tree IO) readUnrecorded repo mbpaths = do-  relevant <- maybeRestrictSubpaths repo mbpaths+  Sealed pending <- Pending.readPending repo+  relevant <- maybeRestrictSubpaths pending repo mbpaths   readIndex repo >>= I.updateIndex . applyTreeFilter relevant  -- | A variant of 'readUnrecorded' that takes the UseIndex and ScanKnown@@ -320,28 +346,25 @@                        => Repository rt p wR wU wT                        -> UseIndex                        -> ScanKnown+                       -> LookForMoves                        -> Maybe [SubPath] -> IO (Tree IO)-readUnrecordedFiltered repo useidx scan mbpaths = do-  (all_current, _) <- readPending repo -- we have no need for the pending patch-  relevant <- maybeRestrictSubpaths repo mbpaths-  let getIndex = I.updateIndex =<< (applyTreeFilter relevant <$> readIndex repo)-      current = applyTreeFilter relevant all_current-  filteredWorking useidx scan relevant getIndex current+readUnrecordedFiltered repo useidx scan lfm mbpaths = do+  (_, working_tree, _) <-+    readPendingAndMovesAndUnrecorded repo useidx scan lfm mbpaths+  return working_tree  -- | Obtains a Tree corresponding to the complete working copy of the -- repository (modified and non-modified files). readWorking :: IO (Tree IO)-readWorking = expand =<< (nodarcs `fmap` readPlainTree ".")-  where nodarcs = Tree.filter (\(AnchoredPath (Name x:_)) _ -> x /= BC.pack darcsdir)+readWorking = expand =<< (applyTreeFilter restrictDarcsdir <$> readPlainTree ".") --- | Obtains the same Tree as 'readRecorded' would but with the additional side---   effect of reading/checking the pending patch.+-- | Obtains the recorded 'Tree' with the pending patch applied. readRecordedAndPending :: (RepoPatch p, ApplyState p ~ Tree)                        => Repository rt p wR wU wT -> IO (Tree IO) readRecordedAndPending repo = fst `fmap` readPending repo --- | Obtains a Tree corresponding to the recorded state of the repository---   and a pending patch to go with it. The pending patch should start at the+-- | Obtains the recorded 'Tree' with the pending patch applied, plus+--   the pending patch itself. The pending patch should start at the --   recorded state (we even verify that it applies, and degrade to --   renaming pending and starting afresh if it doesn't), but we've set to --   say it starts at the tentative state.@@ -349,84 +372,99 @@ --   Question (Eric Kow) Is this a bug? Darcs.Repository.Pending.readPending --   says it is readPending :: (RepoPatch p, ApplyState p ~ Tree)-            => Repository rt p wR wU wT -> IO (Tree IO, Sealed (FL p wT))-readPending repo =-  do Sealed pending <- readPendingLL repo-     pristine <- readRecorded repo-     catch ((\t -> (t, seal pending)) `fmap` applyToTree pending pristine) $ \ (err :: IOException) -> do+            => Repository rt p wR wU wT+            -> IO (Tree IO, Sealed (FL (PrimOf p) wT))+readPending repo = do+  pristine <- readRecorded repo+  Sealed pending <- Pending.readPending repo+  catch ((\t -> (t, seal pending)) <$> applyToTree pending pristine) $+    \(err :: IOException) -> do        putStrLn $ "Yikes, pending has conflicts! " ++ show err        putStrLn "Stashing the buggy pending as _darcs/patches/pending_buggy"        renameFile (darcsdir </> "patches" </> "pending")                   (darcsdir </> "patches" </> "pending_buggy")        return (pristine, seal NilFL) +index_file, index_invalid :: FilePath+index_file = darcsdir </> "index"+index_invalid = darcsdir </> "index_invalid"+ -- | Mark the existing index as invalid. This has to be called whenever the -- listing of pristine changes and will cause darcs to update the index next -- time it tries to read it. (NB. This is about files added and removed from -- pristine: changes to file content in either pristine or working are handled -- transparently by the index reading code.) invalidateIndex :: t -> IO ()-invalidateIndex _ = B.writeFile (darcsdir </> "index_invalid") B.empty+invalidateIndex _ = B.writeFile index_invalid B.empty -readIndex :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO I.Index+readIndex :: (RepoPatch p, ApplyState p ~ Tree)+          => Repository rt p wR wU wT -> IO I.Index readIndex repo = do-  invalid <- doesFileExist $ darcsdir </> "index_invalid"-  exists <- doesFileExist $ darcsdir </> "index"-  formatValid <- if exists-                     then I.indexFormatValid $ darcsdir </> "index"-                     else return True-  when (exists && not formatValid) $ removeFile $ darcsdir </> "index"+  (invalid, exists, formatValid) <- checkIndex   if not exists || invalid || not formatValid      then do pris <- readRecordedAndPending repo-             idx <- I.updateIndexFrom (darcsdir </> "index") darcsTreeHash pris-             when invalid $ removeFile $ darcsdir </> "index_invalid"+             idx <- I.updateIndexFrom index_file darcsTreeHash pris+             when invalid $ removeFile index_invalid              return idx-     else I.readIndex (darcsdir </> "index") darcsTreeHash+     else I.readIndex index_file darcsTreeHash -updateIndex :: (RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wT -> IO ()+updateIndex :: (RepoPatch p, ApplyState p ~ Tree)+            => Repository rt p wR wU wT -> IO () updateIndex repo = do-    invalid <- doesFileExist $ darcsdir </> "index_invalid"-    exists <- doesFileExist $ darcsdir </> "index"-    formatValid <- if exists-                     then I.indexFormatValid $ darcsdir </> "index"+  (invalid, _, _) <- checkIndex+  pris <- readRecordedAndPending repo+  _ <- I.updateIndexFrom index_file darcsTreeHash pris+  when invalid $ removeFile index_invalid++checkIndex :: IO (Bool, Bool, Bool)+checkIndex = do+  invalid <- doesFileExist $ index_invalid+  exists <- doesFileExist index_file+  formatValid <- if exists+                     then I.indexFormatValid index_file                      else return True-    when (exists && not formatValid) $ removeFile $ darcsdir </> "index"-    pris <- readRecordedAndPending repo-    _ <- I.updateIndexFrom (darcsdir </> "index") darcsTreeHash pris-    when invalid $ removeFile $ darcsdir </> "index_invalid"+  when (exists && not formatValid) $ removeFile index_file+  return (invalid, exists, formatValid)  -- |Remove any patches (+dependencies) from a sequence that -- conflict with the recorded or unrecorded changes in a repo-filterOutConflicts :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)-     => RL (PatchInfoAnd rt p) wX wT                  -- ^Recorded patches from repository, starting from-                                                   -- same context as the patches to filter-     -> Repository rt p wR wU wT                      -- ^Repository itself, used for grabbing unrecorded changes-     -> FL (PatchInfoAnd rt p) wX wZ                  -- ^Patches to filter-     -> IO (Bool, Sealed (FL (PatchInfoAnd rt p) wX)) -- ^(True iff any patches were removed, possibly filtered patches)+filterOutConflicts+  :: (RepoPatch p, ApplyState p ~ Tree)+  => RL (PatchInfoAnd rt p) wX wT -- ^Recorded patches from repository, starting from+                                  --  same context as the patches to filter+  -> Repository rt p wR wU wT     -- ^Repository itself, used for grabbing+                                  --  unrecorded changes+  -> FL (PatchInfoAnd rt p) wX wZ -- ^Patches to filter+  -> IO (Bool, Sealed (FL (PatchInfoAnd rt p) wX))+                                  -- ^True iff any patches were removed,+                                  --  possibly filtered patches filterOutConflicts us repository them      = do let commuter = commuterIdRL selfCommuter           unrec <- fmap n2pia . anonymous . fromPrims-                     =<< unrecordedChanges (UseIndex, ScanKnown, MyersDiff) repository Nothing+                     =<< unrecordedChanges (UseIndex, ScanKnown, MyersDiff)+                          NoLookForMoves NoLookForReplaces repository Nothing           them' :> rest <- return $ partitionConflictingFL commuter them (us :<: unrec)           return (check rest, Sealed them')   where check :: FL p wA wB -> Bool         check NilFL = False         check _ = True --- |Automatically detect file moves using the index-getMovesPs :: forall rt p wR wU wB prim.-              (PrimConstruct prim, PrimCanonize prim, RepoPatch p,-               ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)-           => Repository rt p wR wU wR-           -> Maybe [SubPath]-           -> IO (FL prim wB wB)-getMovesPs repository files = mkMovesFL <$> getMovedFiles repository files+-- | Automatically detect file moves using the index.+-- TODO: This function lies about the witnesses.+getMoves :: forall rt p wR wU wT wB prim.+            (RepoPatch p, ApplyState p ~ Tree, prim ~ PrimOf p)+         => LookForMoves+         -> Repository rt p wR wU wT+         -> Maybe [SubPath]+         -> IO (FL prim wB wB)+getMoves NoLookForMoves _ _ = return NilFL+getMoves YesLookForMoves repository files =+    mkMovesFL <$> getMovedFiles repository files   where     mkMovesFL [] = NilFL     mkMovesFL ((a,b,_):xs) = move (anchorPath "" a) (anchorPath "" b) :>: mkMovesFL xs -    getMovedFiles :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)-                  => Repository rt p wR wU wR+    getMovedFiles :: Repository rt p wR wU wT                   -> Maybe [SubPath]                   -> IO [(AnchoredPath, AnchoredPath, ItemType)]     getMovedFiles repo fs = do@@ -439,19 +477,23 @@         new <- sortBy (comparing snd) <$>                  (addIDs . map (\(a,b) -> (a, itemType b)) . Tree.list  =<<                    expand =<< applyTreeFilter nonboring <$> readPlainTree ".")-        let match (x:xs) (y:ys) | snd x > snd y = match (x:xs) ys-                                | snd x < snd y = match xs (y:ys)-                                | snd (fst x) /= snd (fst y) = match xs ys-                                | otherwise = (fst (fst x), fst (fst y), snd (fst x)):match xs ys+        let match (x:xs) (y:ys)+              | snd x > snd y = match (x:xs) ys+              | snd x < snd y = match xs (y:ys)+              | snd (fst x) /= snd (fst y) = match xs ys+              | otherwise = (fst (fst x), fst (fst y), snd (fst x)):match xs ys             match _ _ = []             movedfiles = match old new-            fmovedfiles = case fs of-                            Nothing -> movedfiles-                            Just subpath -> filter (\(f1,f2,_) -> any (`elem` selfiles) [f1,f2]) movedfiles-                                               where selfiles = map (floatPath . toFilePath) subpath+            fmovedfiles =+              case fs of+                Nothing -> movedfiles+                Just subpath ->+                  filter (\(f1, f2, _) -> any (`elem` selfiles) [f1, f2]) movedfiles+                  where selfiles = map (floatPath . toFilePath) subpath         return (resolve fmovedfiles) -    resolve :: [(AnchoredPath, AnchoredPath, ItemType)] -> [(AnchoredPath, AnchoredPath, ItemType)]+    resolve :: [(AnchoredPath, AnchoredPath, ItemType)]+            -> [(AnchoredPath, AnchoredPath, ItemType)]     resolve xs = fixPaths $ sortMoves $ deleteCycles xs       where         -- Input relation is left-and-right-unique. Makes cycle detection easier.@@ -495,66 +537,120 @@ -- | Search for possible replaces between the recordedAndPending state -- and the unrecorded (or working) state. Return a Sealed FL list of -- replace patches to be applied to the recordedAndPending state.-getReplaces :: forall rt p wR wU wT wX. (RepoPatch p, ApplyState p ~ Tree,-                          ApplyState (PrimOf p) ~ Tree, wX ~ wR)-                       => (UseIndex, ScanKnown, DiffAlgorithm)-                       -> Repository rt p wR wU wT-                       -> Maybe [SubPath]-                       -> IO (Sealed (FL (PrimOf p) wX))-getReplaces (useindex, scan, dopts) repo files = do-    relevant <- maybeRestrictSubpaths repo files-    working <- readUnrecordedFiltered repo useindex scan files-    pending <- applyTreeFilter relevant <$> readRecordedAndPending repo+getReplaces :: forall rt p wR wU wT+             . (RepoPatch p, ApplyState p ~ Tree)+            => LookForReplaces+            -> DiffAlgorithm+            -> Repository rt p wR wU wT+            -> Tree IO -- ^ pending tree (including possibly detected moves)+            -> Tree IO -- ^ working tree+            -> IO (Tree IO, -- new pending tree+                   Sealed (FL (PrimOf p) wU))+getReplaces NoLookForReplaces _ _ pending _ = return (pending, Sealed NilFL)+getReplaces YesLookForReplaces diffalg _repo pending working = do     ftf <- filetypeFunction--    Sealed changes <- unFreeLeft <$> treeDiff dopts ftf pending working-    _ :> hunks <- return $ partitionRL primIsHunk $ reverseFL changes-    let allModifiedTokens = concat $ mapFL modifiedTokens (reverseRL hunks)+    Sealed changes <- unFreeLeft <$> treeDiff diffalg ftf pending working+    let allModifiedTokens = concat $ mapFL modifiedTokens changes         replaces = rmInvalidReplaces allModifiedTokens-    mapSeal concatFL . toFL <$>-        mapM (\(f,a,b) -> doReplace defaultToks pending-                            (fromJust $ simpleSubPath $ fn2fp $ normPath f)-                            (BC.unpack a) (BC.unpack b)) replaces-  where -- get individual tokens that have been modified-        modifiedTokens (FP f (Hunk _ old new)) = -- old and new are list of lines (= 1 bytestring per line)-          map (\(a,b) -> (f, a, b)) (concatMap checkModified $-             filter (\(a,b) -> length a == length b) -- only keep lines with same number of tokens-                  $ zip (map breakToTokens old) (map breakToTokens new))-        modifiedTokens _ = error "modifiedTokens: Not Hunk patch"+    (patches, new_pending) <-+      flip runStateT pending $+        forM replaces $ \(f,a,b) ->+          doReplace defaultToks+            (fromJust $ simpleSubPath $ fn2fp $ normPath f)+            (BC.unpack a) (BC.unpack b)+    return (new_pending, mapSeal concatFL $ toFL patches)+  where+    modifiedTokens :: PrimOf p wX wY -> [(FileName, B.ByteString, B.ByteString)]+    modifiedTokens p = case isHunk p of+      Just (FileHunk f _ old new) ->+        map (\(a,b) -> (f, a, b)) (concatMap checkModified $+          filter (\(a,b) -> length a == length b) -- only keep lines with same number of tokens+            $ zip (map breakToTokens old) (map breakToTokens new))+      Nothing -> [] -        -- from a pair of token lists, create a pair of modified token lists-        checkModified = filter (\(a,b) -> a/=b) . uncurry zip+    -- from a pair of token lists, create a pair of modified token lists+    checkModified = filter (\(a,b) -> a/=b) . uncurry zip -        rmInvalidReplaces [] = []-        rmInvalidReplaces ((f,old,new):rs)-          | any (\(f',a,b) -> f' == f && old == a && b /= new) rs = -- inconsistency detected-              rmInvalidReplaces $ filter (\(f'',a',_) -> f'' /= f || a' /= old) rs-        rmInvalidReplaces (r:rs) = r:rmInvalidReplaces (filter (/=r) rs)+    rmInvalidReplaces [] = []+    rmInvalidReplaces ((f,old,new):rs)+      | any (\(f',a,b) -> f' == f && old == a && b /= new) rs =+          -- inconsistency detected+          rmInvalidReplaces $ filter (\(f'',a',_) -> f'' /= f || a' /= old) rs+    rmInvalidReplaces (r:rs) = r:rmInvalidReplaces (filter (/=r) rs) -        doReplace toks pend f old new = do-            let maybeReplace p = isJust <$> maybeApplyToTree replacePatch p-            pendReplaced <- maybeReplace pend-            if pendReplaced-                then return $ joinGap (:>:) (freeGap replacePatch) (emptyGap NilFL)-                else getForceReplace f toks pend old new-          where-            replacePatch = tokreplace (toFilePath f) toks old new+    doReplace toks f old new = do+        pend <- get+        mpend' <- liftIO $ maybeApplyToTree replacePatch pend+        case mpend' of+          Nothing -> getForceReplace f toks old new+          Just pend' -> do+            put pend'+            return $ joinGap (:>:) (freeGap replacePatch) (emptyGap NilFL)+      where+        replacePatch = tokreplace (toFilePath f) toks old new -        getForceReplace :: PrimPatch prim => SubPath -> String -> Tree IO -> String -> String-                        -> IO (FreeLeft (FL prim))-        getForceReplace f toks tree old new = do-            let path = floatSubPath f-            -- It would be nice if we could fuse the two traversals here, that is,-            -- expandPath and findFile. OTOH it is debatable whether adding a new-            -- effectful version of findFile to Darcs.Util.Tree is justified.-            expandedTree <- expandPath tree path-            content <- case findFile expandedTree path of-              Just blob -> readBlob blob-              Nothing -> error $ "getForceReplace: not in tree: " ++ show path-            let newcontent = forceTokReplace toks (BC.pack new) (BC.pack old)-                                (B.concat $ BL.toChunks content)-                tree' = modifyTree expandedTree path . Just . File $ makeBlobBS newcontent-            ftf <- filetypeFunction-            normaliseNewTokPatch <- treeDiff dopts ftf expandedTree tree'-            return . joinGap (+>+) normaliseNewTokPatch $ freeGap $-                tokreplace (toFilePath f) toks old new :>: NilFL+    getForceReplace :: (PrimPatch prim, ApplyState prim ~ Tree)+                    => SubPath -> String -> String -> String+                    -> StateT (Tree IO) IO (FreeLeft (FL prim))+    getForceReplace f toks old new = do+        let path = floatSubPath f+        -- the tree here is the "current" pending state+        tree <- get+        -- It would be nice if we could fuse the two traversals here, that is,+        -- expandPath and findFile. OTOH it is debatable whether adding a new+        -- effectful version of findFile to Darcs.Util.Tree is justified.+        expandedTree <- liftIO $ expandPath tree path+        content <- case findFile expandedTree path of+          Just blob -> liftIO $ readBlob blob+          Nothing -> bug $ "getForceReplace: not in tree: " ++ show path+        let newcontent = forceTokReplace toks (BC.pack new) (BC.pack old)+                            (B.concat $ BL.toChunks content)+            tree' = modifyTree expandedTree path . Just . File $ makeBlobBS newcontent+        ftf <- liftIO $ filetypeFunction+        normaliseNewTokPatch <- liftIO $ treeDiff diffalg ftf expandedTree tree'+        -- make sure we can apply them to the pending state+        patches <- return $ joinGap (+>+) normaliseNewTokPatch $ freeGap $+            tokreplace (toFilePath f) toks old new :>: NilFL+        mtree'' <- case unFreeLeft patches of+            Sealed ps -> liftIO $ maybeApplyToTree ps tree+        case mtree'' of+            Nothing -> bug "getForceReplace: unable to apply detected force replaces"+            Just tree'' -> do+                put tree''+                return patches+++-- | Add an 'FL' of patches started from the pending state to the pending patch.+-- TODO: add witnesses for pending so we can make the types precise: currently+-- the passed patch can be applied in any context, not just after pending.+addPendingDiffToPending :: (RepoPatch p, ApplyState p ~ Tree)+                          => Repository rt p wR wU wT -> UpdateWorking+                          -> FreeLeft (FL (PrimOf p)) -> IO ()+addPendingDiffToPending _ NoUpdateWorking  _ = return ()+addPendingDiffToPending repo uw@YesUpdateWorking newP = do+    (toPend :> _) <-+        readPendingAndWorking (UseIndex, ScanKnown, MyersDiff)+          NoLookForMoves NoLookForReplaces repo Nothing+    invalidateIndex repo+    case unFreeLeft newP of+        (Sealed p) -> do recordedState <- readRecorded repo+                         Pending.makeNewPending repo uw (toPend +>+ p) recordedState++-- | Add an 'FL' of patches starting from the working state to the pending patch,+-- including as much extra context as is necessary (context meaning+-- dependencies), by commuting the patches to be added past as much of the+-- changes between pending and working as is possible, and including anything+-- that doesn't commute, and the patch itself in the new pending patch.+addToPending :: (RepoPatch p, ApplyState p ~ Tree)+             => Repository rt p wR wU wT -> UpdateWorking+             -> FL (PrimOf p) wU wY -> IO ()+addToPending _ NoUpdateWorking  _ = return ()+addToPending repo uw@YesUpdateWorking p = do+   (toPend :> toUnrec) <- readPendingAndWorking (UseIndex, ScanKnown, MyersDiff)+      NoLookForMoves NoLookForReplaces repo Nothing+   invalidateIndex repo+   case genCommuteWhatWeCanRL commuteFL (reverseFL toUnrec :> p) of+       (toP' :> p'  :> _excessUnrec) -> do+           recordedState <- readRecorded repo+           Pending.makeNewPending repo uw+            (toPend +>+ reverseRL toP' +>+ p') recordedState
src/Darcs/Repository/Test.hs view
@@ -35,30 +35,24 @@ import Darcs.Util.Path ( AbsolutePath ) import Darcs.Util.Prompt ( askUser ) import Darcs.Repository.Prefs ( getPrefval )-import Darcs.Patch-    ( RepoPatch ) -import Darcs.Repository.Internal-    ( setScriptsExecutable-    , withTentative-    )+import Darcs.Repository.Hashed ( withTentative )+import Darcs.Repository.Working ( setScriptsExecutable ) import Darcs.Repository.Flags     ( LeaveTestDir(..)     , Verbosity(..)     , SetScriptsExecutable(..)     , RunTest (..)+    , HookConfig (..)     ) import Darcs.Repository.InternalTypes-    ( Repository(..) )+    ( Repository, repoLocation ) import Darcs.Util.Progress ( debugMessage ) import Darcs.Util.Lock     ( withTempDir     , withPermDir     )-import Darcs.Patch.Apply ( ApplyState )-import Darcs.Util.Tree ( Tree ) - getTest :: Verbosity -> IO (IO ExitCode) getTest verb =  let putInfo s = when (verb /= Quiet) $ putStr s@@ -71,8 +65,8 @@      putInfo "Running test...\n"      runTest testcode putInfo -runPosthook :: Maybe String -> Bool -> Verbosity -> AbsolutePath -> IO ExitCode-runPosthook mPostHook askPostHook verb repodir+runPosthook :: HookConfig -> Verbosity -> AbsolutePath -> IO ExitCode+runPosthook (HookConfig mPostHook askPostHook) verb repodir     = do ph <- getPosthook mPostHook askPostHook          withCurrentDirectory repodir $ runHook verb "Posthook" ph @@ -91,8 +85,8 @@                 _ -> putStrLn "Posthook cancelled..." >> return Nothing       else return $ Just command -runPrehook :: Maybe String -> Bool -> Verbosity -> AbsolutePath -> IO ExitCode-runPrehook mPreHookCmd askPreHook verb repodir =+runPrehook :: HookConfig -> Verbosity -> AbsolutePath -> IO ExitCode+runPrehook (HookConfig mPreHookCmd askPreHook) verb repodir =     do ph <- getPrehook mPreHookCmd askPreHook        withCurrentDirectory repodir $ runHook verb "Prehook" ph @@ -121,8 +115,7 @@          else hPutStrLn stderr $ cname++" failed!"        return ec -testTentative :: (RepoPatch p, ApplyState p ~ Tree)-              => Repository rt p wR wU wT+testTentative :: Repository rt p wR wU wT               -> RunTest               -> LeaveTestDir               -> SetScriptsExecutable@@ -139,8 +132,7 @@     return ec  -testAny :: RepoPatch p-        => (Repository rt p wR wU wT+testAny :: (Repository rt p wR wU wT             -> ((AbsolutePath -> IO ExitCode) -> IO ExitCode)             -> (AbsolutePath -> IO ExitCode) -> IO ExitCode            )@@ -150,10 +142,12 @@         -> SetScriptsExecutable         -> Verbosity         -> IO ExitCode-testAny withD repository@(Repo dir _ _ _) doRunTest ltd sse verb =+testAny withD repository doRunTest ltd sse verb =     debugMessage "Considering whether to test..." >>-    if doRunTest == NoRunTest then return ExitSuccess else withCurrentDirectory dir $-    do let putInfo = if verb == Quiet then const (return ()) else putStrLn+    if doRunTest == NoRunTest+      then return ExitSuccess+      else withCurrentDirectory (repoLocation repository) $ do+       let putInfo = if verb == Quiet then const (return ()) else putStrLn        debugMessage "About to run test if it exists."        testline <- getPrefval "test"        case testline of
+ src/Darcs/Repository/Working.hs view
@@ -0,0 +1,75 @@+module Darcs.Repository.Working+    ( applyToWorking+    , setScriptsExecutable+    , setScriptsExecutablePatches+    )  where++import Control.Monad ( when, unless, filterM )+import System.Directory ( doesFileExist )++import qualified Data.ByteString as B ( readFile+                                      , isPrefixOf+                                      )+import qualified Data.ByteString.Char8 as BC (pack)++import Darcs.Util.File ( withCurrentDirectory )+import Darcs.Util.Progress ( debugMessage )+import Darcs.Util.Workaround ( setExecutable )+import Darcs.Util.Tree ( Tree )+import Darcs.Util.Path ( anchorPath )+import qualified Darcs.Util.Tree as Tree++import Darcs.Patch ( RepoPatch, apply, listTouchedFiles )+import Darcs.Patch.Apply ( ApplyState )+import Darcs.Patch.Prim ( PrimOf )+import Darcs.Patch.Witnesses.Ordered+    ( FL(..) )+import Darcs.Patch.Dummy ( DummyPatch )+import Darcs.Patch.Inspect ( PatchInspect )++import Darcs.Repository.Format ( RepoProperty( NoWorkingDir ), formatHas )+import Darcs.Repository.Flags  ( Verbosity(..) )+import Darcs.Repository.InternalTypes+    ( Repository+    , repoFormat+    , repoLocation+    , coerceU )+import Darcs.Repository.ApplyPatches ( runTolerantly, runSilently )+import Darcs.Repository.State ( readWorking )++applyToWorking :: (ApplyState p ~ Tree, RepoPatch p)+               => Repository rt p wR wU wT -> Verbosity -> FL (PrimOf p) wU wY+               -> IO (Repository rt p wR wY wT)+applyToWorking repo verb patch =+  do+    unless (formatHas NoWorkingDir (repoFormat repo)) $+      withCurrentDirectory (repoLocation repo) $+        if verb == Quiet+          then runSilently $ apply patch+          else runTolerantly $ apply patch+    return $ coerceU repo++-- | Sets scripts in or below the current directory executable.+--   A script is any file that starts with the bytes '#!'.+--   This is used for --set-scripts-executable.+setScriptsExecutable_ :: PatchInspect p => Maybe (p wX wY) -> IO ()+setScriptsExecutable_ pw = do+    debugMessage "Making scripts executable"+    tree <- readWorking+    paths <- case pw of+          Just ps -> filterM doesFileExist $ listTouchedFiles ps+          Nothing -> return [ anchorPath "." p | (p, Tree.File _) <- Tree.list tree ]+    let setExecutableIfScript f =+              do contents <- B.readFile f+                 when (BC.pack "#!" `B.isPrefixOf` contents) $ do+                   debugMessage ("Making executable: " ++ f)+                   setExecutable f True+    mapM_ setExecutableIfScript paths++setScriptsExecutable :: IO ()+setScriptsExecutable = setScriptsExecutable_ (Nothing :: Maybe (FL DummyPatch wX wY))++setScriptsExecutablePatches :: PatchInspect p => p wX wY -> IO ()+setScriptsExecutablePatches = setScriptsExecutable_ . Just++
src/Darcs/UI/ApplyPatches.hs view
@@ -11,22 +11,24 @@ import Control.Exception                  ( catch, fromException, SomeException, throwIO ) import Control.Monad ( when, unless )+import qualified Data.ByteString.Char8 as BC  import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd ) import Darcs.Util.SignalHandler ( withSignalsBlocked ) import Darcs.UI.Commands     ( putVerbose     , putInfo-    , printDryRunMessageAndExit     , setEnvDarcsPatches     )+import Darcs.UI.Commands.Util ( printDryRunMessageAndExit ) import Darcs.UI.CommandsAux ( checkPaths ) import Darcs.UI.Flags-    ( DarcsFlag, verbosity, compression, reorder, allowConflicts, externalMerge+    ( DarcsFlag, verbosity, compress, reorder, allowConflicts, externalMerge     , wantGuiPause, diffingOpts, setScriptsExecutable, isInteractive, testChanges-    , hasXmlOutput, getReply, getCc, getSendmailCmd, hasSummary, dryRun+    , xmlOutput, reply, getCc, getSendmailCmd, dryRun     ) import qualified Darcs.UI.Options.All as O+import Darcs.UI.Options ( (?) ) import Darcs.UI.Commands.Util ( testTentativeAndMaybeExit ) import Darcs.Repository.Flags ( UpdateWorking(..) ) import Darcs.Repository@@ -38,7 +40,7 @@     , setScriptsExecutablePatches     ) import Darcs.Repository.Job ( RepoJob(RepoJob) )-import Darcs.Patch ( RepoPatch, RepoType, IsRepoType, description, PrimOf )+import Darcs.Patch ( RepoPatch, RepoType, IsRepoType, description ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.Witnesses.Ordered     ( FL, mapFL, nullFL )@@ -63,7 +65,7 @@         -> [DarcsFlag]         -> (forall rt p wR wU                . ( IsRepoType rt, ApplierRepoTypeConstraint pa rt-                 , RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree+                 , RepoPatch p, ApplyState p ~ Tree                  )               => (PatchProxy p -> Repository rt p wR wU wR -> IO ()))         -> RepoJob ()@@ -71,7 +73,7 @@     applyPatches         :: forall rt p wR wU wT wX wZ          . ( ApplierRepoTypeConstraint pa rt, IsRepoType rt-           , RepoPatch p, ApplyState (PrimOf p) ~ Tree, ApplyState p ~ Tree+           , RepoPatch p, ApplyState p ~ Tree            )         => pa         -> PatchProxy p@@ -91,18 +93,18 @@  standardApplyPatches            :: forall rt p wR wU wT wX wZ-            . (IsRepoType rt, RepoPatch p, ApplyState (PrimOf p) ~ Tree, ApplyState p ~ Tree)+            . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)            => String -> [DarcsFlag] -> String -> Repository rt p wR wU wT            -> FL (PatchInfoAnd rt p) wX wT -> FL (PatchInfoAnd rt p) wX wZ -> IO () standardApplyPatches cmdName opts from_whom repository us' to_be_applied = do    printDryRunMessageAndExit cmdName-      (verbosity opts)-      (hasSummary O.NoSummary opts)-      (dryRun opts)-      (hasXmlOutput opts)+      (verbosity ? opts)+      (O.summary ? opts)+      (dryRun ? opts)+      (xmlOutput ? opts)       (isInteractive True opts)       to_be_applied-   when (nullFL to_be_applied && reorder opts == O.NoReorder) $ do +   when (nullFL to_be_applied && reorder ? opts == O.NoReorder) $ do             putStrLn $ "You don't want to " ++ cmdName ++ " any patches, so I'm exiting!"            exitSuccess    checkPaths opts to_be_applied@@ -113,30 +115,30 @@         setEnvDarcsPatches to_be_applied     Sealed pw <- tentativelyMergePatches repository cmdName                          (allowConflicts opts) YesUpdateWorking-                         (externalMerge opts) (wantGuiPause opts)-                         (compression opts) (verbosity opts)-                         (reorder opts) (diffingOpts opts)+                         (externalMerge ? opts) (wantGuiPause opts)+                         (compress ? opts) (verbosity ? opts)+                         (reorder ? opts) (diffingOpts opts)                          us' to_be_applied     invalidateIndex repository     testTentativeAndMaybeExit repository-         (verbosity opts)-         (testChanges opts)-         (setScriptsExecutable opts)+         (verbosity ? opts)+         (testChanges ? opts)+         (setScriptsExecutable ? opts)          (isInteractive True opts)          "those patches do not pass the tests." (cmdName ++ " them") Nothing-    withSignalsBlocked $ do finalizeRepositoryChanges repository YesUpdateWorking (compression opts)-                            _ <- applyToWorking repository (verbosity opts) pw `catch` \(e :: SomeException) ->+    withSignalsBlocked $ do finalizeRepositoryChanges repository YesUpdateWorking (compress ? opts)+                            _ <- applyToWorking repository (verbosity ? opts) pw `catch` \(e :: SomeException) ->                                 fail ("Error applying patch to working dir:\n" ++ show e)-                            when (setScriptsExecutable opts == O.YesSetScriptsExecutable) $+                            when (setScriptsExecutable ? opts == O.YesSetScriptsExecutable) $                               setScriptsExecutablePatches pw                             return ()-    case (nullFL to_be_applied, reorder opts == O.Reorder) of+    case (nullFL to_be_applied, reorder ? opts == O.Reorder) of                 (True,True)  -> putInfo opts $ text $ "Nothing to " ++ cmdName ++ ", finished reordering."                 (False,True) -> putInfo opts $ text $ "Finished " ++ cmdName ++ "ing and reordering."                 _            -> putInfo opts $ text $ "Finished " ++ cmdName ++ "ing."  redirectOutput :: [DarcsFlag] -> String -> IO () -> IO ()-redirectOutput opts to doit = case getReply opts of+redirectOutput opts to doit = case reply ? opts of     Nothing -> doit     Just from -> withStdoutTemp $ \tempf -> doitAndCleanup `catch` sendit tempf from   where@@ -171,7 +173,7 @@ -- an email.  sanitizeFile :: FilePath -> IO String-sanitizeFile f = sanitize `fmap` readBinFile f+sanitizeFile f = sanitize . BC.unpack <$> readBinFile f     where sanitize s = wash $ remove_backspaces "" s           wash ('\000':s) = "\\NUL" ++ wash s           wash ('\026':s) = "\\EOF" ++ wash s
src/Darcs/UI/Commands.hs view
@@ -15,12 +15,13 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} module Darcs.UI.Commands     ( CommandControl ( CommandData, HiddenCommand, GroupName )     , DarcsCommand ( .. )     , WrappedCommand(..)     , wrappedCommandName+    , wrappedCommandDescription     , commandAlias     , commandStub     , commandOptions@@ -28,12 +29,7 @@     , withStdOpts     , disambiguateCommands     , CommandArgs(..)-    , getCommandHelp-    , getCommandMiniHelp     , getSubcommands-    , usage-    , usageHelper-    , subusage     , extractCommands     , extractAllCommands     , normalCommand@@ -46,7 +42,6 @@     , putWarning     , putVerboseWarning     , abortRun-    , printDryRunMessageAndExit     , setEnvDarcsPatches     , setEnvDarcsFiles     , defaultRepo@@ -62,50 +57,41 @@ import Prelude hiding ( (^) ) import Control.Monad ( when, unless ) import Data.List ( sort, isPrefixOf )-import Data.Maybe ( catMaybes ) import Darcs.Util.Tree ( Tree ) import System.Console.GetOpt ( OptDescr )-import System.Exit ( exitSuccess ) import System.IO ( stderr )-#ifndef WIN32-import System.Posix.Env ( setEnv )-+import System.IO.Error ( catchIOError )+import System.Environment ( setEnv ) import Darcs.Patch ( listTouchedFiles ) import qualified Darcs.Patch ( summary )-#endif-import Darcs.Patch ( RepoPatch, xmlSummary, Patchy )+import Darcs.Patch ( RepoPatch ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.Info ( toXml ) import Darcs.Patch.Inspect ( PatchInspect )-import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, info, hopefullyM )+import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, info ) import Darcs.Patch.Witnesses.Ordered ( FL, mapFL )  import qualified Darcs.Repository as R ( amInHashedRepository, amInRepository                                        , amNotInRepository, findRepository ) import Darcs.Repository.Prefs ( defaultrepo ) -import Darcs.UI.Options ( DarcsOption, DarcsOptDescr, (^), optDescr, odesc, parseFlags )+import Darcs.UI.Options ( DarcsOption, DarcsOptDescr, (^), optDescr, odesc, parseFlags, (?) ) import Darcs.UI.Options.All-    ( StdCmdAction, stdCmdActions, anyVerbosity, UseCache, useCache, hooks-    , Verbosity(..), verbosity, Summary(..), DryRun(..), dryRun, XmlOutput(..) )+    ( StdCmdAction, stdCmdActions, anyVerbosity, UseCache, useCache, HooksConfig, hooks+    , Verbosity(..), DryRun(..), dryRun+    ) -import Darcs.UI.Flags ( remoteRepos, workRepo, DarcsFlag )-import Darcs.UI.PrintPatch ( showFriendly )-import Darcs.UI.Usage ( usageInfo )+import Darcs.UI.Flags ( DarcsFlag, remoteRepos, workRepo, quiet, verbose ) +import Darcs.Util.ByteString ( decodeLocale, packStringToUTF8 ) import Darcs.Util.Path ( AbsolutePath )-import Darcs.Util.Printer ( Doc, putDocLn, hPutDocLn, text, (<+>), errorDoc-                          , vsep, insertBeforeLastline, prefix, ($$), vcat-#ifndef WIN32-                          , renderString-#endif-                          , RenderMode(..)-                          )-#ifndef WIN32-import Darcs.Util.Progress ( beginTedious, endTedious, tediousSize-                           , finishedOneIO )-#endif-import Darcs.Util.Text ( chompTrailingNewline )+import Darcs.Util.Printer+    ( Doc, text, (<+>), ($$), vcat+    , putDocLnWith, hPutDocLn, errorDoc, renderString+    )+import Darcs.Util.Printer.Color ( fancyPrinters )+import Darcs.Util.Progress+    ( debugMessage, beginTedious, endTedious, tediousSize, finishedOneIO )  extractCommands :: [CommandControl] -> [WrappedCommand] extractCommands ccl = [ cmd | CommandData cmd <- ccl ]@@ -158,7 +144,8 @@                               (AbsolutePath, AbsolutePath)                            -> parsedFlags -> [String] -> IO ()           , commandPrereq :: [DarcsFlag] -> IO (Either String ())-          , commandGetArgPossibilities :: IO [String]+          , commandCompleteArgs :: (AbsolutePath, AbsolutePath)+                                -> [DarcsFlag] -> [String] -> IO [String]           , commandArgdefaults :: [DarcsFlag] -> AbsolutePath -> [String]                                -> IO [String]           , commandBasicOptions :: [DarcsOptDescr DarcsFlag]@@ -177,7 +164,7 @@           }  withStdOpts :: DarcsOption (Maybe StdCmdAction -> Bool -> Bool -> Verbosity -> Bool -> b) c-            -> DarcsOption (UseCache -> Maybe String -> Bool -> Maybe String -> Bool -> a) b+            -> DarcsOption (UseCache -> HooksConfig -> a) b             -> DarcsOption a c withStdOpts basicOpts advancedOpts =   basicOpts ^ stdCmdActions ^ anyVerbosity ^ advancedOpts ^ useCache ^ hooks@@ -199,7 +186,7 @@ nodefaults _ _ = return  getSubcommands :: DarcsCommand pf -> [CommandControl]-getSubcommands c@(SuperCommand {}) = commandSubCommands c+getSubcommands c@(SuperCommand {}) = commandGroup "Subcommands:" : commandSubCommands c getSubcommands _ = []  commandAlias :: String -> Maybe (DarcsCommand pf) -> DarcsCommand pf -> DarcsCommand pf@@ -222,120 +209,10 @@                         , commandCommand = \_ _ _ -> putStr h                         } -usage :: [CommandControl] -> String-usage cs = unlines-    [ "Usage: darcs COMMAND ..."-    , ""-    , "Commands:"-    , usageHelper cs-    , "Use 'darcs COMMAND --help' for help on a single command."-    , "Use 'darcs --version' to see the darcs version number."-    , "Use 'darcs --exact-version' to see a detailed darcs version."-    , "Use 'darcs help patterns' for help on patch matching."-    , "Use 'darcs help environment' for help on environment variables."-    , "Use 'darcs help manpage' to display help in the manpage format."-    , "Use 'darcs help markdown' to display help in the markdown format."-    , ""-    , "Check bug reports at http://bugs.darcs.net/"-    ]--subusage :: DarcsCommand pf -> String-subusage super = usageInfo header (odesc stdCmdActions) ++ superHelp-  where-    header = unlines [ unwords [ "Usage:"-                               , commandProgramName super-                               , commandName super-                               , "SUBCOMMAND ..."-                               ]-                     , ""-                     , commandDescription super-                     , ""-                     , "Subcommands:"-                     , usageHelper (getSubcommands super)-                     , "Options:"-                     ]-    superHelp = '\n' : commandHelp super--usageHelper :: [CommandControl] -> String-usageHelper xs = usageHelper' (maximum $ 15 : (catMaybes $ map f xs)) xs-   where-         -- returns length of necessary tabbing this command-         f (CommandData c) = Just ((+2) . length . wrappedCommandName $ c)-         f _ = Nothing--usageHelper' :: Int -> [CommandControl] -> String-usageHelper' _ [] = ""-usageHelper' x (HiddenCommand _ : cs) = usageHelper' x cs-usageHelper' x (CommandData c : cs) = "  " ++ padSpaces (wrappedCommandName c) x-                                        ++ chompTrailingNewline (wrappedCommandDescription c)-                                        ++ "\n" ++ usageHelper' x cs-usageHelper' x (GroupName n : cs) = "\n" ++ n ++ "\n" ++ usageHelper' x cs--padSpaces :: String -> Int -> String-padSpaces s n = s ++ replicate (n - length s) ' '- superName :: Maybe (DarcsCommand pf) -> String superName Nothing  = "" superName (Just x) = commandName x ++ " " -getCommandMiniHelp :: Maybe (DarcsCommand pf1) -> DarcsCommand pf2 -> String-getCommandMiniHelp msuper cmd = unlines-    [ getCommandHelpCore msuper cmd-    , ""-    , unwords [ "See"-              , commandProgramName cmd-              , "help"-              , maybe "" ((++ " ") . commandName) msuper ++ commandName cmd-              , "for details."-              ]-    ]--getCommandHelp :: Maybe (DarcsCommand pf1) -> DarcsCommand pf2 -> String-getCommandHelp msuper cmd = basicHelp ++ advancedHelp ++ cmdHelp-  where-    basicHelp = unlines (reverse basicR)--    advancedHelp = if null advanced-                       then ""-                       else '\n' :-                            unlines ("Advanced options:" : reverse advancedR)--    cmdHelp =  '\n' : commandHelp cmd--    -- we could just call usageInfo twice, but then the advanced-    -- options might not line up with the basic ones (no short switches)-    (advancedR, basicR) = splitAt (length advanced) . reverse . lines $-                              combinedUsage--    combinedUsage = let header = getCommandHelpCore msuper cmd ++ subcommands-                                     ++ "\n\nOptions:"-                    in usageInfo header (basic ++ advanced)--    (basic, advanced) = commandAlloptions cmd--    subcommands = case msuper of-                      Nothing -> case getSubcommands cmd of-                                     [] -> []-                                     s  -> "\n\nSubcommands:\n"-                                           ++ usageHelper s-                      -- we don't want to list subcommands if we're already-                      -- specifying them-                      Just _  -> ""--getCommandHelpCore :: Maybe (DarcsCommand pf1) -> DarcsCommand pf2 -> String-getCommandHelpCore msuper cmd =-    unwords [ "Usage:"-            , commandProgramName cmd-            , superName msuper ++ commandName cmd-            , "[OPTION]..."-            , unwords args_help-            ]-    ++ "\n" ++ commandDescription cmd-  where-    args_help = case cmd of-                    (DarcsCommand {}) -> commandExtraArgHelp cmd-                    _ -> []- data CommandArgs where     CommandOnly :: DarcsCommand parsedFlags -> CommandArgs     SuperCommandOnly :: DarcsCommand parsedFlags -> CommandArgs@@ -366,89 +243,36 @@     potentials = [c | c <- extractCommands cs, cmd `isPrefixOf` wrappedCommandName c]                  ++ [h | h <- extractHiddenCommands cs, cmd == wrappedCommandName h] -amVerbose :: [DarcsFlag] -> Bool-amVerbose = (== Verbose) . parseFlags verbosity--amQuiet :: [DarcsFlag] -> Bool-amQuiet = (== Quiet) . parseFlags verbosity- putVerbose :: [DarcsFlag] -> Doc -> IO ()-putVerbose flags = when (amVerbose flags) . putDocLn+putVerbose flags = when (verbose flags) . putDocLnWith fancyPrinters  putInfo :: [DarcsFlag] -> Doc -> IO ()-putInfo flags = unless (amQuiet flags) . putDocLn+putInfo flags = unless (quiet flags) . putDocLnWith fancyPrinters  putWarning :: [DarcsFlag] -> Doc -> IO ()-putWarning flags = unless (amQuiet flags) . hPutDocLn Encode stderr+putWarning flags = unless (quiet flags) . hPutDocLn stderr  putVerboseWarning :: [DarcsFlag] -> Doc -> IO ()-putVerboseWarning flags = when (amVerbose flags) . hPutDocLn Encode stderr+putVerboseWarning flags = when (verbose flags) . hPutDocLn stderr  abortRun :: [DarcsFlag] -> Doc -> IO () abortRun flags msg = if parseFlags dryRun flags == YesDryRun-                        then putInfo flags $ text "NOTE:" <+> msg+                        then putInfo flags $ "NOTE:" <+> msg                         else errorDoc msg --- | @'printDryRunMessageAndExit' action flags patches@ prints a string--- representing the action that would be taken if the @--dry-run@ option had--- not been passed to darcs. Then darcs exits successfully.  @action@ is the--- name of the action being taken, like @\"push\"@ @flags@ is the list of flags--- which were sent to darcs @patches@ is the sequence of patches which would be--- touched by @action@.-printDryRunMessageAndExit :: (RepoPatch p, ApplyState p ~ Tree)-                          => String-                          -> Verbosity -> Summary -> DryRun -> XmlOutput-                          -> Bool -- interactive-                          -> FL (PatchInfoAnd rt p) wX wY-                          -> IO ()-printDryRunMessageAndExit action v s d x interactive patches = do-    when (d == YesDryRun) $ do-        putInfoX . text $ unwords [ "Would"-                                  , action-                                  , "the following changes:"-                                  ]-        putDocLn put_mode-        putInfoX $ text ""-        putInfoX $ text "Making no changes: this is a dry run."-        exitSuccess-    when (not interactive && s == YesSummary) $ do-        putInfoX . text $ unwords [ "Will"-                                  , action-                                  , "the following changes:"-                                  ]-        putDocLn put_mode-  where-    put_mode = if x == YesXml-                   then text "<patches>" $$-                        vcat (mapFL (indent . xml_info s) patches) $$-                        text "</patches>"-                   else vsep $ mapFL (showFriendly v s) patches--    putInfoX = if x == YesXml then const (return ()) else putDocLn--    xml_info YesSummary = xml_with_summary-    xml_info NoSummary  = toXml . info--    xml_with_summary hp-        | Just p <- hopefullyM hp = insertBeforeLastline (toXml $ info hp)-                                        (indent $ xmlSummary p)-    xml_with_summary hp = toXml (info hp)--    indent = prefix "    "- -- | Set the DARCS_PATCHES and DARCS_PATCHES_XML environment variables with -- info about the given patches, for use in post-hooks. setEnvDarcsPatches :: (RepoPatch p, ApplyState p ~ Tree)                    => FL (PatchInfoAnd rt p) wX wY -> IO ()-#ifndef WIN32 setEnvDarcsPatches ps = do     let k = "Defining set of chosen patches"+    debugMessage $ unlines ("setEnvDarcsPatches:" : listTouchedFiles ps)     beginTedious k     tediousSize k 3     finishedOneIO k "DARCS_PATCHES"-    setEnvCautiously "DARCS_PATCHES" (renderString Encode $ Darcs.Patch.summary ps)+    setEnvCautiously "DARCS_PATCHES" (renderString $ Darcs.Patch.summary ps)     finishedOneIO k "DARCS_PATCHES_XML"-    setEnvCautiously "DARCS_PATCHES_XML" . renderString Encode $+    setEnvCautiously "DARCS_PATCHES_XML" . renderString $         text "<patches>" $$         vcat (mapFL (toXml . info) ps) $$         text "</patches>"@@ -456,43 +280,37 @@     setEnvCautiously "DARCS_FILES" $ unlines (listTouchedFiles ps)     endTedious k +-- | Set the DARCS_FILES environment variable to the files touched by the+-- given patch, one per line, for use in post-hooks.+setEnvDarcsFiles :: (PatchInspect p) => p wX wY -> IO ()+setEnvDarcsFiles ps =+    setEnvCautiously "DARCS_FILES" $ unlines (listTouchedFiles ps)+ -- | Set some environment variable to the given value, unless said value is -- longer than 10K characters, in which case do nothing. setEnvCautiously :: String -> String -> IO () setEnvCautiously e v     | toobig (10 * 1024) v = return ()-    | otherwise = setEnv e v True+    | otherwise =+        setEnv e v `catchIOError` (\_ -> setEnv e (decodeLocale (packStringToUTF8 v)))   where     -- note: not using (length v) because we want to be more lazy than that     toobig :: Int -> [a] -> Bool     toobig 0 _ = True     toobig _ [] = False     toobig n (_ : xs) = toobig (n - 1) xs-#else-setEnvDarcsPatches _ = return ()-#endif --- | Set the DARCS_FILES environment variable to the files touched by the--- given patch, one per line, for use in post-hooks.-setEnvDarcsFiles :: (PatchInspect p, Patchy p) => p wX wY -> IO ()-#ifndef WIN32-setEnvDarcsFiles ps =-    setEnvCautiously "DARCS_FILES" $ unlines (listTouchedFiles ps)-#else-setEnvDarcsFiles _ = return ()-#endif- defaultRepo :: [DarcsFlag] -> AbsolutePath -> [String] -> IO [String]-defaultRepo fs = defaultrepo (remoteRepos fs)+defaultRepo fs = defaultrepo (remoteRepos ? fs)  amInHashedRepository :: [DarcsFlag] -> IO (Either String ())-amInHashedRepository fs = R.amInHashedRepository (workRepo fs)+amInHashedRepository fs = R.amInHashedRepository (workRepo ? fs)  amInRepository :: [DarcsFlag] -> IO (Either String ())-amInRepository fs = R.amInRepository (workRepo fs)+amInRepository fs = R.amInRepository (workRepo ? fs)  amNotInRepository :: [DarcsFlag] -> IO (Either String ())-amNotInRepository fs = R.amNotInRepository (workRepo fs)+amNotInRepository fs = R.amNotInRepository (workRepo ? fs)  findRepository :: [DarcsFlag] -> IO (Either String ())-findRepository fs = R.findRepository (workRepo fs)+findRepository fs = R.findRepository (workRepo ? fs)
src/Darcs/UI/Commands/Add.hs view
@@ -23,30 +23,23 @@ -- Stability   : experimental -- Portability : portable -{-# LANGUAGE CPP #-}-module Darcs.UI.Commands.Add-    (-      add-    , expandDirs-    ) where+module Darcs.UI.Commands.Add ( add ) where  import Prelude () import Darcs.Prelude -#include "impossible.h"--import Prelude hiding ( (^) )- import Control.Exception ( catch, IOException )-import Control.Monad ( when, unless, liftM )+import Control.Monad ( when, unless ) import Data.List ( (\\), nub ) import Data.List.Ordered ( nubSort ) import Data.Maybe ( isNothing, maybeToList ) import Darcs.Util.Printer ( text ) import Darcs.Util.Tree ( Tree, findTree, expand )-import Darcs.Util.Path ( floatPath, anchorPath, parents,-                    SubPath, toFilePath, simpleSubPath, toPath, AbsolutePath )-import System.FilePath.Posix ( takeDirectory, (</>) )+import Darcs.Util.Path+    ( floatPath, anchorPath, parents+    , SubPath, toFilePath, AbsolutePath+    )+import System.FilePath.Posix ( takeDirectory ) import System.Posix.Files ( isRegularFile, isDirectory, isSymbolicLink ) import System.Directory ( getPermissions, readable ) @@ -55,32 +48,30 @@ import Darcs.UI.Commands     ( DarcsCommand(..), withStdOpts, putInfo, putWarning, putVerboseWarning     , nodefaults, amInHashedRepository)+import Darcs.UI.Commands.Util.Tree ( treeHas, treeHasDir, treeHasAnycase )+import Darcs.UI.Commands.Util ( expandDirs, doesDirectoryReallyExist )+import Darcs.UI.Completion ( unknownFileArgs ) import Darcs.UI.Flags     ( DarcsFlag-    , includeBoring, doAllowCaseOnly, doAllowWindowsReserved, useCache, dryRun, umask-    , fixSubPaths, verbosity )+    , includeBoring, allowCaseDifferingFilenames, allowWindowsReservedFilenames, useCache, dryRun, umask+    , fixSubPaths, quiet ) import Darcs.UI.Options-    ( DarcsOption-    , (^), odesc, ocheck, onormalise, defaultFlags, parseFlags )+    ( (^), odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O-import Darcs.UI.Commands.Util.Tree ( treeHas, treeHasDir, treeHasAnycase ) import Darcs.Repository.Flags ( UpdateWorking(..) )-import Darcs.Patch ( Patchy, PrimPatch, applyToTree, addfile, adddir )+import Darcs.Patch ( PrimPatch, applyToTree, addfile, adddir ) import Darcs.Patch.Apply ( ApplyState ) import Darcs.Repository.State ( readRecordedAndPending, updateIndex ) import Darcs.Repository     ( withRepoLock     , RepoJob(..)     , addToPending-    , listFiles-    , listUnregisteredFiles     ) import Darcs.Repository.Prefs ( darcsdirFilter, boringFileFilter )-import Darcs.Util.File ( getFileStatus, withCurrentDirectory )+import Darcs.Util.File ( getFileStatus ) import Darcs.Patch.Witnesses.Ordered ( FL(..), (+>+), nullFL ) import Darcs.Patch.Witnesses.Sealed ( Sealed(..), Gap(..), FreeLeft, unFreeLeft ) - addDescription :: String addDescription = "Add new files to version control." @@ -111,38 +102,6 @@     "`ReadMe` and `README`).  If `--case-ok` is used, the repository might be\n" ++     "unusable on those systems!\n\n" -addBasicOpts :: DarcsOption a-                (O.IncludeBoring -> Bool -> Bool -> Bool -> Maybe String -> O.DryRun -> a)-addBasicOpts = O.includeBoring-             ^ O.allowProblematicFilenames-             ^ O.recursive-             ^ O.workingRepoDir-             ^ O.dryRun--addAdvancedOpts :: DarcsOption a (O.UMask -> a)-addAdvancedOpts = O.umask--addOpts :: DarcsOption a-           (O.IncludeBoring-            -> Bool-            -> Bool-            -> Bool-            -> Maybe String-            -> O.DryRun-            -> Maybe O.StdCmdAction-            -> Bool-            -> Bool-            -> O.Verbosity-            -> Bool-            -> O.UMask-            -> O.UseCache-            -> Maybe String-            -> Bool-            -> Maybe String-            -> Bool-            -> a)-addOpts = withStdOpts addBasicOpts addAdvancedOpts- add :: DarcsCommand [DarcsFlag] add = DarcsCommand     { commandProgramName          = "darcs"@@ -153,8 +112,7 @@     , commandExtraArgHelp         = [ "<FILE or DIRECTORY> ..." ]     , commandCommand              = addCmd     , commandPrereq               = amInHashedRepository-    , commandGetArgPossibilities  = listUnregisteredFiles False-                                    -- bash completion should not offer boring files+    , commandCompleteArgs  = unknownFileArgs     , commandArgdefaults          = nodefaults     , commandAdvancedOptions      = odesc addAdvancedOpts     , commandBasicOptions         = odesc addBasicOpts@@ -162,6 +120,15 @@     , commandCheckOptions         = ocheck addOpts     , commandParseOptions         = onormalise addOpts     }+  where+    addBasicOpts+      = O.includeBoring+      ^ O.allowProblematicFilenames+      ^ O.recursive+      ^ O.repoDir+      ^ O.dryRun+    addAdvancedOpts = O.umask+    addOpts = withStdOpts addBasicOpts addAdvancedOpts   addCmd :: (AbsolutePath, AbsolutePath)@@ -181,7 +148,9 @@ addFiles :: [DarcsFlag]  -- ^ Command options          -> [SubPath]          -> IO ()-addFiles opts origfiles = withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+addFiles opts origfiles =+  withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $+  RepoJob $ \repository -> do     -- TODO do not expand here, and use findM/findIO or such later     -- (needs adding to hashed-storage first though)     cur <- expand =<< readRecordedAndPending repository@@ -196,19 +165,19 @@     mapM_ (putWarning opts . text . ((msgSkipping msgs ++ " boring file ")++)) $         flist \\ nboring flist     Sealed ps <- fmap unFreeLeft $ addp msgs opts cur $ nboring flist-    when (nullFL ps && not (null origfiles) && notQuiet) $+    -- TODO whether we fail or not depends on verbosity BAD BAD BAD+    when (nullFL ps && not (null origfiles) && not (quiet opts)) $         fail "No files were added"     unless gotDryRun $       do addToPending repository YesUpdateWorking ps          updateIndex repository   where-    gotDryRun = dryRun opts == O.YesDryRun+    gotDryRun = dryRun ? opts == O.YesDryRun     msgs | gotDryRun = dryRunMessages          | otherwise = normalMessages-    notQuiet = verbosity opts /= O.Quiet  -addp :: forall prim . (Patchy prim, PrimPatch prim, ApplyState prim ~ Tree)+addp :: forall prim . (PrimPatch prim, ApplyState prim ~ Tree)      => AddMessages      -> [DarcsFlag]      -> Tree IO@@ -319,8 +288,8 @@                       msgSkipping msgs ++ " '" ++ f ++ "' ... " ++ show e                   return (cur, Nothing, Nothing)           parentdir = takeDirectory f-    gotAllowCaseOnly = doAllowCaseOnly opts-    gotAllowWindowsReserved = doAllowWindowsReserved opts+    gotAllowCaseOnly = allowCaseDifferingFilenames ? opts+    gotAllowWindowsReserved = allowWindowsReservedFilenames ? opts   data AddMessages = AddMessages@@ -352,34 +321,9 @@     }  -doesDirectoryReallyExist :: FilePath -> IO Bool-doesDirectoryReallyExist f = maybe False isDirectory `fmap` getFileStatus f---expandDirs :: Bool -> [SubPath]-           -> IO [SubPath]-expandDirs doIncludeBoring fs =-  do-    liftM (map (fromJust . simpleSubPath)) $-      concat `fmap` mapM (expandOne doIncludeBoring . toPath) fs---expandOne :: Bool -> FilePath-          -> IO [FilePath]-expandOne doIncludeBoring "" = listFiles doIncludeBoring-expandOne doIncludeBoring f = do-    isdir <- doesDirectoryReallyExist f-    if not isdir-      then return [f]-      else do-        fs <- withCurrentDirectory f (listFiles doIncludeBoring)-        return $ f: map (f </>) fs-- getParents :: Tree IO            -> [FilePath]            -> [FilePath] getParents cur = map (anchorPath "") . go . map floatPath   where     go fs = filter (isNothing . findTree cur) $ concatMap parents fs-
src/Darcs/UI/Commands/Amend.hs view
@@ -43,8 +43,9 @@     , amInHashedRepository     ) import Darcs.UI.Commands.Util ( announceFiles, testTentativeAndMaybeExit )+import Darcs.UI.Completion ( modifiedFileArgs, knownFileArgs ) import Darcs.UI.Flags ( DarcsFlag, diffOpts, fixSubPaths )-import Darcs.UI.Options ( DarcsOption, (^), oparse, odesc, ocheck, defaultFlags )+import Darcs.UI.Options ( DarcsOption, (^), oparse, odesc, ocheck, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.UI.PatchHeader ( updatePatchHeader, AskAboutDeps(..)                             , HijackOptions(..)@@ -70,12 +71,10 @@     , withManualRebaseUpdate     , finalizeRepositoryChanges     , invalidateIndex-    , unrecordedChangesWithPatches+    , unrecordedChanges     , readRecorded-    , listRegisteredFiles     ) import Darcs.Repository.Prefs ( globalPrefsDirDoc )-import Darcs.Repository.State ( getMovesPs, getReplaces ) import Darcs.UI.SelectChanges     ( WhichChanges(..)     , selectionContextPrim@@ -88,12 +87,10 @@ import Darcs.Util.Exception ( clarifyErrors ) import Darcs.Patch.Witnesses.Ordered     ( FL(..), (:>)(..), (+>+), nullFL, reverseRL, mapFL_FL )-import Darcs.Patch.Witnesses.Sealed ( Sealed(..) )-import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP )  import Darcs.Util.Printer ( putDocLn ) import Darcs.Util.Tree( Tree )-import Darcs.Repository.Internal ( tentativelyRemoveFromPending )+import Darcs.Repository.Pending ( tentativelyRemoveFromPending )   amendDescription :: String@@ -151,11 +148,11 @@     ^ O.author     ^ O.selectAuthor     ^ O.patchname-    ^ O.askdeps+    ^ O.askDeps     ^ O.askLongComment     ^ O.keepDate     ^ O.lookfor-    ^ O.workingRepoDir+    ^ O.repoDir     ^ O.withContext     ^ O.diffAlgorithm @@ -192,10 +189,7 @@               -> O.UMask               -> O.SetScriptsExecutable               -> O.UseCache-              -> Maybe String-              -> Bool-              -> Maybe String-              -> Bool+              -> O.HooksConfig               -> a) amendOpts = withStdOpts amendBasicOpts amendAdvancedOpts @@ -237,7 +231,7 @@     , commandExtraArgHelp         = ["[FILE or DIRECTORY]..."]     , commandCommand              = amendCmd     , commandPrereq               = amInHashedRepository-    , commandGetArgPossibilities  = listRegisteredFiles+    , commandCompleteArgs         = amendFileArgs     , commandArgdefaults          = nodefaults     , commandAdvancedOptions      = odesc amendAdvancedOpts     , commandBasicOptions         = odesc amendBasicOpts@@ -245,7 +239,11 @@     , commandCheckOptions         = ocheck amendOpts     , commandParseOptions         = amendConfig     }-+  where+    amendFileArgs fps flags args =+      if (O.amendUnrecord ? flags)+        then knownFileArgs fps flags args+        else modifiedFileArgs fps flags args  amendrecord :: DarcsCommand AmendConfig amendrecord = commandAlias "amend-record" Nothing amend@@ -293,15 +291,9 @@                            (_ :> chosenPrims) <- runSelection (effect oldp) context                            let invPrims = reverseRL (invertFL chosenPrims)                            addChangesToPatch cfg repository oldp invPrims-                   else do Sealed replacePs <- if O.replaces (lookfor cfg) == O.YesLookForReplaces-                             then getReplaces (diffingOpts cfg) repository files-                             else return (Sealed NilFL)-                           movesPs <- if O.moves (lookfor cfg) == O.YesLookForMoves-                              then getMovesPs repository files-                              else return NilFL-                           go =<< unrecordedChangesWithPatches-                                    movesPs (unsafeCoerceP replacePs :: FL (PrimOf p) wR wR)-                                    (diffingOpts cfg) repository files+                   else go =<< unrecordedChanges (diffingOpts cfg)+                                  (O.moves (lookfor cfg)) (O.replaces (lookfor cfg))+                                  repository files               -- amending a tag            else if hasEditMetadata cfg && isNothing files                         -- the user is not trying to add new changes to the tag so there is
src/Darcs/UI/Commands/Annotate.hs view
@@ -14,22 +14,21 @@ --  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.-{-# LANGUAGE CPP, OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings #-}  module Darcs.UI.Commands.Annotate ( annotate ) where  import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) )- import Control.Arrow ( first )-import Control.Monad ( unless )+import Control.Monad ( when )  import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository )-import Darcs.UI.Flags ( DarcsFlag(NoPatchIndexFlag), useCache, fixSubPaths, umask )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise-                        , defaultFlags, parseFlags )+import Darcs.UI.Completion ( knownFileArgs )+import Darcs.UI.Flags ( DarcsFlag, useCache, fixSubPaths, patchIndexYes )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise+                        , defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.State ( readRecorded ) import Darcs.Repository@@ -38,11 +37,9 @@     , RepoJob(..)     , readRepo     , repoPatchType-    , listRegisteredFiles     )-import Darcs.Repository.Flags ( UpdateWorking(..) ) import Darcs.Repository.PatchIndex ( attemptCreatePatchIndex )-import Darcs.Patch.Set ( newset2RL )+import Darcs.Patch.Set ( patchSet2RL ) import Darcs.Patch ( invertRL ) import qualified Data.ByteString.Char8 as BC ( pack, concat, intercalate ) import Data.ByteString.Lazy ( toChunks )@@ -57,10 +54,8 @@ import Darcs.Util.Tree( TreeItem(..), readBlob, list, expand ) import Darcs.Util.Tree.Monad( findM, virtualTreeIO ) import Darcs.Util.Path( floatPath, anchorPath, fp2fn, toFilePath-                      , AbsolutePath )-import qualified Darcs.Util.Diff as D ( DiffAlgorithm(MyersDiff) )--#include "impossible.h"+                      , AbsolutePath, SubPath )+import Darcs.Util.Exception ( die )  annotateDescription :: String annotateDescription = "Annotate lines of a file with the last patch that modified it."@@ -74,36 +69,6 @@  , "machine postprocessing."  ] -annotateBasicOpts :: DarcsOption a-                     (Bool-                      -> [O.MatchFlag]-                      -> Maybe String-                      -> a)-annotateBasicOpts = O.machineReadable-                  ^ O.matchUpToOne-                  ^ O.workingRepoDir--annotateAdvancedOpts :: DarcsOption a (O.WithPatchIndex -> a)-annotateAdvancedOpts = O.patchIndexYes--annotateOpts :: DarcsOption a-                (   Bool-                 -> [O.MatchFlag]-                 -> Maybe String-                 -> Maybe O.StdCmdAction-                 -> Bool-                 -> Bool-                 -> O.Verbosity-                 -> Bool-                 -> O.WithPatchIndex-                 -> O.UseCache-                 -> Maybe String-                 -> Bool-                 -> Maybe String-                 -> Bool-                 -> a)-annotateOpts = annotateBasicOpts `withStdOpts` annotateAdvancedOpts- annotate :: DarcsCommand [DarcsFlag] annotate = DarcsCommand     { commandProgramName = "darcs"@@ -114,60 +79,69 @@     , commandExtraArgHelp = ["[FILE or DIRECTORY]"]     , commandCommand = annotateCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = listRegisteredFiles+    , commandCompleteArgs = knownFileArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc annotateAdvancedOpts     , commandBasicOptions = odesc annotateBasicOpts     , commandDefaults = defaultFlags annotateOpts     , commandCheckOptions = ocheck annotateOpts     , commandParseOptions = onormalise annotateOpts-}+    }+  where+    annotateBasicOpts = O.machineReadable ^ O.matchUpToOne ^ O.repoDir+    annotateAdvancedOpts = O.patchIndexYes+    annotateOpts = annotateBasicOpts `withStdOpts` annotateAdvancedOpts  annotateCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-annotateCmd _ _ [""] = fail "No filename argument given to annotate!" annotateCmd fps opts args = do- let matchFlags = parseFlags O.matchUpToOne opts- unless (NoPatchIndexFlag `elem` opts)-   $ withRepoLockCanFail (useCache opts) YesUpdateWorking (umask opts) $ RepoJob attemptCreatePatchIndex- withRepository (useCache opts) $ RepoJob $ \repository -> do+  fixed_paths <- fixSubPaths fps args+  case fixed_paths of+    [] -> die "Error: annotate needs a filename to work with"+    (fixed_path:_) -> do+      when (patchIndexYes ? opts == O.YesPatchIndex)+        $ withRepoLockCanFail (useCache ? opts)+        $ RepoJob (\repo -> readRepo repo >>= attemptCreatePatchIndex repo)+      annotateCmd' opts fixed_path++annotateCmd' :: [DarcsFlag] -> SubPath -> IO ()+annotateCmd' opts fixed_path = withRepository (useCache ? opts) $ RepoJob $ \repository -> do+  let matchFlags = parseFlags O.matchUpToOne opts   r <- readRepo repository-  (origpath:_) <- fixSubPaths fps args   recorded <- readRecorded repository-   (patches, initial, path') <-     if haveNonrangeMatch (repoPatchType repository) matchFlags        then do Sealed x <- getOnePatchset repository matchFlags-               let fn = [fp2fn $ toFilePath origpath]+               let fn = [fp2fn $ toFilePath fixed_path]                    nonRangeMatch = getNonrangeMatchS matchFlags r                    (_, [path], _) = withFileNames Nothing fn nonRangeMatch                initial <- snd `fmap` virtualTreeIO (getNonrangeMatchS matchFlags r) recorded-               return (seal $ newset2RL x, initial, toFilePath path)-       else return (seal $ newset2RL r, recorded, toFilePath origpath)+               return (seal $ patchSet2RL x, initial, toFilePath path)+       else return (seal $ patchSet2RL r, recorded, toFilePath fixed_path)   let path = "./" ++ path'    found <- findM initial (floatPath $ toFilePath path)   -- TODO need to decide about the --machine flag   let fmt = if parseFlags O.machineReadable opts then A.machineFormat else A.format+  usePatchIndex <- (O.yes (O.patchIndexYes ? opts) &&) <$> canUsePatchIndex repository   case found of-    Nothing -> fail $ "No such file or directory: " ++ toFilePath path+    Nothing -> die $ "Error: no such file or directory: " ++ toFilePath path     Just (SubTree s) -> do       s' <- expand s       let subs = map (fp2fn . (path </>) . anchorPath "" . fst) $ list s'           showPath (n, File _) = BC.pack (path </> n)           showPath (n, _) = BC.concat [BC.pack (path </> n), "/"]       (Sealed ans_patches) <- do-         upi <- canUsePatchIndex repository-         if not upi+         if not usePatchIndex             then return patches-            else getRelevantSubsequence patches repository subs+            else getRelevantSubsequence patches repository r subs       putStrLn $ fmt (BC.intercalate "\n" $                         map (showPath . first (anchorPath "")) $ list s') $-        A.annotateDirectory D.MyersDiff (invertRL ans_patches) (fp2fn path) subs+        A.annotateDirectory (invertRL ans_patches) (fp2fn path) subs     Just (File b) -> do (Sealed ans_patches) <- do-                           upi <- canUsePatchIndex repository-                           if not upi+                           if not usePatchIndex                               then return patches-                              else getRelevantSubsequence patches repository [fp2fn path]+                              else getRelevantSubsequence patches repository r [fp2fn path]                         con <- BC.concat `fmap` toChunks `fmap` readBlob b-                        putStrLn $ fmt con $ A.annotate D.MyersDiff (invertRL ans_patches) (fp2fn path) con+                        putStrLn $ fmt con $+                          A.annotateFile (invertRL ans_patches) (fp2fn path) con     Just (Stub _ _) -> impossible
src/Darcs/UI/Commands/Apply.hs view
@@ -15,8 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.UI.Commands.Apply     ( apply, applyCmd     , getPatchBundle -- used by darcsden@@ -26,7 +24,6 @@ import Darcs.Prelude  import System.Exit ( exitSuccess )-import Prelude hiding ( (^) ) import Control.Monad ( when )  import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, hopefullyM, info )@@ -35,14 +32,15 @@     , putVerbose     , amInHashedRepository     )+import Darcs.UI.Completion ( fileArgs ) import Darcs.UI.Flags     ( DarcsFlag-    , doHappyForwarding, doReverse, verbosity, useCache, dryRun+    , happyForwarding, changesReverse, verbosity, useCache, dryRun     , reorder, umask     , fixUrl, getCc, getSendmailCmd-    , isUnified, getReply+    , withContext, reply     )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags, parseFlags )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Flags ( UpdateWorking(..) ) import Darcs.Util.Path ( toFilePath, AbsolutePath )@@ -53,10 +51,10 @@     , readRepo     , filterOutConflicts     )-import Darcs.Patch.Set ( Origin, newset2RL )-import Darcs.Patch ( IsRepoType, RepoPatch, PrimOf )+import Darcs.Patch.Set ( Origin, patchSet2RL )+import Darcs.Patch ( IsRepoType, RepoPatch ) import Darcs.Patch.Apply( ApplyState )-import Darcs.Patch.Info ( PatchInfo, showPatchInfoUI )+import Darcs.Patch.Info ( PatchInfo, displayPatchInfo ) import Darcs.Patch.Witnesses.Ordered     ( RL(..), (:\/:)(..), (:>)(..)     , mapRL, nullFL, reverseFL )@@ -85,13 +83,10 @@ import Darcs.Patch.Bundle ( scanBundle ) import Darcs.Util.Printer     ( packedString, vcat, text, empty-    , renderString, RenderMode(..)+    , renderString     ) import Darcs.Util.Tree( Tree ) -#include "impossible.h"-- applyDescription :: String applyDescription = "Apply a patch bundle created by `darcs send'." @@ -138,99 +133,6 @@ stdindefault _ [] = return ["-"] stdindefault _ x = return x -conflictsOpt :: DarcsOption a (Maybe O.AllowConflicts -> a)-conflictsOpt = O.conflicts O.NoAllowConflicts--applyBasicOpts :: DarcsOption a-                  (O.Verify-                   -> O.Reorder-                   -> Maybe Bool-                   -> O.DryRun-                   -> O.XmlOutput-                   -> [O.MatchFlag]-                   -> Maybe O.AllowConflicts-                   -> O.ExternalMerge-                   -> O.RunTest-                   -> O.LeaveTestDir-                   -> Maybe String-                   -> O.DiffAlgorithm-                   -> a)-applyBasicOpts-    = O.verify-    ^ O.reorder-    ^ O.interactive-    ^ O.dryRunXml-    ^ O.matchSeveral-    ^ conflictsOpt-    ^ O.useExternalMerge-    ^ O.test-    ^ O.leaveTestDir-    ^ 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 O.AllowConflicts-              -> O.ExternalMerge-              -> O.RunTest-              -> O.LeaveTestDir-              -> 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- apply :: DarcsCommand [DarcsFlag] apply = DarcsCommand     { commandProgramName = "darcs"@@ -241,7 +143,7 @@     , commandExtraArgHelp = ["<PATCHFILE>"]     , commandCommand = applyCmd StandardPatchApplier     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = fileArgs     , commandArgdefaults = const stdindefault     , commandAdvancedOptions = odesc applyAdvancedOpts     , commandBasicOptions = odesc applyBasicOpts@@ -249,25 +151,55 @@     , commandCheckOptions = ocheck applyOpts     , commandParseOptions = onormalise applyOpts     }+  where+    applyBasicOpts+      = O.verify+      ^ O.reorder+      ^ O.interactive+      ^ O.dryRunXml+      ^ O.matchSeveral+      ^ O.conflictsNo+      ^ O.externalMerge+      ^ O.runTest+      ^ O.leaveTestDir+      ^ O.repoDir+      ^ O.diffAlgorithm+    applyAdvancedOpts+      = O.reply+      ^ O.ccApply+      ^ O.happyForwarding+      ^ O.sendmail+      ^ O.useIndex+      ^ O.compress+      ^ O.setScriptsExecutable+      ^ O.umask+      ^ O.restrictPaths+      ^ O.changesReverse+      ^ O.pauseForGui+    applyOpts = applyBasicOpts `withStdOpts` applyAdvancedOpts  applyCmd :: PatchApplier pa => pa -> (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () applyCmd _ _ _ [""] = fail "Empty filename argument given to apply!"-applyCmd patchApplier _ opts ["-"] = withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $ repoJob patchApplier opts $ \patchProxy repository -> do+applyCmd patchApplier _ opts ["-"] =+  withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $+  repoJob patchApplier opts $ \patchProxy repository -> do     -- for darcs users who try out 'darcs apply' without any arguments-  putVerbose opts $ text "reading patch bundle from stdin..."-  bundle <- gzReadStdin-  applyCmdCommon patchApplier patchProxy opts bundle repository+    putVerbose opts $ text "reading patch bundle from stdin..."+    bundle <- gzReadStdin+    applyCmdCommon patchApplier patchProxy opts bundle repository -applyCmd patchApplier (_,o) opts [unfixed_patchesfile] = withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $ repoJob patchApplier opts $ \patchProxy repository -> do-  patchesfile <- fixUrl o unfixed_patchesfile-  bundle <- gzFetchFilePS (toFilePath patchesfile) Uncachable-  applyCmdCommon patchApplier patchProxy opts bundle repository+applyCmd patchApplier (_,o) opts [unfixed_patchesfile] =+  withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $+  repoJob patchApplier opts $ \patchProxy repository -> do+    patchesfile <- fixUrl o unfixed_patchesfile+    bundle <- gzFetchFilePS (toFilePath patchesfile) Uncachable+    applyCmdCommon patchApplier patchProxy opts bundle repository  applyCmd _ _ _ _ = impossible  applyCmdCommon     :: forall rt pa p wR wU-     . ( PatchApplier pa, RepoPatch p, ApplyState (PrimOf p) ~ Tree, ApplyState p ~ Tree+     . ( PatchApplier pa, RepoPatch p, ApplyState p ~ Tree        , ApplierRepoTypeConstraint pa rt, IsRepoType rt        )     => pa@@ -290,22 +222,22 @@   common :> _ <- return $ findCommonWithThem us them    -- all patches that are in "them" and not in "common" need to be available; check that-  let common_i = mapRL info $ newset2RL common-      them_i = mapRL info $ newset2RL them+  let common_i = mapRL info $ patchSet2RL common+      them_i = mapRL info $ patchSet2RL them       required = them_i \\ common_i -- FIXME quadratic?       check :: RL (PatchInfoAnd rt p) wX wY -> [PatchInfo] -> IO ()       check (ps' :<: p) bad = case hopefullyM p of         Nothing | info p `elem` required -> check ps' (info p : bad)         _ -> check ps' bad       check NilRL [] = return ()-      check NilRL bad = fail . renderString Encode $ vcat $ map showPatchInfoUI bad +++      check NilRL bad = fail . renderString $ vcat $ map displayPatchInfo bad ++                         [ text "\nFATAL: Cannot apply this bundle. We are missing the above patches." ] -  check (newset2RL them) []+  check (patchSet2RL them) []    (us':\/:them') <- return $ findUncommon us them   (hadConflicts, Sealed their_ps)-    <- if parseFlags conflictsOpt opts == Nothing -- skip conflicts+    <- if O.conflictsNo ? opts == Nothing -- skip conflicts         then filterOutConflicts (reverseFL us') repository them'         else return (False, Sealed them')   when hadConflicts $ putStrLn "Skipping some patches which would cause conflicts."@@ -314,9 +246,9 @@            then putStrLn ("All new patches of the bundle cause conflicts.  " ++                           "Nothing to do.") >> exitSuccess            else putStrLn ("All these patches have already been applied.  " ++-                          "Nothing to do.") >> when (reorder opts /= O.Reorder) exitSuccess+                          "Nothing to do.") >> when (reorder ? opts /= O.Reorder) exitSuccess           -  let direction = if doReverse opts then FirstReversed else First+  let direction = if changesReverse ? opts then FirstReversed else First       context = selectionContext direction "apply" (patchSelOpts opts) Nothing Nothing   (to_be_applied :> _) <- runSelection their_ps context   applyPatches patchApplier patchProxy "apply" opts from_whom repository us' to_be_applied@@ -394,7 +326,7 @@     "key, or there was a GPG failure.\n"  considerForwarding :: [DarcsFlag] -> B.ByteString -> IO Bool-considerForwarding opts bundle = case getReply opts of+considerForwarding opts bundle = case reply ? opts of   Nothing -> return False   Just from -> case break is_from (linesPS bundle) of     (m1, f:m2) ->@@ -405,7 +337,7 @@             then return False -- Refuse possible email loop.             else do               scmd <- getSendmailCmd opts-              if doHappyForwarding opts+              if happyForwarding ? opts                then resendEmail from scmd bundle                else sendEmailDoc f' from "A forwarded darcs patch" cc                                  scmd (Just (empty,empty))@@ -421,12 +353,12 @@  patchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions patchSelOpts flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { S.verbosity = verbosity ? flags     , S.matchFlags = parseFlags O.matchSeveral flags     , S.interactive = maybeIsInteractive flags     , S.selectDeps = O.PromptDeps -- option not supported, use default     , S.summary = O.NoSummary -- option not supported, use default-    , S.withContext = isUnified flags+    , S.withContext = withContext ? flags     }  maybeIsInteractive :: [DarcsFlag] -> Bool
src/Darcs/UI/Commands/Clone.hs view
@@ -15,8 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.UI.Commands.Clone     ( get     , put@@ -28,8 +26,6 @@ import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) )- import System.Directory ( doesDirectoryExist, doesFileExist                         , setCurrentDirectory ) import System.Exit ( ExitCode(..) )@@ -43,17 +39,20 @@                       , commandAlias                       , putInfo                       )+import Darcs.UI.Completion ( noArgs ) import Darcs.UI.Flags( DarcsFlag( NewRepo                                   , UpToPattern                                   , UpToPatch+                                  , UpToHash                                   , OnePattern                                   , OnePatch+                                  , OneHash                                   )-                     , toMatchFlags, useCache, umask, remoteRepos-                     , setDefault , DarcsFlag(Quiet), usePacks+                     , matchAny, useCache, umask, remoteRepos+                     , setDefault, quiet, usePacks                      , remoteDarcs, cloneKind, verbosity, setScriptsExecutable-                     , withWorkingDir, runPatchIndex )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags, parseFlags )+                     , withWorkingDir, patchIndexNo )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.UI.Commands.Util ( getUniqueRepositoryName ) import Darcs.Repository ( cloneRepository )@@ -70,7 +69,7 @@ import Darcs.Patch.Bundle ( scanContextFile ) import Darcs.Patch.Dummy ( DummyPatch ) import Darcs.Patch.Set ( PatchSet, Origin )-import Darcs.Repository.Motd ( showMotd )+import Darcs.Repository.Prefs ( showMotd ) import Darcs.Util.Progress ( debugMessage ) import Darcs.Util.Printer ( text, ($$) ) import Darcs.Util.Path ( toFilePath, toPath, ioAbsoluteOrRemote, AbsolutePath )@@ -116,47 +115,6 @@   ] ++ cloneHelpTag     ++ cloneHelpSSE -cloneBasicOpts :: DarcsOption a-                  (Maybe String-                   -> CloneKind-                   -> [O.MatchFlag]-                   -> Maybe Bool-                   -> O.SetScriptsExecutable-                   -> O.WithWorkingDir-                   -> a)-cloneBasicOpts = O.reponame-               ^ O.partial-               ^ O.matchOneContext-               ^ O.setDefault-               ^ O.setScriptsExecutable-               ^ O.useWorkingDir--cloneAdvancedOpts :: DarcsOption a (Bool -> O.WithPatchIndex -> O.NetworkOptions -> a)-cloneAdvancedOpts = O.usePacks ^ O.patchIndex ^ O.network--cloneOpts :: DarcsOption a-             (Maybe String-              -> CloneKind-              -> [O.MatchFlag]-              -> Maybe Bool-              -> O.SetScriptsExecutable-              -> O.WithWorkingDir-              -> Maybe O.StdCmdAction-              -> Bool-              -> Bool-              -> O.Verbosity-              -> Bool-              -> Bool-              -> O.WithPatchIndex-              -> O.NetworkOptions-              -> O.UseCache-              -> Maybe String-              -> Bool-              -> Maybe String-              -> Bool-              -> a)-cloneOpts = cloneBasicOpts `withStdOpts` cloneAdvancedOpts- clone :: DarcsCommand [DarcsFlag] clone = DarcsCommand     { commandProgramName = "darcs"@@ -167,7 +125,7 @@     , commandExtraArgHelp = ["<REPOSITORY>", "[<DIRECTORY>]"]     , commandCommand = cloneCmd     , commandPrereq = validContextFile-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc cloneAdvancedOpts     , commandBasicOptions = odesc cloneBasicOpts@@ -175,6 +133,16 @@     , commandCheckOptions = ocheck cloneOpts     , commandParseOptions = onormalise cloneOpts     }+  where+    cloneBasicOpts+      = O.reponame+      ^ O.cloneKind+      ^ O.matchOneContext+      ^ O.setDefault+      ^ O.setScriptsExecutable+      ^ O.withWorkingDir+    cloneAdvancedOpts = O.usePacks ^ O.patchIndexNo ^ O.network+    cloneOpts = cloneBasicOpts `withStdOpts` cloneAdvancedOpts  get :: DarcsCommand [DarcsFlag] get = commandAlias "get" Nothing clone@@ -199,7 +167,7 @@   debugMessage "Starting work on clone..."   typed_repodir <- ioAbsoluteOrRemote inrepodir   let repodir = toPath typed_repodir-  unless (Quiet `elem` opts) $ showMotd repodir+  unless (quiet opts) $ showMotd repodir   rfsource <- identifyRepoFormat repodir   debugMessage $ "Found the format of "++repodir++"..." @@ -226,61 +194,63 @@       withTempDir "clone" $ \_ -> do          putInfo opts $ text "Creating local clone..."          currentDir <- getCurrentDirectory-         cloneRepository repodir "local" (verbosity opts) (useCache opts)-                         CompleteClone (umask opts) (remoteDarcs opts)-                         (setScriptsExecutable opts)-                         (remoteRepos opts) (NoSetDefault True)-                         (toMatchFlags $ map convertUpToToOne opts)+         mysimplename <- makeRepoName True [] repodir -- give correct name to local clone+         cloneRepository repodir mysimplename (verbosity ? opts) (useCache ? opts)+                         CompleteClone (umask ? opts) (remoteDarcs opts)+                         (setScriptsExecutable ? opts)+                         (remoteRepos ? opts) (NoSetDefault True)+                         (matchAny ? map convertUpToToOne opts)                          rfsource-                         (withWorkingDir opts)-                         (runPatchIndex opts)-                         (usePacks opts)+                         (withWorkingDir ? opts)+                         (patchIndexNo ? opts)+                         (usePacks ? opts)                          YesForgetParent          setCurrentDirectory currentDir          (scp, args) <- getSSH SCP-         putInfo opts $ text "Transferring clone by SCP..."-         r <- exec scp (args ++ ["-r", "local", repo]) (AsIs,AsIs,AsIs)-         when (r /= ExitSuccess) $ fail $ "Problem during SCP transfer."+         putInfo opts $ text $ "Transferring clone using " ++ scp ++ "..."+         r <- exec scp (args ++ ["-r", mysimplename ++ "/", repo]) (AsIs,AsIs,AsIs)+         when (r /= ExitSuccess) $ fail $ "Problem during " ++ scp ++ " transfer."          putInfo opts $ text "Cloning and transferring successful."     Nothing -> do       mysimplename <- makeRepoName True opts repodir-      cloneRepository repodir mysimplename (verbosity opts) (useCache opts)-                  (cloneKind opts) (umask opts) (remoteDarcs opts)-                  (setScriptsExecutable opts)-                  (remoteRepos opts) (setDefault True opts)-                  (toMatchFlags $ map convertUpToToOne opts)+      cloneRepository repodir mysimplename (verbosity ? opts) (useCache ? opts)+                  (cloneKind ? opts) (umask ? opts) (remoteDarcs opts)+                  (setScriptsExecutable ? opts)+                  (remoteRepos ? opts) (setDefault True opts)+                  (matchAny ? map convertUpToToOne opts)                   rfsource-                  (withWorkingDir opts)-                  (runPatchIndex opts)-                  (usePacks opts)+                  (withWorkingDir ? opts)+                  (patchIndexNo ? opts)+                  (usePacks ? opts)                   NoForgetParent       putInfo opts $ text "Finished cloning."  cloneCmd _ _ _ = fail "You must provide 'clone' with either one or two arguments."  cloneToSSH :: [DarcsFlag] -> Maybe String-cloneToSSH fs = case parseFlags O.reponame fs of+cloneToSSH fs = case O.reponame ? fs of   Nothing -> Nothing   Just r -> if isSshUrl r then Just r else Nothing  makeRepoName :: Bool -> [DarcsFlag] -> FilePath -> IO String-makeRepoName talkative dfs d =- case [ n | NewRepo n <- dfs] of-  (n:_) ->-    do exists <- doesDirectoryExist n-       file_exists <- doesFileExist n-       if exists || file_exists-          then fail $ "Directory or file named '" ++ n ++ "' already exists."-          else return n-  [] ->-    case dropWhile (=='.') $ reverse $-         takeWhile (\c -> c /= '/' && c /= ':') $-         dropWhile (=='/') $ reverse d of-      ""   -> getUniqueRepositoryName talkative "anonymous_repo"-      base@('/':_) -> getUniqueRepositoryName talkative base -- Absolute-      base -> do -- Relative-              cwd <- getCurrentDirectory-              getUniqueRepositoryName talkative (cwd ++ "/" ++ base)+makeRepoName talkative fs d =+  case O.reponame ? fs of+    Just n -> do+      exists <- doesDirectoryExist n+      file_exists <- doesFileExist n+      if exists || file_exists+        then fail $ "Directory or file named '" ++ n ++ "' already exists."+        else return n+    Nothing ->+      case mkName d of+        "" -> getUniqueRepositoryName talkative "anonymous_repo"+        base@('/':_) -> getUniqueRepositoryName talkative base -- Absolute+        base -- Relative+         -> do+          cwd <- getCurrentDirectory+          getUniqueRepositoryName talkative (cwd ++ "/" ++ base)+      where mkName = dropWhile (== '.') . reverse .+              takeWhile (not . (`elem` "/:")) . dropWhile (== '/') . reverse  cloneHelpTag :: String cloneHelpTag =@@ -330,11 +300,14 @@              else return . Left $                  "Context file " ++ ctxFilePath ++ " does not exist" +-- TODO getContext choses arbitrarily the first --context flag+-- should instead report an error when more than one is given+ -- | 'getContext' takes a list of flags and returns the context -- specified by @Context c@ in that list of flags, if any. -- This flag is present if darcs was invoked with @--context=FILE@ getContext :: [DarcsFlag] -> Maybe AbsolutePath-getContext fs = listToMaybe [ f | O.Context f <- toMatchFlags fs ]+getContext fs = listToMaybe [ f | O.Context f <- O.context ? fs ]  -- The 'clone' command takes --to-patch and --to-match as arguments, -- but internally wants to handle them as if they were --patch and --match@@ -343,4 +316,5 @@ convertUpToToOne :: DarcsFlag -> DarcsFlag convertUpToToOne (UpToPattern p) = OnePattern p convertUpToToOne (UpToPatch p) = OnePatch p+convertUpToToOne (UpToHash p) = OneHash p convertUpToToOne f = f
src/Darcs/UI/Commands/Convert.hs view
@@ -15,7 +15,7 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, MagicHash, OverloadedStrings #-}+{-# LANGUAGE MagicHash, OverloadedStrings #-}  module Darcs.UI.Commands.Convert ( convert ) where @@ -23,8 +23,11 @@ import Darcs.Prelude hiding ( readFile, lex )  import System.FilePath.Posix ( (</>) )-import System.Directory ( setCurrentDirectory, doesDirectoryExist, doesFileExist,-                   createDirectory, removeFile )+import System.Directory+    ( doesDirectoryExist+    , doesFileExist+    , removeFile+    ) import System.IO ( stdin ) import Data.IORef ( newIORef, modifyIORef, readIORef ) import Data.Char ( isSpace )@@ -35,7 +38,6 @@ import Control.Exception ( finally ) import Control.Applicative ( (<|>) ) -import GHC.Base ( unsafeCoerce# ) import System.Time ( toClockTime ) import Data.Maybe ( catMaybes, fromMaybe ) import qualified Data.IntMap as M@@ -49,6 +51,7 @@ import qualified Data.Attoparsec.ByteString.Char8 as A import Data.Attoparsec.ByteString.Char8( (<?>) ) +import Darcs.Util.ByteString ( decodeLocale ) import qualified Darcs.Util.Tree as T import qualified Darcs.Util.Tree.Monad as TM import Darcs.Util.Tree.Monad hiding ( createDirectory, exists, rename )@@ -57,14 +60,14 @@                       , emptyTree, listImmediate, findTree ) import Darcs.Util.Path( anchorPath, appendPath, floatPath                       , parent, anchoredRoot-                      , AnchoredPath(..), Name(..)+                      , AnchoredPath(..), makeName                       , ioAbsoluteOrRemote, toPath, AbsolutePath ) import Darcs.Util.Hash( encodeBase16, sha256, Hash(..) )  import Darcs.Util.DateTime ( formatDateTime, fromClockTime, parseDateTime, startOfTime ) import Darcs.Util.Global ( darcsdir )-import Darcs.Util.File ( withCurrentDirectory ) import Darcs.Util.Exception ( clarifyErrors )+import Darcs.Util.Lock ( withNewDirectory ) import Darcs.Util.Prompt ( askUser ) import Darcs.Util.Printer ( text, ($$) ) import Darcs.Util.Printer.Color ( traceDoc )@@ -72,10 +75,9 @@  import Darcs.Patch.Depends ( getUncovered ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, n2pia, info, hopefully )-import Darcs.Patch ( IsRepoType, showPatch, fromPrim, fromPrims,-                     effect,-                     RepoPatch, apply, listTouchedFiles-                   , move )+import Darcs.Patch+    ( showPatch, ShowPatchFor(..), fromPrim, fromPrims+    , effect, RepoPatch, apply, listTouchedFiles, move ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.Effect ( Effect ) import Darcs.Patch.Named@@ -86,63 +88,74 @@ import qualified Darcs.Patch.Named.Wrapped as Wrapped ( getdeps ) import Darcs.Patch.Witnesses.Eq ( EqCheck(..), (=/\=) ) import Darcs.Patch.Witnesses.Ordered-    ( FL(..), RL(..), bunchFL, mapFL, mapFL_FL,+    ( FL(..), RL(..), bunchFL, mapFL_FL,     concatFL, mapRL, nullFL, (+>+), (+<+)-    , reverseRL, reverseFL )+    , reverseRL, reverseFL, foldFL_M ) import Darcs.Patch.Witnesses.Sealed ( FlippedSeal(..), Sealed(..), unFreeLeft-                                    ,  flipSeal, unsafeUnsealFlipped )+                                    , mapSeal, flipSeal, unsafeUnsealFlipped )+ import Darcs.Patch.Info ( piRename, piTag, isTag, PatchInfo, patchinfo,                           piName, piLog, piDate, piAuthor, makePatchname )-import Darcs.Patch.V1 ( RepoPatchV1 )-import Darcs.Patch.V2 ( RepoPatchV2 )+import qualified Darcs.Patch.V1 as V1 ( RepoPatchV1 )+import qualified Darcs.Patch.V1.Prim as V1 ( Prim(..) )+import qualified Darcs.Patch.V2 as V2 ( RepoPatchV2 )+import qualified Darcs.Patch.V2.Prim as V2 ( Prim(..) ) import Darcs.Patch.V1.Commute ( publicUnravel )-import Darcs.Patch.V1.Core ( RepoPatchV1(PP), isMerger )+import qualified Darcs.Patch.V1.Core as V1 ( RepoPatchV1(PP), isMerger ) import Darcs.Patch.V2.RepoPatch ( mergeUnravelled ) import Darcs.Patch.Prim ( sortCoalesceFL ) import Darcs.Patch.Prim.Class ( PrimOf )-import Darcs.Patch.Prim.V1 ( Prim )-import Darcs.Patch.RepoType ( RepoType(..), RebaseType(..) )-import Darcs.Patch.Set ( PatchSet(..), Tagged(..), newset2RL, newset2FL )+import Darcs.Patch.RepoType ( RepoType(..), IsRepoType(..), RebaseType(..) )+import Darcs.Patch.Set ( PatchSet(..), Tagged(..), patchSet2RL, patchSet2FL ) import Darcs.Patch.Progress ( progressFL ) -import Darcs.Repository.Flags ( UpdateWorking(..), Reorder (..), UseIndex(..), ScanKnown(..)-                              , AllowConflicts(..), ExternalMerge(..), WantGuiPause(..), PatchFormat(..)-                              , Compression(..), DryRun(NoDryRun), DiffAlgorithm(MyersDiff, PatienceDiff) )-import Darcs.Repository ( Repository, withRepoLock, RepoJob(..), withRepositoryDirectory,-                          createRepository, invalidateIndex,-                          tentativelyMergePatches,-                          createPristineDirectoryTree,-                          revertRepositoryChanges, finalizeRepositoryChanges,-                          applyToWorking-                        , readRepo, readTentativeRepo, cleanRepository )+import Darcs.Repository.Flags+    ( UpdateWorking(..)+    , Compression(..)+    , DiffAlgorithm(PatienceDiff) )+import Darcs.Repository+    ( Repository, RepoJob(..), withRepositoryLocation+    , createRepository, invalidateIndex, repoLocation+    , createPristineDirectoryTree, repoCache+    , revertRepositoryChanges, finalizeRepositoryChanges+    , applyToWorking, repoLocation, repoCache+    , readRepo, readTentativeRepo, cleanRepository+    , createRepositoryV2, EmptyRepository(..)+    , withUMaskFlag+    ) import qualified Darcs.Repository as R( setScriptsExecutable )+import Darcs.Repository.InternalTypes ( coerceR ) import Darcs.Repository.State( readRecorded ) import Darcs.Repository.Cache ( HashedDir( HashedPristineDir ) )-import Darcs.Repository.InternalTypes ( extractCache )-import Darcs.Repository.HashedRepo ( readHashedPristineRoot, addToTentativeInventory )+import Darcs.Repository.Hashed+    ( tentativelyAddPatch_+    , UpdatePristine(..)+    , readHashedPristineRoot+    , addToTentativeInventory ) import Darcs.Repository.HashedIO ( cleanHashdir )-import Darcs.Repository.Prefs( FileType(..) )+import Darcs.Repository.Prefs( FileType(..), showMotd ) import Darcs.Repository.Format(identifyRepoFormat, formatHas, RepoProperty(Darcs2))-import Darcs.Repository.Motd ( showMotd )-import Darcs.Util.Lock ( writeBinFile ) import Darcs.Util.External ( fetchFilePS, Cachable(Uncachable) ) import Darcs.Repository.Diff( treeDiff )   import Darcs.UI.External ( catchall ) import Darcs.UI.Flags-    ( verbosity, useCache, umask, withWorkingDir, runPatchIndex+    ( verbosity, useCache, umask, withWorkingDir, patchIndexNo     , DarcsFlag ( NewRepo )-    , getRepourl, patchFormat+    , getRepourl, patchFormat, quiet     ) import Darcs.UI.Commands ( DarcsCommand(..), amInRepository, nodefaults, putInfo                          , normalCommand, withStdOpts ) import Darcs.UI.Commands.Util.Tree ( treeHasDir, treeHasFile )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags, parseFlags )+import Darcs.UI.Completion ( noArgs )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O -#include "impossible.h"+type RepoPatchV1 = V1.RepoPatchV1 V1.Prim+type RepoPatchV2 = V2.RepoPatchV2 V2.Prim + convertDescription :: String convertDescription = "Convert repositories between various formats." @@ -212,46 +225,19 @@  ]  convert :: DarcsCommand [DarcsFlag]-convert = SuperCommand {-      commandProgramName = "darcs"+convert = SuperCommand+    { commandProgramName = "darcs"     , commandName = "convert"     , commandHelp = ""     , commandDescription = convertDescription     , commandPrereq = amInRepository-    , commandSubCommands = [  normalCommand convertDarcs2,-                              normalCommand convertExport,-                              normalCommand convertImport-                           ]+    , commandSubCommands =+        [ normalCommand convertDarcs2+        , normalCommand convertExport+        , normalCommand convertImport+        ]     } -convertDarcs2BasicOpts :: DarcsOption a (Maybe String -> O.SetScriptsExecutable -> O.WithWorkingDir -> a)-convertDarcs2BasicOpts = O.reponame ^ O.setScriptsExecutable ^ O.useWorkingDir--convertDarcs2AdvancedOpts :: DarcsOption a (O.NetworkOptions -> O.WithPatchIndex -> a)-convertDarcs2AdvancedOpts = O.network ^ O.patchIndex--convertDarcs2Opts :: DarcsOption a-                     (Maybe String-                      -> O.SetScriptsExecutable-                      -> O.WithWorkingDir-                      -> Maybe O.StdCmdAction-                      -> Bool-                      -> Bool-                      -> O.Verbosity-                      -> Bool-                      -> O.NetworkOptions-                      -> O.WithPatchIndex-                      -> O.UseCache-                      -> Maybe String-                      -> Bool-                      -> Maybe String-                      -> Bool-                      -> a)-convertDarcs2Opts = convertDarcs2BasicOpts `withStdOpts` convertDarcs2AdvancedOpts--convertDarcs2SilentOpts :: DarcsOption a (O.PatchFormat -> a)-convertDarcs2SilentOpts = O.patchFormat- convertDarcs2 :: DarcsCommand [DarcsFlag] convertDarcs2 = DarcsCommand     { commandProgramName = "darcs"@@ -262,7 +248,7 @@     , commandExtraArgHelp = ["<SOURCE>", "[<DESTINATION>]"]     , commandCommand = toDarcs2     , commandPrereq = \_ -> return $ Right ()-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc convertDarcs2AdvancedOpts     , commandBasicOptions = odesc convertDarcs2BasicOpts@@ -270,31 +256,11 @@     , commandCheckOptions = ocheck convertDarcs2Opts     , commandParseOptions = onormalise convertDarcs2Opts     }--convertExportBasicOpts :: DarcsOption a-                          (Maybe String -> Maybe String -> Maybe String -> a)-convertExportBasicOpts = O.reponame ^ O.marks--convertExportAdvancedOpts :: DarcsOption a (O.NetworkOptions -> a)-convertExportAdvancedOpts = O.network--convertExportOpts :: DarcsOption a-                     (Maybe String-                      -> Maybe String-                      -> Maybe String-                      -> Maybe O.StdCmdAction-                      -> Bool-                      -> Bool-                      -> O.Verbosity-                      -> Bool-                      -> O.NetworkOptions-                      -> O.UseCache-                      -> Maybe String-                      -> Bool-                      -> Maybe String-                      -> Bool-                      -> a)-convertExportOpts = convertExportBasicOpts `withStdOpts` convertExportAdvancedOpts+  where+    convertDarcs2BasicOpts = O.reponame ^ O.setScriptsExecutable ^ O.withWorkingDir+    convertDarcs2AdvancedOpts = O.network ^ O.patchIndexNo+    convertDarcs2Opts = convertDarcs2BasicOpts `withStdOpts` convertDarcs2AdvancedOpts+    convertDarcs2SilentOpts = O.patchFormat  convertExport :: DarcsCommand [DarcsFlag] convertExport = DarcsCommand@@ -306,7 +272,7 @@     , commandExtraArgHelp = []     , commandCommand = fastExport     , commandPrereq = amInRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc convertExportAdvancedOpts     , commandBasicOptions = odesc convertExportBasicOpts@@ -314,40 +280,10 @@     , commandCheckOptions = ocheck convertExportOpts     , commandParseOptions = onormalise convertExportOpts     }--convertImportBasicOpts :: DarcsOption a-                          (Maybe String-                           -> O.SetScriptsExecutable-                           -> O.PatchFormat-                           -> O.WithWorkingDir-                           -> a)-convertImportBasicOpts-  = O.reponame-  ^ O.setScriptsExecutable-  ^ O.patchFormat-  ^ O.useWorkingDir--convertImportAdvancedOpts :: DarcsOption a (O.WithPatchIndex -> a)-convertImportAdvancedOpts = O.patchIndex--convertImportOpts :: DarcsOption a-                     (Maybe String-                      -> O.SetScriptsExecutable-                      -> O.PatchFormat-                      -> O.WithWorkingDir-                      -> Maybe O.StdCmdAction-                      -> Bool-                      -> Bool-                      -> O.Verbosity-                      -> Bool-                      -> O.WithPatchIndex-                      -> O.UseCache-                      -> Maybe String-                      -> Bool-                      -> Maybe String-                      -> Bool-                      -> a)-convertImportOpts = convertImportBasicOpts `withStdOpts` convertImportAdvancedOpts+  where+    convertExportBasicOpts = O.reponame ^ O.marks+    convertExportAdvancedOpts = O.network+    convertExportOpts = convertExportBasicOpts `withStdOpts` convertExportAdvancedOpts  convertImport :: DarcsCommand [DarcsFlag] convertImport = DarcsCommand@@ -359,7 +295,7 @@     , commandExtraArgHelp = ["[<DIRECTORY>]"]     , commandCommand = fastImport     , commandPrereq = \_ -> return $ Right ()-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc convertImportAdvancedOpts     , commandBasicOptions = odesc convertImportBasicOpts@@ -367,15 +303,25 @@     , commandCheckOptions = ocheck convertImportOpts     , commandParseOptions = onormalise convertImportOpts     }+  where+    convertImportBasicOpts+      = O.reponame+      ^ O.setScriptsExecutable+      ^ O.patchFormat+      ^ O.withWorkingDir+    convertImportAdvancedOpts = O.patchIndexNo+    convertImportOpts = convertImportBasicOpts `withStdOpts` convertImportAdvancedOpts  toDarcs2 :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-toDarcs2 fps opts [inrepodir, outname] = toDarcs2 fps (NewRepo outname:opts) [inrepodir]-toDarcs2 _ opts [inrepodir] = do-+toDarcs2 _ opts' args = do+  (inrepodir, opts) <-+    case args of+      [arg1, arg2] -> return (arg1, NewRepo arg2:opts')+      [arg1] -> return (arg1, opts')+      _ -> fail "You must provide either one or two arguments."   typed_repodir <- ioAbsoluteOrRemote inrepodir   let repodir = toPath typed_repodir -  --test for converting darcs-2 repository   format <- identifyRepoFormat repodir   when (formatHas Darcs2 format) $ fail "Repository is already in darcs 2 format." @@ -385,42 +331,46 @@   vow' <- askUser ("by typing `" ++ vow ++ "': ")   when (vow' /= vow) $ fail "User didn't understand the consequences." -  unless (parseFlags O.verbosity opts == O.Quiet) $ showMotd repodir+  unless (quiet opts) $ showMotd repodir+   mysimplename <- makeRepoName opts repodir-  createDirectory mysimplename-  setCurrentDirectory mysimplename-  createRepository PatchFormat2 (withWorkingDir opts) (runPatchIndex opts)-  writeBinFile (darcsdir++"/hashed_inventory") ""-  withRepoLock NoDryRun (useCache opts) NoUpdateWorking (umask opts) $ V2Job $ \repository ->-    withRepositoryDirectory (useCache opts) repodir $ V1Job $ \themrepo -> do-      theirstuff <- readRepo themrepo-      let patches = mapFL_FL (convertNamed . hopefully) $ newset2FL theirstuff-          outOfOrderTags = catMaybes $ mapRL oot $ newset2RL theirstuff+  withUMaskFlag (umask ? opts) $ withNewDirectory mysimplename $ do+    repo <- createRepositoryV2+      (withWorkingDir ? opts) (patchIndexNo ? opts) (O.useCache ? opts)+    revertRepositoryChanges repo NoUpdateWorking++    withRepositoryLocation (useCache ? opts) repodir $ V1Job $ \other -> do+      theirstuff <- readRepo other+      let patches = mapFL_FL (convertNamed . hopefully) $ patchSet2FL theirstuff+          outOfOrderTags = catMaybes $ mapRL oot $ patchSet2RL theirstuff               where oot t = if isTag (info t) && info t `notElem` inOrderTags theirstuff                             then Just (info t, Wrapped.getdeps $ hopefully t)                             else Nothing           fixDep p = case lookup p outOfOrderTags of                      Just d -> p : concatMap fixDep d                      Nothing -> [p]-          convertOne :: RepoPatchV1 Prim wX wY -> FL (RepoPatchV2 Prim) wX wY-          convertOne x | isMerger x = case mergeUnravelled $ publicUnravel x of-                                       Just (FlippedSeal y) ->-                                           case effect y =/\= effect x of-                                           IsEq -> y :>: NilFL-                                           NotEq ->-                                               traceDoc (text "lossy conversion:" $$-                                                         showPatch x)-                                               fromPrims (effect x)-                                       Nothing -> traceDoc (text-                                                            "lossy conversion of complicated conflict:" $$-                                                            showPatch x)-                                                  fromPrims (effect x)-          convertOne (PP x) = fromPrim x :>: NilFL+          primV1toV2 = V2.Prim . V1.unPrim+          convertOne :: RepoPatchV1 wX wY -> FL RepoPatchV2 wX wY+          convertOne x | V1.isMerger x =+            let ex = mapFL_FL primV1toV2 (effect x) in+            case mergeUnravelled $ map (mapSeal (mapFL_FL primV1toV2)) $ publicUnravel x of+             Just (FlippedSeal y) ->+                 case effect y =/\= ex of+                 IsEq -> y :>: NilFL+                 NotEq ->+                     traceDoc (text "lossy conversion:" $$+                               showPatch ForDisplay x)+                     fromPrims ex+             Nothing -> traceDoc (text+                                  "lossy conversion of complicated conflict:" $$+                                  showPatch ForDisplay x)+                        fromPrims ex+          convertOne (V1.PP x) = fromPrim (primV1toV2 x) :>: NilFL           convertOne _ = impossible-          convertFL :: FL (RepoPatchV1 Prim) wX wY -> FL (RepoPatchV2 Prim) wX wY+          convertFL :: FL RepoPatchV1 wX wY -> FL RepoPatchV2 wX wY           convertFL = concatFL . mapFL_FL convertOne-          convertNamed :: WrappedNamed ('RepoType 'NoRebase) (RepoPatchV1 Prim) wX wY-                       -> PatchInfoAnd ('RepoType 'NoRebase) (RepoPatchV2 Prim) wX wY+          convertNamed :: WrappedNamed ('RepoType 'NoRebase) RepoPatchV1 wX wY+                       -> PatchInfoAnd ('RepoType 'NoRebase) RepoPatchV2 wX wY           convertNamed (NormalP n)                          = n2pia $ NormalP $                            adddeps (infopatch (convertInfo $ patch2patchinfo n) $@@ -428,24 +378,9 @@                                    (map convertInfo $ concatMap fixDep $ getdeps n)           convertInfo n | n `elem` inOrderTags theirstuff = n                         | otherwise = maybe n (\t -> piRename n ("old tag: "++t)) $ piTag n-          applySome xs = do -- TODO this unsafeCoerce hack is because we don't keep track of the repository state properly-                            -- Really sequence_ $ mapFL applySome below should instead be a repeated add operation --                            -- there doesn't seem to be any reason we need to do a merge here.-                            let repository2 = unsafeCoerce# repository :: Repository ('RepoType 'NoRebase) (RepoPatchV2 Prim) wA wB wA-                            Sealed pw <- tentativelyMergePatches repository2 "convert"-                                             YesAllowConflicts NoUpdateWorking-                                             NoExternalMerge NoWantGuiPause-                                             GzipCompression (verbosity opts)-                                             NoReorder-                                             (UseIndex, ScanKnown, MyersDiff)-                                             NilFL xs-                            finalizeRepositoryChanges repository2 NoUpdateWorking GzipCompression -- this is to clean out pristine.hashed-                            revertRepositoryChanges repository2 NoUpdateWorking-                            _ <- revertable $ applyToWorking repository2 (verbosity opts) pw-                            invalidateIndex repository2-      sequence_ $ mapFL applySome $ bunchFL 100 $ progressFL "Converting patch" patches-      invalidateIndex repository-      revertable $ createPristineDirectoryTree repository "." (withWorkingDir opts)++      -- Note: we use bunchFL so we can commit every 100 patches+      _ <- applyAll opts repo $ bunchFL 100 $ progressFL "Converting patch" patches       when (parseFlags O.setScriptsExecutable opts == O.YesSetScriptsExecutable)         R.setScriptsExecutable @@ -455,13 +390,71 @@        `catchall` return ()        putInfo opts $ text "Finished converting."-      where revertable x = x `clarifyErrors` unlines-                  ["An error may have left your new working directory an inconsistent",-                   "but recoverable state. You should be able to make the new",-                   "repository consistent again by running darcs revert -a."]+  where+    applyOne :: (RepoPatch p, ApplyState p ~ Tree)+             => [DarcsFlag]+             -> W2 (Repository rt p wR) wX+             -> PatchInfoAnd rt p wX wY+             -> IO (W2 (Repository rt p wR) wY)+    applyOne opts (W2 r) x = do+      r' <- tentativelyAddPatch_ (updatePristine opts) r+        GzipCompression (verbosity ? opts) (updateWorking opts) x+      r'' <- withTryAgainMsg $ applyToWorking r' (verbosity ? opts) (effect x)+      invalidateIndex r''+      return (W2 r'') -toDarcs2 _ _ _ = fail "You must provide either one or two arguments."+    applySome opts (W3 r) xs = do+      r' <- unW2 <$> foldFL_M (applyOne opts) (W2 r) xs+      -- commit after applying a bunch of patches+      finalizeRepositoryChanges r' (updateWorking opts) GzipCompression+      revertRepositoryChanges r' (updateWorking opts)+      -- finalizeRepositoryChanges and revertRepositoryChanges+      -- do not (yet?) return a repo with properly coerced witnesses.+      -- We should have+      --+      -- > finalizeRepositoryChanges :: ... wR wU wT -> ... wT wU wT+      --+      -- and+      --+      -- > revertRepositoryChanges :: ... wR wU wT -> ... wR wU wR+      --+      -- This is why we must coerce here:+      return (W3 (coerceR r')) +    applyAll :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+             => [DarcsFlag]+             -> Repository rt p wX wX wX+             -> FL (FL (PatchInfoAnd rt p)) wX wY+             -> IO (Repository rt p wY wY wY)+    applyAll opts r xss = unW3 <$> foldFL_M (applySome opts) (W3 r) xss++    updatePristine :: [DarcsFlag] -> UpdatePristine+    updatePristine opts =+      case withWorkingDir ? opts of+        O.WithWorkingDir -> UpdatePristine+        -- this should not be necessary but currently is, because+        -- some commands (e.g. send) cannot cope with a missing pristine+        -- even if the repo is marked as having no working tree+        O.NoWorkingDir -> {- DontUpdatePristineNorRevert -}UpdatePristine++    updateWorking :: [DarcsFlag] -> UpdateWorking+    updateWorking opts =+      case withWorkingDir ? opts of+        O.WithWorkingDir -> YesUpdateWorking+        O.NoWorkingDir -> NoUpdateWorking++    withTryAgainMsg :: IO a -> IO a+    withTryAgainMsg x = x `clarifyErrors` unlines+      [ "An error occurred while applying patches to the working tree."+      , "You may have more luck if you supply --no-working-dir." ]++-- | Need this to make 'foldFL_M' work with a function that changes+-- the last two (identical) witnesses at the same time.+newtype W2 r wX = W2 {unW2 :: r wX wX}++-- | Similarly for when the function changes all three witnesses.+newtype W3 r wX = W3 {unW3 :: r wX wX wX}+ makeRepoName :: [DarcsFlag] -> FilePath -> IO String makeRepoName (NewRepo n:_) _ =     do exists <- doesDirectoryExist n@@ -503,7 +496,7 @@   marks <- case parseFlags O.readMarks opts of     Nothing -> return emptyMarks     Just f  -> readMarks f-  newMarks <- withRepositoryDirectory (useCache opts) repodir $ RepoJob $ \repo -> fastExport' repo marks+  newMarks <- withRepositoryLocation (useCache ? opts) repodir $ RepoJob $ \repo -> fastExport' repo marks   case parseFlags O.writeMarks opts of     Nothing -> return ()     Just f  -> writeMarks f newMarks@@ -514,7 +507,7 @@   putStrLn "progress (reading repository)"   patchset <- readRepo repo   marksref <- newIORef marks-  let patches = newset2FL patchset+  let patches = patchSet2FL patchset       tags = inOrderTags patchset       mark :: (PatchInfoAnd rt p) x y -> Int -> TreeIO ()       mark p n = liftIO $ do putStrLn $ "mark :" ++ show n@@ -543,7 +536,7 @@  `finally` do   putStrLn "progress (cleaning up)"   current <- readHashedPristineRoot repo-  cleanHashdir (extractCache repo) HashedPristineDir $ catMaybes [current]+  cleanHashdir (repoCache repo) HashedPristineDir $ catMaybes [current]   putStrLn "progress done"  dumpPatches ::  (RepoPatch p, ApplyState p ~ Tree)@@ -623,7 +616,7 @@           -> (PatchInfoAnd rt p) x y -> Int           -> TreeIO () dumpPatch mark p n =-  do dumpBits [ BLC.pack $ "progress " ++ show n ++ ": " ++ piName (info p)+  do dumpBits [ BLU.fromString $ "progress " ++ show n ++ ": " ++ piName (info p)               , "commit refs/heads/master" ]      mark p n      dumpBits [ BLU.fromString $ "committer " ++ patchAuthor p ++ " " ++ patchDate p@@ -722,14 +715,16 @@  fastImport :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () fastImport _ opts [outrepo] =-  do createDirectory outrepo-     withCurrentDirectory outrepo $ do-       createRepository (patchFormat opts) (withWorkingDir opts) (runPatchIndex opts)-       withRepoLock NoDryRun (useCache opts) NoUpdateWorking (umask opts) $ RepoJob $ \repo -> do-         -- TODO implement --dry-run, which would be read-only?-         marks <- fastImport' repo emptyMarks-         createPristineDirectoryTree repo "." (withWorkingDir opts)-         return marks+  withUMaskFlag (umask ? opts) $ withNewDirectory outrepo $ do+    EmptyRepository repo <- createRepository+      (patchFormat ? opts)+      (withWorkingDir ? opts)+      (patchIndexNo ? opts)+      (useCache ? opts)+    -- TODO implement --dry-run, which would be read-only?+    marks <- fastImport' repo emptyMarks+    createPristineDirectoryTree repo "." (withWorkingDir ? opts)+    return marks fastImport _ _ _ = fail "I need exactly one output repository."  fastImport' :: forall rt p r u . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) =>@@ -749,8 +744,8 @@         -- sort marks into buckets, since there can be a *lot* of them         markpath :: Int -> AnchoredPath         markpath n = floatPath (darcsdir </> "marks")-                        `appendPath` (Name $ BC.pack $ show (n `div` 1000))-                        `appendPath` (Name $ BC.pack $ show (n `mod` 1000))+                        `appendPath` (makeName $ show (n `div` 1000))+                        `appendPath` (makeName $ show (n `mod` 1000))          makeinfo author message tag = do           let (name, log) = case BC.unpack message of@@ -765,16 +760,18 @@         addtag author msg =           do info_ <- makeinfo author msg True              gotany <- liftIO $ doesFileExist $ darcsdir </> "tentative_hashed_pristine"-             deps <- if gotany then liftIO $ getUncovered `fmap` readTentativeRepo repo+             deps <- if gotany then liftIO $+                                      getUncovered `fmap`+                                        readTentativeRepo repo (repoLocation repo)                                else return []-             let ident = NilFL :: FL (RepoPatchV2 Prim) cX cX+             let ident = NilFL :: FL RepoPatchV2 cX cX                  patch = NormalP (adddeps (infopatch info_ ident) deps)-             void $ liftIO $ addToTentativeInventory (extractCache repo)+             void $ liftIO $ addToTentativeInventory (repoCache repo)                                                      GzipCompression (n2pia patch)          -- processing items         updateHashes = do-          let nodarcs = \(AnchoredPath (Name x:_)) _ -> x /= BC.pack darcsdir+          let nodarcs = \(AnchoredPath (x:_)) _ -> x /= makeName darcsdir               hashblobs (File blob@(T.Blob con NoHash)) =                 do hash <- sha256 `fmap` readBlob blob                    return $ File (T.Blob con hash)@@ -809,7 +806,7 @@          process :: State p -> Object -> TreeIO (State p)         process s (Progress p) = do-          liftIO $ putStrLn ("progress " ++ BC.unpack p)+          liftIO $ putStrLn ("progress " ++ decodeLocale p)           return s          process (Toplevel _ _) End = do@@ -826,7 +823,7 @@           if Just what == n              then addtag author msg              else liftIO $ putStrLn $ "WARNING: Ignoring out-of-order tag " ++-                             head (lines $ BC.unpack msg)+                             head (lines $ decodeLocale msg)           return (Toplevel n b)          process (Toplevel n _) (Reset branch from) =@@ -919,7 +916,7 @@           {- current <- updateHashes -} -- why not?           (prims :: FL p cX cY)  <- return $ fromPrims $ sortCoalesceFL $ reverseRL ps           let patch = NormalP (infopatch info_ ((NilFL :: FL p cX cX) +>+ prims))-          void $ liftIO $ addToTentativeInventory (extractCache repo)+          void $ liftIO $ addToTentativeInventory (repoCache repo)                                                   GzipCompression (n2pia patch)           case mark of             Nothing -> return ()
src/Darcs/UI/Commands/Diff.hs view
@@ -15,8 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.UI.Commands.Diff ( diffCommand, getDiffDoc ) where  import Prelude ()@@ -39,10 +37,9 @@     , execPipeIgnoreError     ) import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository )-import Darcs.UI.Flags-    ( DarcsFlag ( AfterPatch, DiffCmd, LastN )-    , wantGuiPause, useCache, fixSubPaths )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags, parseFlags )+import Darcs.UI.Completion ( knownFileArgs )+import Darcs.UI.Flags ( DarcsFlag, wantGuiPause, useCache, fixSubPaths )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Flags ( WantGuiPause (..), DiffAlgorithm(MyersDiff) ) import Darcs.Patch.PatchInfoAnd ( info, n2pia )@@ -55,22 +52,21 @@     , matchSecondPatchset     ) import Darcs.Repository ( withRepository, RepoJob(..), readRepo )-import Darcs.Repository.State ( readUnrecorded, restrictSubpaths-                              , readRecorded, unrecordedChanges-                              , UseIndex(..), ScanKnown(..), applyTreeFilter )+import Darcs.Repository.State+    ( readUnrecorded, restrictSubpaths+    , readRecorded, unrecordedChanges+    , UseIndex(..), ScanKnown(..), applyTreeFilter+    ) import Darcs.Patch.Witnesses.Ordered ( mapRL, (:>)(..), (+>+), RL(..) ) import Darcs.Patch.Witnesses.Unsafe ( unsafeCoercePEnd ) import Darcs.Patch.Witnesses.Sealed ( unseal, Sealed(..), seal ) import Darcs.Patch ( RepoPatch, IsRepoType, apply, listTouchedFiles, invert, fromPrims ) import Darcs.Patch.Depends ( findCommonWithThem ) import Darcs.Patch.Named.Wrapped ( anonymous )-import Darcs.Patch.Set ( PatchSet(..), newset2RL )-import Darcs.Patch.Info ( PatchInfo, showPatchInfoUI )+import Darcs.Patch.Set ( PatchSet(..), patchSet2RL )+import Darcs.Patch.Info ( PatchInfo, displayPatchInfo ) import Darcs.Util.Lock ( withTempDir )-import Darcs.Util.Printer ( Doc, putDoc, vcat, empty, RenderMode(..), ($$) )--#include "impossible.h"-+import Darcs.Util.Printer ( Doc, putDoc, vcat, empty, ($$) )  diffDescription :: String diffDescription = "Create a diff between two versions of the repository."@@ -110,43 +106,6 @@  "\n" ++  "If this option is used, `--diff-opts` is ignored.\n" -diffBasicOpts :: DarcsOption a-                 ([O.MatchFlag]-                  -> O.ExternalDiff-                  -> Bool-                  -> Maybe String-                  -> Bool-                  -> a)-diffBasicOpts-    = O.matchRange-    ^ O.extDiff-    ^ O.unidiff-    ^ O.workingRepoDir-    ^ O.storeInMemory--diffAdvancedOpts :: DarcsOption a (WantGuiPause -> a)-diffAdvancedOpts = O.pauseForGui--diffOpts :: DarcsOption a-            ([O.MatchFlag]-             -> O.ExternalDiff-             -> Bool-             -> Maybe String-             -> Bool-             -> Maybe O.StdCmdAction-             -> Bool-             -> Bool-             -> O.Verbosity-             -> Bool-             -> WantGuiPause-             -> O.UseCache-             -> Maybe String-             -> Bool-             -> Maybe String-             -> Bool-             -> a)-diffOpts = diffBasicOpts `withStdOpts` diffAdvancedOpts- diffCommand :: DarcsCommand [DarcsFlag] diffCommand = DarcsCommand     { commandProgramName = "darcs"@@ -157,7 +116,7 @@     , commandExtraArgHelp = ["[FILE or DIRECTORY]..."]     , commandCommand = diffCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = knownFileArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc diffAdvancedOpts     , commandBasicOptions = odesc diffBasicOpts@@ -165,11 +124,18 @@     , commandCheckOptions = ocheck diffOpts     , commandParseOptions = onormalise diffOpts     }+  where+    diffBasicOpts+      = O.matchRange+      ^ O.extDiff+      ^ O.repoDir+      ^ O.storeInMemory+    diffAdvancedOpts = O.pauseForGui+    diffOpts = diffBasicOpts `withStdOpts` diffAdvancedOpts -getDiffOpts :: [DarcsFlag] -> [String]-getDiffOpts fs = addUnified $ otherDiffOpts fs where-  addUnified = if parseFlags O.unidiff fs then ("-u":) else id-  otherDiffOpts = O._diffOpts . parseFlags O.extDiff+getDiffOpts :: O.ExternalDiff -> [String]+getDiffOpts O.ExternalDiff {O.diffOpts=os,O.diffUnified=u} = addUnified os where+  addUnified = if u then ("-u":) else id  -- | Returns the command we should use for diff as a tuple (command, arguments). -- This will either be whatever the user specified via --diff-command  or the@@ -177,20 +143,21 @@ -- user's diff-command, hence the possibility for failure with an exception. getDiffCmdAndArgs :: String -> [DarcsFlag] -> String -> String                       -> Either String (String, [String])-getDiffCmdAndArgs cmd opts f1 f2 = helper opts where-  helper (DiffCmd c:_) =-    case parseCmd [ ('1', f1) , ('2', f2) ] c of-    Left err      -> Left $ show err-    Right ([],_)  -> bug "parseCmd should never return empty list"-    Right (h:t,_) -> Right (h,t)-  helper [] = -- if no command specified, use 'diff'-    Right (cmd, "-rN":getDiffOpts opts++[f1,f2])-  helper (_:t) = helper t+getDiffCmdAndArgs cmd opts f1 f2 = helper (O.extDiff ? opts) where+  helper extDiff =+    case O.diffCmd extDiff of+      Just c ->+        case parseCmd [ ('1', f1) , ('2', f2) ] c of+          Left err      -> Left $ show err+          Right ([],_)  -> bug "parseCmd should never return empty list"+          Right (h:t,_) -> Right (h,t)+      Nothing -> -- if no command specified, use 'diff'+        Right (cmd, "-rN":getDiffOpts extDiff++[f1,f2])  diffCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () diffCmd fps opts args-  | not (null [i | LastN i <- opts]) &&-      not (null [p | AfterPatch p <- opts]) =+  | not (null (O.matchLast ? opts)) &&+      not (null (O.matchFrom ? opts)) =         fail $ "using --patch and --last at the same time with the 'diff'" ++           " command doesn't make sense. Use --from-patch to create a diff" ++           " from this patch to the present, or use just '--patch' to view" ++@@ -202,14 +169,16 @@ doDiff opts msubpaths = getDiffDoc opts msubpaths >>= putDoc  getDiffDoc :: [DarcsFlag] -> Maybe [SubPath] ->  IO Doc-getDiffDoc opts msubpaths = withRepository (useCache opts) $ RepoJob $ \repository -> do+getDiffDoc opts msubpaths = withRepository (useCache ? opts) $ RepoJob $ \repository -> do   formerdir <- getCurrentDirectory    let thename = takeFileName formerdir    patchset <- readRepo repository -  unrecorded <- fromPrims `fmap` unrecordedChanges (UseIndex, ScanKnown, MyersDiff) repository msubpaths+  unrecorded <- fromPrims `fmap` unrecordedChanges (UseIndex, ScanKnown, MyersDiff)+    O.NoLookForMoves O.NoLookForReplaces+    repository msubpaths   unrecorded' <- n2pia `fmap` anonymous unrecorded    let matchFlags = parseFlags O.matchRange opts@@ -270,7 +239,7 @@                 let pausingForGui = (wantGuiPause opts == YesWantGuiPause) in                   do when pausingForGui $ putStrLn $                        "Running command '" ++ unwords (d_cmd:d_args) ++ "'"-                     output <- execPipeIgnoreError Encode d_cmd d_args empty+                     output <- execPipeIgnoreError d_cmd d_args empty                      when pausingForGui $                         askEnter "Hit return to move on..."                      return output@@ -278,7 +247,7 @@ getDiffInfo :: (IsRepoType rt, RepoPatch p) => [DarcsFlag] -> PatchSet rt p wStart wX -> [PatchInfo] getDiffInfo opts ps =     let matchFlags = parseFlags O.matchRange opts-        infos = mapRL info . newset2RL+        infos = mapRL info . patchSet2RL         handle (match_cond, do_match)           | match_cond matchFlags = unseal infos (do_match matchFlags ps)           | otherwise = infos ps@@ -286,5 +255,5 @@          \\ handle (firstMatch, matchFirstPatchset)  changelog :: [PatchInfo] -> Doc-changelog pis = vcat $ map showPatchInfoUI pis+changelog pis = vcat $ map displayPatchInfo pis 
src/Darcs/UI/Commands/Dist.hs view
@@ -49,37 +49,40 @@ import Codec.Archive.Zip ( emptyArchive, fromArchive, addEntryToArchive, toEntry ) import Darcs.Util.External ( fetchFilePS, Cachable( Uncachable ) ) import Darcs.Util.Global ( darcsdir )-import Darcs.Repository.HashedRepo ( inv2pris )+import Darcs.Repository.Hashed ( peekPristineHash ) import Darcs.Repository.HashedIO ( pathsAndContents )-import Darcs.Repository.InternalTypes ( Repository (..) ) import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString as B-import Darcs.UI.Flags-    ( DarcsFlag(Verbose, Quiet, DistName, DistZip, SetScriptsExecutable), useCache )+import Darcs.UI.Flags as F ( DarcsFlag, useCache )+import qualified Darcs.UI.Flags as F ( setScriptsExecutable ) import Darcs.UI.Options-    ( DarcsOption, (^), oid, odesc, ocheck, onormalise-    , defaultFlags, parseFlags+    ( (^), oid, odesc, ocheck, onormalise+    , defaultFlags, parseFlags, (?)     ) import qualified Darcs.UI.Options.All as O -import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository )+import Darcs.UI.Commands+    ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository+    , putVerbose, putInfo+    )+import Darcs.UI.Completion ( noArgs ) import Darcs.Util.Lock ( withTempDir ) import Darcs.Patch.Match ( haveNonrangeMatch ) import Darcs.Repository.Match ( getNonrangeMatch )-import Darcs.Repository ( withRepository, withRepositoryDirectory, RepoJob(..),-                          setScriptsExecutable, repoPatchType,+import Darcs.Repository ( withRepository, withRepositoryLocation, RepoJob(..),+                          setScriptsExecutable, repoPatchType, repoCache,                           createPartialsPristineDirectoryTree ) import Darcs.Repository.Prefs ( getPrefval )  import Darcs.Util.DateTime ( getCurrentTime, toSeconds ) import Darcs.Util.Path ( AbsolutePath, toFilePath ) import Darcs.Util.File ( withCurrentDirectory )+import Darcs.Util.Printer ( text, vcat )   distDescription :: String distDescription = "Create a distribution archive." - distHelp :: String distHelp = unlines   [ "`darcs dist` creates a compressed archive in the repository's root"@@ -99,42 +102,6 @@   , "If `--zip` is used, matchers and the predist command are ignored."   ] -distBasicOpts :: DarcsOption a-                 (Maybe String-                  -> Bool-                  -> Maybe String-                  -> [O.MatchFlag]-                  -> O.SetScriptsExecutable-                  -> Bool-                  -> a)-distBasicOpts-    = O.distname-    ^ O.distzip-    ^ O.workingRepoDir-    ^ O.matchUpToOne-    ^ O.setScriptsExecutable-    ^ O.storeInMemory--distOpts :: DarcsOption a-            (Maybe String-             -> Bool-             -> Maybe String-             -> [O.MatchFlag]-             -> O.SetScriptsExecutable-             -> Bool-             -> Maybe O.StdCmdAction-             -> Bool-             -> Bool-             -> O.Verbosity-             -> Bool-             -> O.UseCache-             -> Maybe String-             -> Bool-             -> Maybe String-             -> Bool-             -> a)-distOpts = distBasicOpts `withStdOpts` oid- dist :: DarcsCommand [DarcsFlag] dist = DarcsCommand     { commandProgramName = "darcs"@@ -145,7 +112,7 @@     , commandExtraArgHelp = []     , commandCommand = distCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = odesc distBasicOpts@@ -153,16 +120,22 @@     , commandCheckOptions = ocheck distOpts     , commandParseOptions = onormalise distOpts     }+  where+    distBasicOpts+      = O.distname+      ^ O.distzip+      ^ O.repoDir+      ^ O.matchUpToOne+      ^ O.setScriptsExecutable+      ^ O.storeInMemory+    distOpts = distBasicOpts `withStdOpts` oid -distCmd :: (AbsolutePath, AbsolutePath)-        -> [DarcsFlag]-        -> [String]-        -> IO ()-distCmd _ opts _ | DistZip `elem` opts = doFastZip opts-distCmd _ opts _ = withRepository (useCache opts) $ RepoJob $ \repository -> do+distCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()+distCmd _ opts _ | O.distzip ? opts = doFastZip opts+distCmd _ opts _ = withRepository (useCache ? opts) $ RepoJob $ \repository -> do   let matchFlags = parseFlags O.matchUpToOne opts   formerdir <- getCurrentDirectory-  let distname = getDistName formerdir [x | DistName x <- opts]+  let distname = getDistName formerdir (O.distname ? opts)   predist <- getPrefval "predist"   let resultfile = formerdir </> distname ++ ".tar.gz"   withTempDir "darcsdist" $ \tempdir -> do@@ -174,15 +147,15 @@       ec <- case predist of Nothing -> return ExitSuccess                             Just pd -> system pd       if ec == ExitSuccess-          then-              do-              withCurrentDirectory ddir $-                  when (SetScriptsExecutable `elem` opts) setScriptsExecutable-              doDist opts tempdir ddir resultfile-          else-              do-              putStrLn "Dist aborted due to predist failure"-              exitWith ec+        then do+          withCurrentDirectory ddir $+            when+              (F.setScriptsExecutable ? opts == O.YesSetScriptsExecutable)+              setScriptsExecutable+          doDist opts tempdir ddir resultfile+        else do+          putStrLn "Dist aborted due to predist failure"+          exitWith ec   -- | This function performs the actual distribution action itself.@@ -193,37 +166,36 @@     setCurrentDirectory (toFilePath tempdir)     let safeddir = safename $ takeFileName $ toFilePath ddir     entries <- pack "." [safeddir]-    when (Verbose `elem` opts) $ putStr $ unlines $ map entryPath entries+    putVerbose opts $ vcat $ map (text . entryPath) entries     writeFile resultfile $ compress $ write entries-    when (Quiet `notElem` opts) $ putStrLn $ "Created dist as " ++ resultfile+    putInfo opts $ text $ "Created dist as " ++ resultfile   where     safename n@(c:_) | isAlphaNum c  = n     safename n = "./" ++ n  -getDistName :: FilePath -> [String] -> FilePath-getDistName _ (dn:_) = dn+getDistName :: FilePath -> Maybe String -> FilePath+getDistName _ (Just dn) = dn getDistName currentDirectory _ = takeFileName currentDirectory -doFastZip :: [DarcsFlag]-          -> IO ()+doFastZip :: [DarcsFlag] -> IO () doFastZip opts = do   currentdir <- getCurrentDirectory-  let distname = getDistName currentdir [x | DistName x <- opts]  +  let distname = getDistName currentdir (O.distname ? opts)   let resultfile = currentdir </> distname ++ ".zip"   doFastZip' opts currentdir (writeFile resultfile)-  when (Quiet `notElem` opts) $ putStrLn $ "Created " ++ resultfile+  putInfo opts $ text $ "Created " ++ resultfile  doFastZip' :: [DarcsFlag]              -- ^ Flags/options            -> FilePath                 -- ^ The path to the repository            -> (BL.ByteString -> IO a)  -- ^ An action to perform on the archive contents            -> IO a-doFastZip' opts path act = withRepositoryDirectory (useCache opts) path $ RepoJob $ \(Repo _ _ _ c) -> do-  when (SetScriptsExecutable `elem` opts) $+doFastZip' opts path act = withRepositoryLocation (useCache ? opts) path $ RepoJob $ \repo -> do+  when (F.setScriptsExecutable ? opts == O.YesSetScriptsExecutable) $     putStrLn "WARNING: Zip archives cannot store executable flag."  -  let distname = getDistName path [x | DistName x <- opts]+  let distname = getDistName path (O.distname ? opts)   i <- fetchFilePS (path </> darcsdir </> "hashed_inventory") Uncachable-  pristine <- pathsAndContents (distname ++ "/") c (inv2pris i)+  pristine <- pathsAndContents (distname ++ "/") (repoCache repo) (peekPristineHash i)   epochtime <- toSeconds `fmap` getCurrentTime   let entries = [ toEntry filepath epochtime (toLazy contents) | (filepath,contents) <- pristine ]   let archive = foldr addEntryToArchive emptyArchive entries
src/Darcs/UI/Commands/GZCRCs.hs view
@@ -20,8 +20,6 @@ -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. -{-# LANGUAGE CPP #-}- module Darcs.UI.Commands.GZCRCs     ( gzcrcs     , doCRCWarnings@@ -30,7 +28,6 @@ import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) ) import Control.Monad ( when, unless, forM_ ) import Control.Monad.Trans ( liftIO ) import Control.Monad.Writer ( runWriterT, tell )@@ -44,25 +41,25 @@ import Darcs.Util.File ( getRecursiveContentsFullPath ) import Darcs.Util.ByteString ( isGZFile, gzDecompress ) import Darcs.Util.Global ( getCRCWarnings, resetCRCWarnings )-import Darcs.Repository ( Repository, withRepository, RepoJob(..) )+import Darcs.Repository ( Repository, withRepository, RepoJob(..), repoCache ) -- This command needs access beyond the normal repository APIs (to -- get at the caches and inspect them directly) -- Could move the relevant code into Darcs.Repository modules -- but it doesn't really seem worth it. import Darcs.Repository.Cache ( Cache(..), writable, isThisRepo,                                 hashedFilePath, allHashedDirs )-import Darcs.Repository.InternalTypes ( extractCache ) import Darcs.Util.Lock ( gzWriteAtomicFilePSs )-import Darcs.Patch ( RepoPatch )-import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInRepository )-import Darcs.UI.Options ( DarcsOption, (^), oid, odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Commands+    ( DarcsCommand(..), withStdOpts, nodefaults, amInRepository+    , putInfo, putVerbose+    )+import Darcs.UI.Completion ( noArgs )+import Darcs.UI.Options ( (^), oid, odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Util.Path ( AbsolutePath )-import Darcs.UI.Flags-    ( DarcsFlag( Quiet, Verbose, Check, Repair, JustThisRepo )-    , useCache )+import Darcs.UI.Flags ( DarcsFlag, useCache ) import Darcs.Util.Text ( formatText )-import Darcs.Util.Printer ( putDocLn, text )+import Darcs.Util.Printer ( text )  gzcrcsHelp :: String gzcrcsHelp = formatText 80@@ -112,26 +109,6 @@ gzcrcsDescription = "Check or repair the CRCs of compressed files in the "                     ++ "repository." -gzcrcsBasicOpts :: DarcsOption a (Maybe O.GzcrcsAction -> Bool -> Maybe String -> a)-gzcrcsBasicOpts = O.gzcrcsActions ^ O.justThisRepo ^ O.workingRepoDir--gzcrcsOpts :: DarcsOption a-              (Maybe O.GzcrcsAction-               -> Bool-               -> Maybe String-               -> Maybe O.StdCmdAction-               -> Bool-               -> Bool-               -> O.Verbosity-               -> Bool-               -> O.UseCache-               -> Maybe String-               -> Bool-               -> Maybe String-               -> Bool-               -> a)-gzcrcsOpts = gzcrcsBasicOpts `withStdOpts` oid- gzcrcs :: DarcsCommand [DarcsFlag] gzcrcs = DarcsCommand     { commandProgramName = "darcs"@@ -142,7 +119,7 @@     , commandExtraArgHelp = []     , commandCommand = gzcrcsCmd     , commandPrereq = amInRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = odesc gzcrcsBasicOpts@@ -150,19 +127,23 @@     , commandCheckOptions = ocheck gzcrcsOpts     , commandParseOptions = onormalise gzcrcsOpts     }+  where+    gzcrcsBasicOpts = O.gzcrcsActions ^ O.justThisRepo ^ O.repoDir+    gzcrcsOpts = gzcrcsBasicOpts `withStdOpts` oid  gzcrcsCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-gzcrcsCmd _ opts _ | Check `elem` opts || Repair `elem` opts =-    withRepository (useCache opts) (RepoJob (gzcrcs' opts))-gzcrcsCmd _ _ _ = error "You must specify --check or --repair for gzcrcs"+gzcrcsCmd _ opts _ =+  case O.gzcrcsActions ? opts of+    Nothing -> fail "You must specify --check or --repair for gzcrcs"+    Just action -> withRepository (useCache ? opts) (RepoJob (gzcrcs' action opts)) -gzcrcs' :: (RepoPatch p) => [DarcsFlag] -> Repository rt p wR wU wT -> IO ()-gzcrcs' opts repo = do+gzcrcs' :: O.GzcrcsAction -> [DarcsFlag] -> Repository rt p wR wU wT -> IO ()+gzcrcs' action opts repo = do     -- Somewhat ugly IORef use here because it's convenient, would be nicer to     -- pre-filter the list of locs to check and then decide whether to print     -- the message up front.     warnRelatedRepos <- newIORef $ not isJustThisRepo-    let Ca locs = extractCache repo+    let Ca locs = repoCache repo     (_, Any checkFailed) <- runWriterT $ forM_ locs $ \loc ->         unless (isJustThisRepo && not (isThisRepo loc)) $ do             let isWritable = writable loc@@ -174,7 +155,7 @@                         warn <- readIORef warnRelatedRepos                         when (warn && not (isThisRepo loc)) $ do                             writeIORef warnRelatedRepos False-                            putInfo $+                            putInfo opts $ text $                                 "Also checking related repos and caches; use "                                 ++ "--just-this-repo to disable.\n"                                 ++ "Checking " ++ dir@@ -194,12 +175,12 @@                                     when isCorrupt $ do                                         -- Count of files in current directory                                         tell (Sum 1)-                                        liftIO . putVerbose $+                                        liftIO . putVerbose opts $ text $                                             "Corrupt: " ++ file                                         when (isWritable && shouldRepair) $                                             doRepair file uncompressed                     when (count > (0 :: Int)) $ do-                        liftIO . putInfo $+                        liftIO . putInfo opts $ text $                             "Found " ++ show count ++ " corrupt file"                             ++ (if count > 1 then "s" else "")                             ++ (if shouldRepair@@ -209,12 +190,9 @@                                     else "")                         -- Something corrupt somewhere                         tell (Any True)-    when (Check `elem` opts && checkFailed) $+    when (action == O.GzcrcsCheck && checkFailed) $         exitWith (ExitFailure 1)   where-    [shouldRepair, isQuiet, isVerbose, isJustThisRepo] = zipWith ($)-        (elem `fmap` [Repair, Quiet, Verbose, JustThisRepo]) (repeat opts)-    putInfo = unless isQuiet . putDocLn . text-    putVerbose = when isVerbose . putDocLn . text+    shouldRepair = action == O.GzcrcsRepair+    isJustThisRepo = O.justThisRepo ? opts     doRepair name contents = liftIO $ gzWriteAtomicFilePSs name contents-
src/Darcs/UI/Commands/Help.hs view
@@ -34,27 +34,31 @@     ( CommandArgs(..)     , CommandControl(..)     , normalCommand-    , DarcsCommand(..), withStdOpts+    , DarcsCommand(..)     , WrappedCommand(..)     , wrappedCommandName     , disambiguateCommands     , extractCommands-    , getCommandHelp+    , getSubcommands     , nodefaults-    , usage     ) import Darcs.UI.External ( viewDoc )+import Darcs.UI.Usage+    ( getCommandHelp+    , usage+    , subusage+    ) import Darcs.Util.Lock ( environmentHelpTmpdir, environmentHelpKeepTmpdir                        , environmentHelpLocks ) import Darcs.Patch.Match ( helpOnMatchers )-import Darcs.Repository.Prefs ( boringFileHelp, binariesFileHelp, environmentHelpHome )+import Darcs.Repository.Prefs ( environmentHelpHome, prefsFilesHelp ) import Darcs.Util.Ssh ( environmentHelpSsh, environmentHelpScp, environmentHelpSshPort ) import Darcs.Util.File ( withCurrentDirectory ) import Darcs.Util.Path ( AbsolutePath ) import Control.Arrow ( (***) ) import Data.Char ( isAlphaNum, toLower, toUpper ) import Data.Either ( partitionEithers )-import Data.List ( groupBy, isPrefixOf, intercalate, nub )+import Data.List ( groupBy, isPrefixOf, intercalate, nub, lookup ) import Darcs.Util.English ( andClauses ) import Darcs.Util.Printer (text, vcat, vsep, ($$), empty) import Darcs.Util.Printer.Color ( environmentHelpColor, environmentHelpEscape, environmentHelpEscapeWhite )@@ -62,8 +66,7 @@ import Version ( version ) import Darcs.Util.Download ( environmentHelpProxy, environmentHelpProxyPassword ) import Darcs.Util.Workaround ( getCurrentDirectory )-import Darcs.UI.Options ( DarcsOption, defaultFlags, ocheck, onormalise, oid )-import qualified Darcs.UI.Options.All as O ( StdCmdAction, Verbosity, UseCache )+import Darcs.UI.Options ( defaultFlags, ocheck, onormalise, oid ) import qualified Darcs.UI.TheCommands as TheCommands  helpDescription :: String@@ -75,22 +78,25 @@  "commands and a short description of each one.  With an extra argument,\n" ++  "`darcs help foo` prints detailed help about the darcs command foo.\n" -argPossibilities :: [String]-argPossibilities = map wrappedCommandName $ extractCommands commandControlList+-- | Starting from a list of 'CommandControl's, unwrap one level+-- to get a list of command names together with their subcommands.+unwrapTree :: [CommandControl] -> [(String, [CommandControl])]+unwrapTree cs = [ (wrappedCommandName c, subcmds c) | CommandData c <- cs ]+  where+    subcmds (WrappedCommand sc) = getSubcommands sc -helpOpts :: DarcsOption a-            (Maybe O.StdCmdAction-             -> Bool-             -> Bool-             -> O.Verbosity-             -> Bool-             -> O.UseCache-             -> Maybe String-             -> Bool-             -> Maybe String-             -> Bool-             -> a)-helpOpts = withStdOpts oid oid+-- | Given a list of (normal) arguments to the help command, produce a list+-- of possible completions for the next (normal) argument.+completeArgs :: [String] -> [String]+completeArgs [] = map fst (unwrapTree commandControlList) ++ extraArgs where+  extraArgs = [ "manpage", "markdown", "patterns", "environment" ]+completeArgs (arg:args) = exploreTree arg args commandControlList where+  exploreTree cmd cmds cs =+    case lookup cmd (unwrapTree cs) of+      Nothing -> []+      Just cs' -> case cmds of+        [] -> map fst (unwrapTree cs')+        sub:cmds' -> exploreTree sub cmds' cs'  help :: DarcsCommand [DarcsFlag] help = DarcsCommand@@ -102,13 +108,13 @@     , commandExtraArgHelp = ["[<DARCS_COMMAND> [DARCS_SUBCOMMAND]]  "]     , commandCommand = \ x y z -> helpCmd x y z >> exitSuccess     , commandPrereq = \_ -> return $ Right ()-    , commandGetArgPossibilities = return argPossibilities+    , commandCompleteArgs = \_ _ -> return . completeArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = []-    , commandDefaults = defaultFlags helpOpts-    , commandCheckOptions = ocheck helpOpts-    , commandParseOptions = onormalise helpOpts+    , commandDefaults = defaultFlags oid+    , commandCheckOptions = ocheck oid+    , commandParseOptions = onormalise oid     }  helpCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()@@ -143,18 +149,21 @@                      [] -> Left v                      es -> Right es -helpCmd _ _ [] = viewDoc $ text $ usage commandControlList+helpCmd _ _ [] = viewDoc $ usage commandControlList  helpCmd _ _ (cmd:args) =-    let disambiguated = disambiguateCommands commandControlList cmd args-    in case disambiguated of+    case disambiguateCommands commandControlList cmd args of          Left err -> fail err-         Right (cmds,_) ->+         Right (cmds,as) ->              let msg = case cmds of                          CommandOnly c       -> getCommandHelp Nothing  c-                         SuperCommandOnly c  -> getCommandHelp Nothing  c+                         SuperCommandOnly c  ->+                          if null as then+                            getCommandHelp Nothing  c+                          else+                            text $ "Invalid subcommand!\n\n" ++ subusage c                          SuperCommandSub c s -> getCommandHelp (Just c) s-             in viewDoc $ text msg+             in viewDoc $ msg  listAvailableCommands :: IO () listAvailableCommands =@@ -168,7 +177,6 @@        putStrLn "--help"        putStrLn "--version"        putStrLn "--exact-version"-       putStrLn "--overview"     where isRight (Right _) = True           isRight _ = False @@ -263,10 +271,7 @@  unlines commands,  unlines environment,  ".SH FILES",- ".SS \"_darcs/prefs/binaries\"",- escape $ unlines binariesFileHelp,- ".SS \"_darcs/prefs/boring\"",- escape $ unlines boringFileHelp,+ unlines prefFiles,  ".SH BUGS",  "At http://bugs.darcs.net/ you can find a list of known",  "bugs in Darcs.  Unknown bugs can be reported at that",@@ -357,15 +362,23 @@                   then repl ++ replace find repl (drop (length find) s)                   else head s : replace find repl (tail s) +      prefFiles = concatMap go prefsFilesHelp+        where go (f,h) = [".SS \"_darcs/prefs/" ++ f ++ "\"", escape h]+ markdownLines :: [String] markdownLines =  [ "# Commands", ""  , unlines commands- , "# Environment variables"- , "", unlines environment  , "# Patterns"- , "", unlines helpOnMatchers  ]+ , "", unlines helpOnMatchers+ , "# Configuration"+ , "", unlines prefFiles+ , "# Environment variables"+ , "", unlines environment ]    where+      prefFiles = concatMap go prefsFilesHelp+        where go (f,h) = ["## `_darcs/prefs/" ++ f ++ "`", "", h]+       environment :: [String]       environment = intercalate [""]                      [ renderEnv ks ds | (ks, ds) <- environmentHelp ]@@ -395,12 +408,12 @@        where opts2 = commandAdvancedOptions c  environmentHelpEditor :: ([String], [String])-environmentHelpEditor = (["DARCS_EDITOR", "DARCSEDITOR", "VISUAL", "EDITOR"],[+environmentHelpEditor = (["DARCS_EDITOR", "VISUAL", "EDITOR"],[  "To edit a patch description of email comment, Darcs will invoke an",  "external editor.  Your preferred editor can be set as any of the",- "environment variables $DARCS_EDITOR, $DARCSEDITOR, $VISUAL or $EDITOR.",- "If none of these are set, vi(1) is used.  If vi crashes or is not",- "found in your PATH, emacs, emacs -nw, nano and (on Windows) edit are",+ "environment variables $DARCS_EDITOR, $VISUAL or $EDITOR.",+ "If none of these are set, nano is used.  If nano crashes or is not",+ "found in your PATH, vi, emacs, emacs -nw and (on Windows) edit are",  "each tried in turn."])  environmentHelpPager :: ([String], [String])@@ -412,8 +425,8 @@ environmentHelpTimeout :: ([String], [String]) environmentHelpTimeout = (["DARCS_CONNECTION_TIMEOUT"],[  "Set the maximum time in seconds that darcs allows and connection to",- "take. If the variable is not specified the default are 30 seconds. This",- "option only works with curl."])+ "take. If the variable is not specified the default are 30 seconds.",+ "This option only works with curl."])  -- | There are two environment variables that we do not document: -- - DARCS_USE_ISPRINT: deprecated, use DARCS_DONT_ESCAPE_ISPRINT.
src/Darcs/UI/Commands/Init.hs view
@@ -23,18 +23,15 @@ import Prelude hiding ( (^) ) import Darcs.UI.Commands     ( DarcsCommand(..), withStdOpts, nodefaults, amNotInRepository, putInfo )-import Darcs.UI.Flags ( DarcsFlag( WorkRepoDir ), withWorkingDir, patchFormat, runPatchIndex )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Completion ( noArgs )+import Darcs.UI.Flags ( DarcsFlag( WorkRepoDir ) )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O-    ( patchFormat, useWorkingDir, workingRepoDir, patchIndex, hashed-    , PatchFormat, WithWorkingDir, WithPatchIndex-    , StdCmdAction, Verbosity, UseCache, PatchFormat(..)-    ) import Darcs.UI.Options.All (  ) import Darcs.Util.Printer ( text ) import Darcs.Util.Path ( AbsolutePath ) import Darcs.Util.Text ( quote )-import Darcs.Repository ( createRepository )+import Darcs.Repository ( createRepository, withUMaskFlag )  initializeDescription :: String initializeDescription = "Create an empty repository."@@ -55,31 +52,6 @@  "\n" ++  "Initialize is commonly abbreviated to `init`.\n" -initBasicOpts :: DarcsOption a (O.PatchFormat -> O.WithWorkingDir -> Maybe String -> a)-initBasicOpts = O.patchFormat ^ O.useWorkingDir ^ O.workingRepoDir--initAdvancedOpts :: DarcsOption a (O.WithPatchIndex -> () -> a)-initAdvancedOpts = O.patchIndex ^ O.hashed--initOpts :: DarcsOption a-            (O.PatchFormat-             -> O.WithWorkingDir-             -> Maybe String-             -> Maybe O.StdCmdAction-             -> Bool-             -> Bool-             -> O.Verbosity-             -> Bool-             -> O.WithPatchIndex-             -> ()-             -> O.UseCache-             -> Maybe String-             -> Bool-             -> Maybe String-             -> Bool-             -> a)-initOpts = initBasicOpts `withStdOpts` initAdvancedOpts- initialize :: DarcsCommand [DarcsFlag] initialize = DarcsCommand     { commandProgramName = "darcs"@@ -90,7 +62,7 @@     , commandExtraArgHelp = ["[<DIRECTORY>]"]     , commandPrereq = \_ -> return $ Right ()     , commandCommand = initializeCmd-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc initAdvancedOpts     , commandBasicOptions = odesc initBasicOpts@@ -98,16 +70,25 @@     , commandCheckOptions = ocheck initOpts     , commandParseOptions = onormalise initOpts     }+  where+    initBasicOpts = O.patchFormat ^ O.withWorkingDir ^ O.repoDir+    initAdvancedOpts = O.patchIndexNo ^ O.hashed+    initOpts = initBasicOpts `withStdOpts` initAdvancedOpts  initializeCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () initializeCmd aps opts [outname] | null [ () | WorkRepoDir _ <- opts ] =   initializeCmd aps (WorkRepoDir outname:opts) []-initializeCmd _ opts [] = do-  location <- amNotInRepository opts-  case location of-    Left msg -> fail $ "Unable to " ++ quote ("darcs " ++ commandName initialize)-                        ++ " here.\n\n" ++ msg-    Right () -> do-      createRepository (patchFormat opts) (withWorkingDir opts) (runPatchIndex opts)-      putInfo opts $ text "Repository initialized."+initializeCmd _ opts [] =+  withUMaskFlag (O.umask ? opts) $ do+    location <- amNotInRepository opts+    case location of+      Left msg -> fail $ "Unable to " ++ quote ("darcs " ++ commandName initialize)+                          ++ " here.\n\n" ++ msg+      Right () -> do+        _ <- createRepository+          (O.patchFormat ? opts)+          (O.withWorkingDir ? opts)+          (O.patchIndexNo ? opts)+          (O.useCache ? opts)+        putInfo opts $ text "Repository initialized." initializeCmd _ _ _ = fail "You must provide 'initialize' with either zero or one argument."
src/Darcs/UI/Commands/Log.hs view
@@ -15,8 +15,7 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, PatternGuards #-}-+{-# LANGUAGE PatternGuards #-}  module Darcs.UI.Commands.Log     ( changes, log@@ -26,7 +25,6 @@ import Prelude () import Darcs.Prelude -import Unsafe.Coerce (unsafeCoerce) import Data.List ( intersect, sort, nub, find ) import Data.Maybe ( fromMaybe, fromJust, isJust ) import Control.Arrow ( second )@@ -36,58 +34,57 @@ import Darcs.UI.PrintPatch ( showFriendly ) import Darcs.Patch.PatchInfoAnd ( fmapFLPIAP, hopefullyM, info ) import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, commandAlias, findRepository )+import Darcs.UI.Completion ( knownFileArgs ) import Darcs.UI.External ( viewDocWith ) import Darcs.UI.Flags-    ( DarcsFlag(GenContext,-                MachineReadable, Count, Interactive,-                NumberPatches, XMLOutput, Summary,-                Verbose, Debug, NoPatchIndexFlag)-    , doReverse, showChangesOnlyToFiles-    , useCache, maxCount, umask-    , verbosity, isUnified, isInteractive, hasSummary+    ( DarcsFlag+    , changesReverse, onlyToFiles+    , useCache, maxCount, hasXmlOutput+    , verbosity, withContext, isInteractive, verbose     , fixSubPaths, getRepourl )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags, parseFlags )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Util.Path ( SubPath(), toFilePath,                     fp2fn, fn2fp, normPath, AbsolutePath, simpleSubPath ) import Darcs.Repository ( PatchSet, PatchInfoAnd,-                          withRepositoryDirectory, RepoJob(..),+                          withRepositoryLocation, RepoJob(..),                           readRepo, unrecordedChanges,                           withRepoLockCanFail )-import Darcs.Repository.Flags ( UseIndex(..), ScanKnown(..), DiffAlgorithm(MyersDiff), UpdateWorking(..) )+import Darcs.Repository.Flags ( UseIndex(..), ScanKnown(..), DiffAlgorithm(MyersDiff) ) import Darcs.Util.Lock ( withTempDir )-import Darcs.Patch.Set ( PatchSet(..), newset2RL )+import Darcs.Patch.Set ( PatchSet(..), patchSet2RL ) import Darcs.Patch.Conflict ( Conflict, CommuteNoConflicts ) import Darcs.Patch.Format ( PatchListFormat ) import Darcs.Patch.FileHunk ( IsHunk )-import Darcs.Patch.Info ( toXml, showPatchInfo, escapeXML, PatchInfo )+import Darcs.Patch.Info ( toXml, toXmlShort, showPatchInfo, displayPatchInfo, escapeXML, PatchInfo ) import Darcs.Patch.Depends ( findCommonWithThem ) import Darcs.Patch.Bundle( contextPatches ) import Darcs.Patch.Prim ( PrimPatchBase )-import Darcs.Patch.Show ( ShowPatch )+import Darcs.Patch.Show ( ShowPatch, ShowPatchFor(..) ) import Darcs.Patch.TouchesFiles ( lookTouch ) import Darcs.Patch.Type ( PatchType(PatchType) ) import Darcs.Patch.Apply ( Apply, ApplyState ) import Darcs.Patch ( IsRepoType, invert, xmlSummary, description,                      effectOnFilePaths, listTouchedFiles, showPatch )-import Darcs.Patch.Named.Wrapped ( (:~:)(..) )+import Darcs.Patch.Named.Wrapped ( (:~:)(..), getdeps ) import Darcs.Patch.Witnesses.Eq ( EqCheck(..) ) import Darcs.Patch.Witnesses.Ordered     ( FL(NilFL), RL(..), filterOutFLFL, filterRL,     reverseFL, (:>)(..), mapRL ) import Darcs.Patch.Witnesses.Sealed ( Sealed2(..), unseal2, Sealed(..), seal2 )+import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP ) import Darcs.Patch.Match     ( MatchFlag     , firstMatch     , secondMatch-    , matchAPatchread+    , matchAPatch     , haveNonrangeMatch     , matchFirstPatchset     , matchSecondPatchset     ) import Darcs.Patch.Matchable ( Matchable ) import Darcs.Util.Printer ( Doc, simplePrinters, (<+>), prefix, text, vcat,-                 vsep, (<>), ($$), errorDoc, insertBeforeLastline, empty, RenderMode(..) )+                 vsep, (<>), ($$), errorDoc, insertBeforeLastline, empty ) import Darcs.Util.Printer.Color ( fancyPrinters ) import Darcs.Util.Progress ( setProgressMode, debugMessage ) import Darcs.Util.URL ( isValidLocalPath )@@ -105,56 +102,6 @@  ++ logHelp'  ++ logHelp'' -logBasicOpts :: DarcsOption a-                ([O.MatchFlag]-                 -> Maybe Int-                 -> Bool-                 -> Maybe O.ChangesFormat-                 -> Maybe O.Summary-                 -> Bool-                 -> Maybe String-                 -> Maybe String-                 -> Maybe Bool-                 -> a)-logBasicOpts-    = O.matchSeveralOrRange-    ^ O.matchMaxcount-    ^ O.onlyToFiles-    ^ O.changesFormat-    ^ O.summary-    ^ O.changesReverse-    ^ O.possiblyRemoteRepo-    ^ O.workingRepoDir-    ^ O.interactive -- False--logAdvancedOpts :: DarcsOption a (O.NetworkOptions -> O.WithPatchIndex -> a)-logAdvancedOpts = O.network ^ O.patchIndexYes--logOpts :: DarcsOption a-           ([O.MatchFlag]-            -> Maybe Int-            -> Bool-            -> Maybe O.ChangesFormat-            -> Maybe O.Summary-            -> Bool-            -> Maybe String-            -> Maybe String-            -> Maybe Bool-            -> Maybe O.StdCmdAction-            -> Bool-            -> Bool-            -> O.Verbosity-            -> Bool-            -> O.NetworkOptions-            -> O.WithPatchIndex-            -> O.UseCache-            -> Maybe String-            -> Bool-            -> Maybe String-            -> Bool-            -> a)-logOpts = logBasicOpts `withStdOpts` logAdvancedOpts- log :: DarcsCommand [DarcsFlag] log = DarcsCommand     { commandProgramName = "darcs"@@ -163,7 +110,7 @@     , commandDescription = "List patches in the repository."     , commandExtraArgs = -1     , commandExtraArgHelp = ["[FILE or DIRECTORY]..."]-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = knownFileArgs     , commandCommand = logCmd     , commandPrereq = findRepository     , commandArgdefaults = nodefaults@@ -173,10 +120,23 @@     , commandCheckOptions = ocheck logOpts     , commandParseOptions = onormalise logOpts     }+  where+    logBasicOpts+      = O.matchSeveralOrRange+      ^ O.maxCount+      ^ O.onlyToFiles+      ^ O.changesFormat+      ^ O.summary+      ^ O.changesReverse+      ^ O.possiblyRemoteRepo+      ^ O.repoDir+      ^ O.interactive+    logAdvancedOpts = O.network ^ O.patchIndexYes+    logOpts = logBasicOpts `withStdOpts` logAdvancedOpts  logCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () logCmd fps opts args-  | GenContext `elem` opts = if not . null $ args+  | O.changesFormat ? opts == Just O.GenContext = if not . null $ args       then fail "log --context cannot accept other arguments"       else logContext opts   | hasRemoteRepo opts = do@@ -191,10 +151,10 @@       fs <- fixSubPaths fps args       case fs of         [] -> putStrLn "No valid arguments were given, nothing to do."-        _ -> do unless (Interactive `elem` opts)-                 $ unless (NoPatchIndexFlag `elem` opts)-                  $ withRepoLockCanFail (useCache opts) YesUpdateWorking (umask opts)-                    $ RepoJob attemptCreatePatchIndex+        _ -> do unless (isInteractive False opts)+                 $ when (O.patchIndexNo ? opts == O.YesPatchIndex)+                  $ withRepoLockCanFail (useCache ? opts)+                    $ RepoJob (\repo -> readRepo repo >>= attemptCreatePatchIndex repo)                 showLog opts $ Just $ nub $ sort fs  maybeNotNull :: [a] -> Maybe [a]@@ -215,41 +175,43 @@ showLog :: [DarcsFlag] -> Maybe [SubPath] -> IO () showLog opts files =   let repodir = fromMaybe "." (getRepourl opts) in-  withRepositoryDirectory (useCache opts) repodir $ RepoJob $ \repository -> do-  unless (Debug `elem` opts) $ setProgressMode False+  withRepositoryLocation (useCache ? opts) repodir $ RepoJob $ \repository -> do+  unless (O.debug ? opts) $ setProgressMode False   Sealed unrec <- case files of     Nothing -> return $ Sealed NilFL-    Just _ -> Sealed `fmap` unrecordedChanges (UseIndex, ScanKnown, MyersDiff) repository files+    Just _ -> Sealed `fmap` unrecordedChanges (UseIndex, ScanKnown, MyersDiff)+                  O.NoLookForMoves O.NoLookForReplaces+                  repository files                   `catch` \(_ :: IOException) -> return (Sealed NilFL) -- this is triggered when repository is remote+  debugMessage "About to read the repository..."+  patches <- readRepo repository+  debugMessage "Done reading the repository."   let normfp = fn2fp . normPath . fp2fn       undoUnrecordedOnFPs = effectOnFilePaths (invert unrec)       recFiles = map normfp . undoUnrecordedOnFPs . map toFilePath <$> files       filtered_changes p =           maybe_reverse <$>           getLogInfo-              (maxCount opts)+              (maxCount ? opts)               (parseFlags O.matchSeveralOrRange opts)-              (showChangesOnlyToFiles opts)+              (onlyToFiles ? opts)               recFiles-              (maybeFilterPatches repository)+              (maybeFilterPatches repository patches)               p-  debugMessage "About to read the repository..."-  patches <- readRepo repository-  debugMessage "Done reading the repository."-  if Interactive `elem` opts+  if isInteractive False opts     then do (fp_and_fs, _, _) <- filtered_changes patches             let fp = map fst fp_and_fs             viewChanges (logPatchSelOpts opts) fp-    else do let header = if isJust files && XMLOutput `notElem` opts+    else do let header = if isJust files && hasXmlOutput opts                           then text $ "Changes to "++unwords (fromJust recFiles)++":\n"                           else empty             debugMessage "About to print the patches..."-            let printers = if XMLOutput `elem` opts then simplePrinters else fancyPrinters+            let printers = if hasXmlOutput opts then simplePrinters else fancyPrinters             ps <- readRepo repository -- read repo again to prevent holding onto                                        -- values forced by filtered_changes             logOutput <- changelog opts ps `fmap` filtered_changes patches-            viewDocWith printers Encode $ header $$ logOutput-  where maybe_reverse (xs,b,c) = if doReverse opts+            viewDocWith printers $ header $$ logOutput+  where maybe_reverse (xs,b,c) = if changesReverse ? opts                                  then (reverse xs, b, c)                                  else (xs, b, c) @@ -302,7 +264,7 @@                then matchSecondPatchset matchFlags ps                else Sealed ps         pf = if haveNonrangeMatch (PatchType :: PatchType rt p) matchFlags-             then matchAPatchread matchFlags+             then matchAPatch matchFlags              else \_ -> True          filterOutUnrelatedChanges (pfs, renames, doc)@@ -315,7 +277,7 @@         unrelated fs p           -- If the change does not affect the patches we are looking at,           -- we ignore the difference between the two states.-          | null $ fs `intersect` listTouchedFiles p = unsafeCoerce IsEq+          | null $ fs `intersect` listTouchedFiles p = unsafeCoerceP IsEq           | otherwise                                = NotEq  -- | Take a list of filenames and patches and produce a list of patches that@@ -350,7 +312,7 @@                 else case hopefullyM hp of                     Nothing -> do                         let err = text "Can't find patches prior to:"-                                  $$ showPatchInfo (info hp)+                                  $$ displayPatchInfo (info hp)                         return ([], renames, Just err)                     Just p ->                         case lookTouch (Just renames) fs (invert p) of@@ -382,39 +344,48 @@           -> ([(Sealed2 (PatchInfoAnd rt p), [FilePath])], [(FilePath, FilePath)], Maybe Doc)           -> Doc changelog opts patchset (pis_and_fs, createdAsFs, mbErr)-    | Count `elem` opts = text $ show $ length pis_and_fs-    | XMLOutput `elem` opts =+    | O.changesFormat ? opts == Just O.CountPatches = text $ show $ length pis_and_fs+    | hasXmlOutput opts =          text "<changelog>"       $$ vcat created_as_xml       $$ vcat actual_xml_changes       $$ text "</changelog>"-    | Summary `elem` opts || Verbose `elem`  opts =+    | O.yes (O.summary ? opts) || verbose opts =         mbAppendErr $ vsep (map (number_patch change_with_summary) pis)     | otherwise = mbAppendErr $ vsep (map (number_patch description') pis)     where mbAppendErr = maybe id (\err -> ($$ err)) mbErr           change_with_summary :: Sealed2 (PatchInfoAnd rt p) -> Doc           change_with_summary (Sealed2 hp)-              | Just p <- hopefullyM hp = if MachineReadable `elem` opts-                                           then showPatch p-                                           else showFriendly (verbosity opts) (hasSummary O.NoSummary opts) p-              | otherwise = description hp-                            $$ indent (text "[this patch is unavailable]")+            | Just p <- hopefullyM hp =+              if O.changesFormat ? opts == Just O.MachineReadable+                then showPatch ForStorage p+                else showFriendly (verbosity ? opts) (O.summary ? opts) p+            | otherwise = description hp $$ indent (text "[this patch is unavailable]") -          xml_with_summary (Sealed2 hp)-              | Just p <- hopefullyM hp = insertBeforeLastline-                                           (toXml $ info hp) (indent $ xmlSummary p)+          xml_with_summary (Sealed2 hp) | Just p <- hopefullyM hp =+                    let+                      deps = getdeps p+                      xmlDependencies =+                        text "<explicit_dependencies>"+                        $$ vcat (map (indent . toXmlShort) deps)+                        $$ text "</explicit_dependencies>"+                      summary | deps == [] = indent $ xmlSummary p+                              | otherwise = indent $ xmlDependencies $$ xmlSummary p+                    in+                      insertBeforeLastline (toXml $ info hp) summary           xml_with_summary (Sealed2 hp) = toXml (info hp)           indent = prefix "    "-          actual_xml_changes = if Summary `elem` opts-                               then map xml_with_summary pis-                               else map (toXml . unseal2 info) pis+          actual_xml_changes =+            case O.summary ? opts of+              O.YesSummary -> map xml_with_summary pis+              O.NoSummary -> map (toXml . unseal2 info) pis            created_as_xml = map create createdAsFs where             create rename@(_, as) = createdAsXml (first_change_of as) rename             -- We need to reorder the patches when they haven't been reversed             -- already, so that we find the *first* patch that modifies a given             -- file, not the last (by default, the list is oldest->newest).-            reorderer = if not (doReverse opts) then reverse else id+            reorderer = if not (changesReverse ? opts) then reverse else id             oldest_first_pis_and_fs = reorderer pis_and_fs             couldnt_find fn = error $ "Couldn't find first patch affecting " ++                                       fn ++ " in pis_and_fs"@@ -422,13 +393,13 @@             find_first_change_of fn = fromMaybe (couldnt_find fn)               (mb_first_change_of fn)             first_change_of = unseal2 info . fst . find_first_change_of-          number_patch f x = if NumberPatches `elem` opts+          number_patch f x = if O.changesFormat ? opts == Just O.NumberPatches                              then case get_number x of                                   Just n -> text (show n++":") <+> f x                                   Nothing -> f x                              else f x           get_number :: Sealed2 (PatchInfoAnd re p) -> Maybe Int-          get_number (Sealed2 y) = gn 1 (newset2RL patchset)+          get_number (Sealed2 y) = gn 1 (patchSet2RL patchset)               where iy = info y                     gn :: Int -> RL (PatchInfoAnd rt p) wStart wY -> Maybe Int                     gn n (bs:<:b) | seq n (info b) == iy = Just n@@ -452,12 +423,12 @@ logContext :: [DarcsFlag] -> IO () logContext opts = do   let repodir = fromMaybe "." $ getRepourl opts-  withRepositoryDirectory (useCache opts) repodir $ RepoJob $ \repository -> do+  withRepositoryLocation (useCache ? opts) repodir $ RepoJob $ \repository -> do       (_ :> ps') <- contextPatches `fmap` readRepo repository       let pis = mapRL seal2 ps'       let header = text "\nContext:\n"-      let logOutput = maybe (vsep $ map (unseal2 (showPatchInfo.info)) pis) errorDoc Nothing-      viewDocWith simplePrinters Encode $ header $$ logOutput+      let logOutput = maybe (vsep $ map (unseal2 (showPatchInfo ForStorage . info)) pis) errorDoc Nothing+      viewDocWith simplePrinters $ header $$ logOutput  -- | changes is an alias for log changes :: DarcsCommand [DarcsFlag]@@ -475,10 +446,10 @@  logPatchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions logPatchSelOpts flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { S.verbosity = verbosity ? flags     , S.matchFlags = parseFlags O.matchSeveralOrRange flags     , S.interactive = isInteractive False flags     , S.selectDeps = O.PromptDeps -- option not supported, use default-    , S.summary = hasSummary O.NoSummary flags-    , S.withContext = isUnified flags+    , S.summary = O.summary ? flags+    , S.withContext = withContext ? flags     }
src/Darcs/UI/Commands/MarkConflicts.hs view
@@ -15,41 +15,54 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}  module Darcs.UI.Commands.MarkConflicts ( markconflicts ) where  import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) )- import System.Exit ( exitSuccess )-import Data.List.Ordered ( nubSort )+import Data.List.Ordered ( nubSort, isect ) import Control.Monad ( when, unless ) import Control.Exception ( catch, IOException )  import Darcs.Util.Prompt ( promptYorn )-import Darcs.Util.Path ( AbsolutePath ) import Darcs.Util.SignalHandler ( withSignalsBlocked )-import Darcs.Util.Printer( putDocLn, putDocLnWith, text, redText, ($$) )-import Darcs.Util.Printer.Color (fancyPrinters)+import Darcs.Util.Path ( AbsolutePath, SubPath, toFilePath, simpleSubPath )+import Darcs.Util.Printer+    ( Doc, putDocLnWith, text, redText, debugDocLn, vsep, (<>), (<+>), ($$) )+import Darcs.Util.Printer.Color ( fancyPrinters )+import Darcs.Util.Text ( pathlist ) -import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository )-import Darcs.UI.Flags ( DarcsFlag, diffingOpts, verbosity, dryRun, umask, useCache )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Commands+    ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository, putInfo )+import Darcs.UI.Commands.Util ( filterExistingPaths )+import Darcs.UI.Completion ( knownFileArgs )+import Darcs.UI.Flags+    ( DarcsFlag, diffingOpts, verbosity, dryRun, umask+    , useCache, fixSubPaths )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O+ import Darcs.Repository.Flags ( UpdateWorking (..) )-import Darcs.Repository ( withRepoLock, RepoJob(..), addToPending,-                    applyToWorking,-                    readRepo, unrecordedChanges, Repository-                    )-import Darcs.Patch ( invert, PrimOf, listTouchedFiles )-import Darcs.Patch.Witnesses.Ordered ( FL(..) )+import Darcs.Repository+    ( withRepoLock+    , RepoJob(..)+    , addToPending+    , applyToWorking+    , readRepo+    , unrecordedChanges )++import Darcs.Patch ( invert, listTouchedFiles, effectOnFilePaths )+import Darcs.Patch.Show+import Darcs.Patch.TouchesFiles ( chooseTouching )+import Darcs.Patch.Witnesses.Ordered ( FL(..), mapFL ) import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed) ) import Darcs.Repository.Resolution ( patchsetConflictResolutions )-#include "impossible.h" +-- * The mark-conflicts command+ markconflictsDescription :: String markconflictsDescription =  "Mark unresolved conflicts in working tree, for manual resolution."@@ -72,61 +85,25 @@  ,"However, you might revert or manually delete these markers without"  ,"actually resolving the conflict.  In this case, `darcs mark-conflicts`"  ,"is useful to show where are the unresolved conflicts.  It is also"- ,"useful if `darcs apply` is called with `--apply-conflicts`,"- ,"where conflicts aren't marked initially."+ ,"useful if `darcs apply` or `darcs pull` is called with"+ ,"`--allow-conflicts`, where conflicts aren't marked initially."  ,""  ,"Unless you use the `--dry-run` flag, any unrecorded changes to the"- ,"working tree WILL be lost forever when you run this command!"+ ,"affected files WILL be lost forever when you run this command!"  ,"You will be prompted for confirmation before this takes place."  ] -markconflictsBasicOpts :: DarcsOption a-                          (O.UseIndex-                           -> Maybe String-                           -> O.DiffAlgorithm-                           -> O.DryRun-                           -> O.XmlOutput-                           -> a)-markconflictsBasicOpts-    = O.useIndex-    ^ O.workingRepoDir-    ^ O.diffAlgorithm-    ^ O.dryRunXml--markconflictsAdvancedOpts :: DarcsOption a (O.UMask -> a)-markconflictsAdvancedOpts = O.umask--markconflictsOpts :: DarcsOption a-                     (O.UseIndex-                      -> Maybe String-                      -> O.DiffAlgorithm-                      -> O.DryRun-                      -> O.XmlOutput-                      -> Maybe O.StdCmdAction-                      -> Bool-                      -> Bool-                      -> O.Verbosity-                      -> Bool-                      -> O.UMask-                      -> O.UseCache-                      -> Maybe String-                      -> Bool-                      -> Maybe String-                      -> Bool-                      -> a)-markconflictsOpts = markconflictsBasicOpts `withStdOpts` markconflictsAdvancedOpts- markconflicts :: DarcsCommand [DarcsFlag] markconflicts = DarcsCommand     { commandProgramName = "darcs"     , commandName = "mark-conflicts"     , commandHelp = markconflictsHelp     , commandDescription = markconflictsDescription-    , commandExtraArgs = 0-    , commandExtraArgHelp = []+    , commandExtraArgs = -1+    , commandExtraArgHelp = ["[FILE or DIRECTORY]..."]     , commandCommand = markconflictsCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = knownFileArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc markconflictsAdvancedOpts     , commandBasicOptions = odesc markconflictsBasicOpts@@ -134,33 +111,223 @@     , commandCheckOptions = ocheck markconflictsOpts     , commandParseOptions = onormalise markconflictsOpts     }+  where+    markconflictsBasicOpts+      = O.useIndex+      ^ O.repoDir+      ^ O.diffAlgorithm+      ^ O.dryRunXml+    markconflictsAdvancedOpts = O.umask+    markconflictsOpts = markconflictsBasicOpts `withStdOpts` markconflictsAdvancedOpts  markconflictsCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-markconflictsCmd _ opts [] = withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \(repository :: Repository rt p wR wU wR) -> do-  pend <- unrecordedChanges (diffingOpts opts) repository Nothing-  r <- readRepo repository-  Sealed res <- return $ patchsetConflictResolutions r-  case nubSort $ listTouchedFiles res of-    []  -> putStrLn "No conflicts to mark." >> exitSuccess-    cfs -> putDocLnWith fancyPrinters $-              redText "Conflicts found in the following files:" $$ text (unlines cfs)-  when (dryRun opts == O.YesDryRun) $ do-      putDocLn $ text "Conflicts will not be marked: this is a dry run."+markconflictsCmd fps opts args = do+  paths <- if null args then return Everything else sps2ps <$> fixSubPaths fps args -- Applicative IO+  debugDocLn $ "::: paths =" <+>  (text . show) paths+  withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $ RepoJob $ \repository -> do++{-+    What we do here:+    * read the unrecorded changes (all of them)+    * extract functions representing path rename effects from unrecorded+    * convert argument paths to pre-pending+    * read conflict resolutions that touch pre-pending argument paths+    * affected paths = intersection of paths touched by resolutions+                       and pre-pending argument paths+    * for these paths, revert pending changes+    * apply the (filtered, see above) conflict resolutions++    Technical side-note:+    Ghc can't handle pattern bindings for existentials. So 'let' is out,+    one has to use 'case expr of var ->' or 'do var <- return expr'.+    Case is clearer but do-notation does not increase indentation depth.+    So we use case for small-scope bindings and <-/return when the scope+    is a long do block.+-}++    let (useidx, scan, _) = diffingOpts opts+        verb = verbosity ? opts+    classified_paths <-+      traverse (filterExistingPaths repository verb useidx scan O.NoLookForMoves) paths++    unrecorded <- unrecordedChanges (diffingOpts opts)+      O.NoLookForMoves O.NoLookForReplaces+      repository (fromOnly Everything)++    let forward_renames = liftToPathSet (effectOnFilePaths unrecorded)+        backward_renames = liftToPathSet (effectOnFilePaths (invert unrecorded))+        existing_paths = fmap snd classified_paths+        pre_pending_paths = backward_renames existing_paths+    debugDocLn $ "::: pre_pending_paths =" <+> (text . show) pre_pending_paths++    r <- readRepo repository+    Sealed res <- case patchsetConflictResolutions r of+      Sealed raw_res -> do+        let raw_res_paths = fps2ps (listTouchedFiles raw_res)+        debugDocLn $ "::: raw_res_paths =" <+>  (text . show) raw_res_paths+        return $ chooseTouching (ps2fps pre_pending_paths) raw_res+    let res_paths = fps2ps (listTouchedFiles res)+    debugDocLn $ "::: res_paths =" <+>  (text . show) res_paths++    let affected_paths = isectPathSet res_paths pre_pending_paths+    debugDocLn $ "::: affected_paths =" <+>  (text . show) affected_paths++    when (affected_paths == Only []) $ do+      putInfo opts "No conflicts to mark."       exitSuccess-  let undoUnrec :: FL (PrimOf p) wR wU -> IO (Repository rt p wR wR wR)-      undoUnrec NilFL = return repository-      undoUnrec pend' =-              do putStrLn ("This will trash any unrecorded changes"++-                          " in the working directory.")-                 confirmed <- promptYorn "Are you sure? "-                 unless confirmed exitSuccess-                 applyToWorking repository (verbosity opts) (invert pend') `catch` \(e :: IOException) ->-                    bug ("Can't undo pending changes!" ++ show e)-  repository' <- undoUnrec pend-  withSignalsBlocked $-    do addToPending repository' YesUpdateWorking res-       _ <- applyToWorking repository' (verbosity opts) res `catch` \(e :: IOException) ->-           bug ("Problem marking conflicts in mark-conflicts!" ++ show e)-       return ()-  putStrLn "Finished marking conflicts."-markconflictsCmd _ _ _ = impossible++    to_revert <- unrecordedChanges (diffingOpts opts)+      O.NoLookForMoves O.NoLookForReplaces+      repository (fromOnly affected_paths)++    let post_pending_affected_paths = forward_renames affected_paths+    putInfo opts $ "Marking conflicts in:" <+> showPathSet post_pending_affected_paths <> "."++    debugDocLn $ "::: to_revert =" $$ vsep (mapFL displayPatch to_revert)+    debugDocLn $ "::: res = " $$ vsep (mapFL displayPatch res)+    when (O.yes (dryRun ? opts)) $ do+        putInfo opts $ "Conflicts will not be marked: this is a dry run."+        exitSuccess++    repository' <- case to_revert of+      NilFL -> return repository+      _ -> do+        -- TODO:+        -- (1) create backups for all files where we revert changes+        -- (2) try to add the reverted stuff to the unrevert bundle+        -- after (1) and (2) is done we can soften the warning below+        putDocLnWith fancyPrinters $+          "Warning: This will revert all unrecorded changes in:"+          <+> showPathSet post_pending_affected_paths <> "."+          $$ redText "These changes will be LOST."+        confirmed <- promptYorn "Are you sure? "+        unless confirmed exitSuccess++{-      -- copied from Revert.hs, see comment (2) above+        debugMessage "About to write the unrevert file."+        case commute (norevert:>p) of+          Just (p':>_) -> writeUnrevert repository p' recorded NilFL+          Nothing -> writeUnrevert repository (norevert+>+p) recorded NilFL+        debugMessage "About to apply to the working directory."+-}++        let to_add = invert to_revert+        addToPending repository YesUpdateWorking to_add+        applyToWorking repository (verbosity ? opts) to_add `catch` \(e :: IOException) ->+           bug ("Can't undo pending changes!" ++ show e)+    withSignalsBlocked $+      do addToPending repository' YesUpdateWorking res+         _ <- applyToWorking repository' (verbosity ? opts) res `catch` \(e :: IOException) ->+             bug ("Problem marking conflicts in mark-conflicts!" ++ show e)+         return ()+    putInfo opts "Finished marking conflicts."++-- * Generic 'PathSet' support++{- $SupportCode++What follows is generic support code for working with argument path lists+that are used to restrict operations to a subset of the working or pristine+tree. The rest of Darcs uses two types for this:++ * @'Maybe' ['SubPath']@++ * @'Maybe' ['FilePath']@++The problem with both is the contra-intuitive name 'Nothing', which here+stands for 'Everything'. To make the intended use clearer, we use the 'Only'+type instead (which is is isomorphic to 'Maybe') and the synonym 'PathSet'+defined below.++These abstractions should get their own module (or become integrated into+Darcs.Util.Path) if and when someone decides to reuse it elsewhere. The+functionality provided is intentionally minimal and light-weight.+-}++-- | 'Only' is isomorphic to 'Maybe' but with the opposite semantics.+--+-- About the name: I like the data constructor names, they are pretty+-- suggestive. The data type name is up for grabs; a possible alternative+-- is @AtMost@.+data Only a = Everything | Only a deriving (Eq, Ord, Show)++instance Functor Only where+  fmap _ Everything = Everything+  fmap f (Only x) = Only (f x)++instance Foldable Only where+  foldMap _ Everything = mempty+  foldMap f (Only x) = f x++instance Traversable Only where+  traverse _ Everything = pure Everything+  traverse f (Only x) = Only <$> f x++-- | This is mostly for conversion to legacy APIs+fromOnly :: Only a -> Maybe a+fromOnly Everything = Nothing+fromOnly (Only x) = Just x++{- | A set of repository paths. 'Everything' means every path in the repo, it+usually originates from an empty list of path arguments. The list of+'SubPath's is always kept in sorted order with no duplicates and normalised+(as in 'FilePath.normalise'). This has the nice effect of getting rid of the+idiotic "./" that Darcs insists on prepending to repo paths (which can make+things like comparing paths returned from different parts of the code base a+nightmare).++It uses 'SubPath' for easier compatibility and lists because the number of+elements is expected to be small.+-}+type PathSet = Only [SubPath]++-- | Intersection of two 'PathSet's+isectPathSet :: PathSet -> PathSet -> PathSet+isectPathSet Everything ys = ys+isectPathSet xs Everything = xs+isectPathSet (Only xs) (Only ys) = Only (isect xs ys)++{-+-- | Union of two 'PathSet's+union :: PathSet -> PathSet -> PathSet+union Everything ys = Everything+union xs Everything = Everything+union (Only xs) (Only ys) = Only (union xs ys)+-}++-- | Convert a list of 'SubPath's to a 'PathSet'.+sps2ps :: [SubPath] -> PathSet+sps2ps = Only . nubSort++-- | Convert a list of repo paths to a 'PathSet'.+-- Partial function! Use only with repo paths.+fps2ps :: [FilePath] -> PathSet+fps2ps = sps2ps . map fp2sp++-- | Convert a 'PathSet' to something that e.g. 'chooseTouching'+-- takes as parameter.+ps2fps :: PathSet -> Maybe [FilePath]+ps2fps = fmap (map sp2fp) . fromOnly++-- | Convert a 'PathSet' to a 'Doc'. Uses the English module+-- to generate a nicely readable list of file names.+showPathSet :: Only [SubPath] -> Doc+showPathSet Everything = text "all paths"+showPathSet (Only xs) = pathlist (map sp2fp xs)++-- | Lift a function transforming a list of 'FilePath' to one that+-- transforms a 'PathSet'.+liftToPathSet :: ([FilePath] -> [FilePath]) -> PathSet -> PathSet+liftToPathSet f = fmap (nubSort . map fp2sp . f . map sp2fp)++-- | Convert a 'FilePath' to a 'SubPath'.+--+-- Note: Should call this only with paths we get from the repository.+-- This guarantees that they are relative (to the repo dir).+fp2sp :: FilePath -> SubPath+fp2sp = fromJust . simpleSubPath++-- | Convert a 'SubPath' to a 'FilePath'. Same as 'toFilePath' and+-- only here for symmetry.+sp2fp :: SubPath -> FilePath+sp2fp = toFilePath
src/Darcs/UI/Commands/Move.hs view
@@ -16,8 +16,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.UI.Commands.Move ( move, mv ) where  import Prelude ()@@ -28,11 +26,17 @@ import Darcs.Util.SignalHandler ( withSignalsBlocked )  import Darcs.UI.Commands-    ( DarcsCommand(..), withStdOpts, nodefaults, commandAlias, amInHashedRepository )-import Darcs.UI.Flags ( DarcsFlag(Quiet)-    , doAllowCaseOnly, doAllowWindowsReserved, useCache, dryRun, umask-    , maybeFixSubPaths, fixSubPaths )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags )+    ( DarcsCommand(..), withStdOpts, nodefaults, commandAlias, amInHashedRepository+    , putInfo+    )+import Darcs.UI.Completion ( knownFileArgs )+import Darcs.UI.Flags+    ( DarcsFlag+    , allowCaseDifferingFilenames, allowWindowsReservedFilenames+    , useCache, dryRun, umask+    , maybeFixSubPaths, fixSubPaths+    )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Diff ( treeDiff ) import Darcs.Repository.Flags ( UpdateWorking (..), DiffAlgorithm(..) )@@ -45,13 +49,12 @@     , withRepoLock     , RepoJob(..)     , addPendingDiffToPending-    , listFiles     ) import Darcs.Patch.Witnesses.Ordered ( FL(..), (+>+) ) import Darcs.Patch.Witnesses.Sealed ( emptyGap, freeGap, joinGap, FreeLeft ) import Darcs.Util.Global ( debugMessage ) import qualified Darcs.Patch-import Darcs.Patch ( RepoPatch, PrimPatch, PrimOf )+import Darcs.Patch ( RepoPatch, PrimPatch ) import Darcs.Patch.Apply( ApplyState ) import Data.List ( nub, sort ) import qualified System.FilePath.Windows as WindowsFilePath@@ -68,6 +71,7 @@     , toFilePath     , AbsolutePath     )+import Darcs.Util.Printer ( text, hsep ) import Darcs.Util.Workaround ( renameFile )  moveDescription :: String@@ -89,30 +93,6 @@  "`ReadMe` and `README`).  If `--case-ok` is used, the repository might be\n" ++  "unusable on those systems!\n" -moveBasicOpts :: DarcsOption a (Bool -> Bool -> Maybe String -> a)-moveBasicOpts = O.allowProblematicFilenames ^ O.workingRepoDir--moveAdvancedOpts :: DarcsOption a (O.UMask -> a)-moveAdvancedOpts = O.umask--moveOpts :: DarcsOption a-            (Bool-             -> Bool-             -> Maybe String-             -> Maybe O.StdCmdAction-             -> Bool-             -> Bool-             -> O.Verbosity-             -> Bool-             -> O.UMask-             -> O.UseCache-             -> Maybe String-             -> Bool-             -> Maybe String-             -> Bool-             -> a)-moveOpts = moveBasicOpts `withStdOpts` moveAdvancedOpts- move :: DarcsCommand [DarcsFlag] move = DarcsCommand     { commandProgramName = "darcs"@@ -123,7 +103,7 @@     , commandExtraArgHelp = ["<SOURCE> ... <DESTINATION>"]     , commandCommand = moveCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = listFiles False+    , commandCompleteArgs = knownFileArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc moveAdvancedOpts     , commandBasicOptions = odesc moveBasicOpts@@ -131,6 +111,10 @@     , commandCheckOptions = ocheck moveOpts     , commandParseOptions = onormalise moveOpts     }+  where+    moveBasicOpts = O.allowProblematicFilenames ^ O.repoDir+    moveAdvancedOpts = O.umask+    moveOpts = moveBasicOpts `withStdOpts` moveAdvancedOpts  moveCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () moveCmd fps opts args@@ -235,31 +219,27 @@  withRepoAndState :: [DarcsFlag]                  -> (forall rt p wR wU .-                        (ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree, RepoPatch p) =>+                        (ApplyState p ~ Tree, RepoPatch p) =>                             (Repository rt p wR wU wR, Tree IO, Tree IO, Tree IO)                                 -> IO ())                  -> IO () withRepoAndState opts f =-    withRepoLock dr uc YesUpdateWorking um $ RepoJob $ \repo -> do+    withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RepoJob $ \repo -> do         work <- readPlainTree "."         cur <- readRecordedAndPending repo         recorded <- readRecorded repo         f (repo, work, cur, recorded)-  where-    dr = dryRun opts-    uc = useCache opts-    um = umask opts -simpleMove :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+simpleMove :: (RepoPatch p, ApplyState p ~ Tree)            => Repository rt p wR wU wT            -> [DarcsFlag] -> Tree IO -> Tree IO -> FilePath -> FilePath            -> IO () simpleMove repository opts cur work old_fp new_fp = do     doMoves repository opts cur work [(old_fp, new_fp)]-    unless (Quiet `elem` opts) $-        putStrLn $ unwords ["Moved:", old_fp, "to:", new_fp]+    putInfo opts $ hsep $ map text ["Moved:", old_fp, "to:", new_fp] -moveToDir :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+moveToDir :: (RepoPatch p, ApplyState p ~ Tree)           => Repository rt p wR wU wT           -> [DarcsFlag] -> Tree IO -> Tree IO -> [FilePath] -> FilePath           -> IO ()@@ -267,10 +247,9 @@     let movetargets = map ((finaldir </>) . takeFileName) moved         moves = zip moved movetargets     doMoves repository opts cur work moves-    unless (Quiet `elem` opts) $-      putStrLn $ unwords $ ["Moved:"] ++ moved ++ ["to:", finaldir]+    putInfo opts $ hsep $ map text $ ["Moved:"] ++ moved ++ ["to:", finaldir] -doMoves :: (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+doMoves :: (RepoPatch p, ApplyState p ~ Tree)           => Repository rt p wR wU wT           -> [DarcsFlag] -> Tree IO -> Tree IO           -> [(FilePath, FilePath)] -> IO ()@@ -317,8 +296,7 @@                 then Just <$> deleteNewFromRepoPatches                 else return Nothing         else do-          unless (Quiet `elem` opts) $-              putStrLn "Detected post-hoc move."+          putInfo opts $ text "Detected post-hoc move."           -- Post-hoc move - user has moved/deleted the file in working, so           -- we can hopefully make a move patch to make the repository           -- consistent.@@ -331,7 +309,7 @@                        else return $ emptyGap NilFL   where     newIsOkWindowsPath =-        doAllowWindowsReserved opts || WindowsFilePath.isValid new+        allowWindowsReservedFilenames ? opts || WindowsFilePath.isValid new      newNotOkWindowsPathMsg =         "The filename " ++ new ++ " is not valid under Windows.\n"@@ -340,9 +318,8 @@     -- If we're moving to a file/dir that was recorded, but has been deleted,     -- we need to add patches to pending that remove the original.     deleteNewFromRepoPatches = do-        unless (Quiet `elem` opts) $-            putStrLn $ "Existing recorded contents of " ++ new-                       ++ " will be overwritten."+        putInfo opts $ text $+          "Existing recorded contents of " ++ new ++ " will be overwritten."         ftf <- filetypeFunction         let curNoNew = modifyTree cur (floatPath new) Nothing         -- Return patches to remove new, so that the move patch@@ -352,10 +329,10 @@     -- Check if the passed tree has the new filepath. The old path is removed     -- from the tree before checking if the new path is present.     hasNew s = treeHas_case (modifyTree s (floatPath old) Nothing) new-    treeHas_case = if doAllowCaseOnly opts then treeHas else treeHasAnycase+    treeHas_case = if allowCaseDifferingFilenames ? opts then treeHas else treeHasAnycase      alreadyExists inWhat =-        if doAllowCaseOnly opts+        if allowCaseDifferingFilenames ? opts             then "A file or dir named "++new++" already exists in "                   ++ inWhat ++ "."             else "A file or dir named "++new++" (or perhaps differing "
src/Darcs/UI/Commands/Optimize.hs view
@@ -15,56 +15,49 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings #-} -module Darcs.UI.Commands.Optimize ( optimize, doOptimizeHTTP ) where+module Darcs.UI.Commands.Optimize ( optimize ) where  import Prelude () import Darcs.Prelude -import Control.Exception ( finally )-import Control.Monad ( when, unless, forM, forM_ )+import Control.Monad ( when, unless, forM_ )+import Data.List ( nub ) import Data.Maybe ( isJust, fromJust )-import Data.List ( sort )-import Data.Set ( difference ) import System.Directory     ( getDirectoryContents     , doesDirectoryExist-    , doesFileExist     , renameFile-    , getModificationTime     , createDirectoryIfMissing     , removeFile     , getHomeDirectory     )-import System.IO.Unsafe ( unsafeInterleaveIO )-import qualified Data.ByteString.Char8 as BS-import qualified Data.ByteString.Lazy as BL---import Darcs.Patch.PatchInfoAnd ( extractHash )+import qualified Data.ByteString.Char8 as BC import Darcs.UI.Commands ( DarcsCommand(..), nodefaults                          , amInHashedRepository, amInRepository, putInfo                          , normalCommand, withStdOpts )-import Darcs.Repository.Prefs ( getPreflist, getCaches, globalCacheDir, oldGlobalCacheDir )+import Darcs.UI.Completion ( noArgs )+import Darcs.Repository.Prefs ( getPreflist, getCaches, globalCacheDir ) import Darcs.Repository     ( Repository+    , repoLocation     , withRepoLock     , RepoJob(..)     , readRepo     , reorderInventory     , cleanRepository     , replacePristine-    , maybeIdentifyRepository     )-import Darcs.Repository.Internal ( IdentifyRepo(..) )-import Darcs.Repository.HashedRepo ( inventoriesDir, patchesDir, pristineDir,-                                    hashedInventory, filterDirContents,-                                    readHashedPristineRoot, listInventoriesRepoDir,-                                    listPatchesLocalBucketed, set, unset, inv2pris )+import Darcs.Repository.Job ( withOldRepoLock )+import Darcs.Repository.Identify ( findAllReposInDir )+import Darcs.Repository.Hashed ( inventoriesDir, patchesDir, pristineDir,+                                    hashedInventory,+                                    listInventoriesRepoDir,+                                    listPatchesLocalBucketed, diffHashLists, peekPristineHash )+import Darcs.Repository.Packs ( createPacks )+import Darcs.Repository.Pending ( pendingName ) import Darcs.Repository.HashedIO ( getHashedFiles )-import Darcs.Repository.Old ( oldRepoFailMsg )-import Darcs.Repository.InternalTypes ( Repository(..), Pristine(..) ) import Darcs.Patch.Witnesses.Ordered      ( mapFL      , bunchFL@@ -72,8 +65,8 @@      ) import Darcs.Patch ( IsRepoType, RepoPatch ) import Darcs.Patch.Set-    ( newset2RL-    , newset2FL+    ( patchSet2RL+    , patchSet2FL     , progressPatchSet     ) import Darcs.Patch.Apply( ApplyState )@@ -85,8 +78,13 @@     , writeAtomicFilePS     , rmRecursive     , removeFileMayNotExist+    , writeBinFile     )-import Darcs.Util.File ( withCurrentDirectory, getRecursiveContents )+import Darcs.Util.File+    ( withCurrentDirectory+    , getRecursiveContents+    , doesDirectoryReallyExist+    ) import Darcs.UI.External ( catchall ) import Darcs.Util.Progress     ( beginTedious@@ -99,17 +97,13 @@ import System.FilePath.Posix     ( takeExtension     , (</>)-    , (<.>)-    , takeFileName     , joinPath     ) import Text.Printf ( printf )-import System.Posix.Files ( getFileStatus, isDirectory ) import Darcs.UI.Flags-    (  DarcsFlag(Compress)-    , compression, verbosity, useCache, umask )+    (  DarcsFlag, verbosity, useCache, umask ) import Darcs.UI.Options ( DarcsOption, (^), oid, odesc, ocheck, onormalise-                        , defaultFlags, parseFlags )+                        , defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Flags     ( UpdateWorking (..), DryRun ( NoDryRun ), UseCache (..), UMask (..)@@ -125,7 +119,7 @@     , RepoProperty ( HashedInventory )     ) import Darcs.Repository.PatchIndex-import qualified Darcs.Repository.HashedRepo as HashedRepo+import qualified Darcs.Repository.Hashed as HashedRepo import Darcs.Repository.State ( readRecorded )  import Darcs.Util.Tree@@ -141,11 +135,7 @@     ( writeDarcsHashed     , decodeDarcsSize     )-import Codec.Archive.Tar ( write )-import Codec.Archive.Tar.Entry ( fileEntry, toTarPath )-import Codec.Compression.GZip ( compress ) - optimizeDescription :: String optimizeDescription = "Optimize the repository." @@ -176,24 +166,10 @@     }  commonBasicOpts :: DarcsOption a (Maybe String -> UMask -> a)-commonBasicOpts = O.workingRepoDir ^ O.umask+commonBasicOpts = O.repoDir ^ O.umask+ commonAdvancedOpts :: DarcsOption a a commonAdvancedOpts = oid-commonOpts :: DarcsOption a-              (Maybe String-               -> UMask-               -> Maybe O.StdCmdAction-               -> Bool-               -> Bool-               -> O.Verbosity-               -> Bool-               -> UseCache-               -> Maybe String-               -> Bool-               -> Maybe String-               -> Bool-               -> a)-commonOpts = commonBasicOpts `withStdOpts` commonAdvancedOpts  common :: DarcsCommand [DarcsFlag] common = DarcsCommand@@ -206,13 +182,15 @@     , commandHelp = undefined     , commandDescription = undefined     , commandCommand =  undefined-    , commandGetArgPossibilities = undefined+    , commandCompleteArgs = noArgs     , commandAdvancedOptions = odesc commonAdvancedOpts     , commandBasicOptions = odesc commonBasicOpts     , commandDefaults = defaultFlags commonOpts     , commandCheckOptions = ocheck commonOpts     , commandParseOptions = onormalise commonOpts     }+  where+    commonOpts = commonBasicOpts `withStdOpts` commonAdvancedOpts   optimizeClean :: DarcsCommand [DarcsFlag]@@ -225,7 +203,8 @@  optimizeCleanCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () optimizeCleanCmd _ opts _ =-    withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+    withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RepoJob $ \repository -> do       cleanRepository repository -- garbage collect pristine.hashed, inventories and patches directories       putInfo opts "Done cleaning repository!" @@ -248,9 +227,10 @@  optimizeHttpCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () optimizeHttpCmd _ opts _ =-    withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+    withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RepoJob $ \repository -> do       cleanRepository repository -- garbage collect pristine.hashed, inventories and patches directories-      doOptimizeHTTP repository+      createPacks repository       putInfo opts "Done creating packs!"  optimizePristine :: DarcsCommand [DarcsFlag]@@ -264,7 +244,8 @@  optimizePristineCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () optimizePristineCmd _ opts _ =-    withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+    withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RepoJob $ \repository -> do       cleanRepository repository -- garbage collect pristine.hashed, inventories and patches directories       doOptimizePristine opts repository       putInfo opts "Done optimizing pristine!"@@ -287,34 +268,39 @@  optimizeCompressCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () optimizeCompressCmd _ opts _ =-    withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+    withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RepoJob $ \repository -> do       cleanRepository repository -- garbage collect pristine.hashed, inventories and patches directories-      optimizeCompression [Compress]+      optimizeCompression O.GzipCompression opts       putInfo opts "Done optimizing by compression!"  optimizeUncompressCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () optimizeUncompressCmd _ opts _ =-    withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+    withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RepoJob $ \repository -> do       cleanRepository repository -- garbage collect pristine.hashed, inventories and patches directories-      optimizeCompression []+      optimizeCompression O.NoCompression opts       putInfo opts "Done optimizing by uncompression!" -optimizeCompression :: [DarcsFlag] -> IO ()-optimizeCompression opts = do+optimizeCompression :: O.Compression -> [DarcsFlag] -> IO ()+optimizeCompression compression opts = do     putInfo opts "Optimizing (un)compression of patches..."-    do_compress (darcsdir++"/patches")+    do_compress (darcsdir ++ "/patches")     putInfo opts "Optimizing (un)compression of inventories..."-    do_compress (darcsdir++"/inventories")-    where do_compress f =-              do isd <- doesDirectoryExist f-                 if isd then withCurrentDirectory f $-                             do fs <- filter notdot `fmap` getDirectoryContents "."-                                mapM_ do_compress fs-                        else if Compress `elem` opts-                             then gzReadFilePS f >>= gzWriteAtomicFilePS f-                             else gzReadFilePS f >>= writeAtomicFilePS f-          notdot ('.':_) = False-          notdot _ = True+    do_compress (darcsdir ++ "/inventories")+    where+      do_compress f = do+        isd <- doesDirectoryExist f+        if isd+          then withCurrentDirectory f $ do+                 fs <- filter notdot `fmap` getDirectoryContents "."+                 mapM_ do_compress fs+          else gzReadFilePS f >>=+               case compression of+                 O.GzipCompression -> gzWriteAtomicFilePS f+                 O.NoCompression -> writeAtomicFilePS f+      notdot ('.':_) = False+      notdot _ = True  optimizeEnablePatchIndex :: DarcsCommand [DarcsFlag] optimizeEnablePatchIndex = common@@ -336,14 +322,17 @@  optimizeEnablePatchIndexCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () optimizeEnablePatchIndexCmd _ opts _ =-    withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do-      createOrUpdatePatchIndexDisk repository+    withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RepoJob $ \repository -> do+      ps <- readRepo repository+      createOrUpdatePatchIndexDisk repository ps       putInfo opts "Done enabling patch index!"  optimizeDisablePatchIndexCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () optimizeDisablePatchIndexCmd _ opts _ =-    withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \(Repo repodir _ _ _) -> do-      deletePatchIndex repodir+    withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RepoJob $ \repo -> do+      deletePatchIndex (repoLocation repo)       putInfo opts "Done disabling patch index!"  optimizeReorder :: DarcsCommand [DarcsFlag]@@ -359,30 +348,11 @@  optimizeReorderCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () optimizeReorderCmd _ opts _ =-    withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do-      reorderInventory repository (compression opts) YesUpdateWorking (verbosity opts)+    withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RepoJob $ \repository -> do+      reorderInventory repository (O.compress ? opts) YesUpdateWorking (verbosity ? opts)       putInfo opts "Done reordering!" -optimizeRelinkBasicOpts :: DarcsOption a-                           (Maybe String -> UMask -> [AbsolutePath] -> a)-optimizeRelinkBasicOpts = commonBasicOpts ^ O.siblings-optimizeRelinkOpts :: DarcsOption a-                      (Maybe String-                       -> UMask-                       -> [AbsolutePath]-                       -> Maybe O.StdCmdAction-                       -> Bool-                       -> Bool-                       -> O.Verbosity-                       -> Bool-                       -> UseCache-                       -> Maybe String-                       -> Bool-                       -> Maybe String-                       -> Bool-                       -> a)-optimizeRelinkOpts = optimizeRelinkBasicOpts `withStdOpts` commonAdvancedOpts- optimizeRelink :: DarcsCommand [DarcsFlag] optimizeRelink = common     { commandName = "relink"@@ -395,10 +365,14 @@     , commandCheckOptions = ocheck optimizeRelinkOpts     , commandParseOptions = onormalise optimizeRelinkOpts     }+  where+    optimizeRelinkBasicOpts = commonBasicOpts ^ O.siblings+    optimizeRelinkOpts = optimizeRelinkBasicOpts `withStdOpts` commonAdvancedOpts  optimizeRelinkCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () optimizeRelinkCmd _ opts _ =-    withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+    withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RepoJob $ \repository -> do       cleanRepository repository -- garbage collect pristine.hashed, inventories and patches directories       doRelink opts       putInfo opts "Done relinking!"@@ -434,14 +408,14 @@  "repository, or if you pulled the same patch from a remote repository\n" ++  "into multiple local repositories." -doOptimizePristine :: (RepoPatch p, ApplyState p ~ Tree) => [DarcsFlag] -> Repository rt p wR wU wT -> IO ()+doOptimizePristine :: [DarcsFlag] -> Repository rt p wR wU wT -> IO () doOptimizePristine opts repo = do-    inv <- BS.readFile (darcsdir </> "hashed_inventory")-    let linesInv = BS.split '\n' inv+    inv <- BC.readFile (darcsdir </> "hashed_inventory")+    let linesInv = BC.split '\n' inv     case linesInv of       [] -> return ()       (pris_line:_) ->-          let size = decodeDarcsSize $ BS.drop 9 pris_line+          let size = decodeDarcsSize $ BC.drop 9 pris_line            in when (isJust size) $ do putInfo opts "Optimizing hashed pristine..."                                       readRecorded repo >>= replacePristine repo                                       cleanRepository repo@@ -473,14 +447,12 @@ -- Only 'optimize' commands that works on old-fashionned repositories optimizeUpgradeCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () optimizeUpgradeCmd _ opts _ = do-  debugMessage "Upgrading to hashed..."   rf <- identifyRepoFormat "."   debugMessage "Found our format"   if formatHas HashedInventory rf      then putInfo opts "No action taken because this repository already is hashed."-     else do putInfo opts "Checking repository in case of corruption..."-             withRepoLock NoDryRun YesUseCache YesUpdateWorking NoUMask $ RepoJob $ \repository ->-               actuallyUpgradeFormat repository+     else do putInfo opts "Upgrading to hashed..."+             withOldRepoLock $ RepoJob actuallyUpgradeFormat  actuallyUpgradeFormat   :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)@@ -490,98 +462,48 @@   patches <- readRepo repository   let k = "Hashing patch"   beginTedious k-  tediousSize k (lengthRL $ newset2RL patches)+  tediousSize k (lengthRL $ patchSet2RL patches)   let patches' = progressPatchSet k patches   cache <- getCaches YesUseCache "."-  let compr = compression [] -- default compression-  HashedRepo.writeTentativeInventory cache compr patches'+  -- TODO Why use the default and not what the user provided?+  -- Is it because the author couldn't be bothered to add the option?+  -- Or is there a more profound reason?+  -- Such things justify a few lines of comment!+  let compressDefault = O.compress ? []+  HashedRepo.writeTentativeInventory cache compressDefault patches'   endTedious k   -- convert pristine by applying patches   -- the faster alternative would be to copy pristine, but the apply method is more reliable-  let patchesToApply = progressFL "Applying patch" $ newset2FL patches'+  let patchesToApply = progressFL "Applying patch" $ patchSet2FL patches'   createDirectoryIfMissing False $ darcsdir </> hashedDir HashedPristineDir   -- We ignore the returned root hash, we don't use it.-  _ <- writeDarcsHashed emptyTree $ darcsdir </> "pristine.hashed"-  sequence_ $ mapFL HashedRepo.applyToTentativePristine $ bunchFL 100 patchesToApply+  _ <- writeDarcsHashed emptyTree $ darcsdir </> hashedDir HashedPristineDir+  writeBinFile (darcsdir++"/tentative_pristine") ""+  sequence_ $ mapFL HashedRepo.applyToTentativePristineCwd $ bunchFL 100 patchesToApply   -- now make it official-  HashedRepo.finalizeTentativeChanges repository compr+  HashedRepo.finalizeTentativeChanges repository compressDefault   writeRepoFormat (createRepoFormat PatchFormat1 WithWorkingDir) (darcsdir </> "format")   -- clean out old-fashioned junk   debugMessage "Cleaning out old-fashioned repository files..."-  removeFile   $ darcsdir </> "inventory"-  removeFile   $ darcsdir </> "tentative_inventory"+  removeFileMayNotExist $ darcsdir </> "inventory"+  removeFileMayNotExist $ darcsdir </> "tentative_inventory"   rmRecursive (darcsdir </> "pristine") `catchall` rmRecursive (darcsdir </> "current")   rmGzsIn (darcsdir </> "patches")   rmGzsIn (darcsdir </> "inventories")   let checkpointDir = darcsdir </> "checkpoints"   hasCheckPoints <- doesDirectoryExist checkpointDir   when hasCheckPoints $ rmRecursive checkpointDir+  removeFileMayNotExist (pendingName ++ ".tentative")+  removeFileMayNotExist pendingName  where   rmGzsIn dir =     withCurrentDirectory dir $ do       gzs <- filter ((== ".gz") . takeExtension) `fmap` getDirectoryContents "."       mapM_ removeFile gzs -doOptimizeHTTP-  :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-  => Repository rt p wR wU wT -> IO ()-doOptimizeHTTP repo = flip finally (mapM_ removeFileIfExists-  [ darcsdir </> "meta-filelist-inventories"-  , darcsdir </> "meta-filelist-pristine"-  , basicTar <.> "part"-  , patchesTar <.> "part"-  ]) $ do-  rf <- identifyRepoFormat "."-  -- function is exposed in API so could be called on non-hashed repo-  unless (formatHas HashedInventory rf) $ fail oldRepoFailMsg-  createDirectoryIfMissing False packsDir-  -- pristine hash-  Just hash <- readHashedPristineRoot repo-  writeFile ( packsDir </> "pristine" ) hash-  -- pack patchesTar-  ps <- mapFL hashedPatchFileName . newset2FL <$> readRepo repo-  is <- map ((darcsdir </> "inventories") </>) <$> HashedRepo.listInventories-  writeFile (darcsdir </> "meta-filelist-inventories") . unlines $-    map takeFileName is-  -- tinkering with zlib's compression parameters does not make-  -- any noticeable difference in generated archive size.-  -- switching to bzip2 does OTOH (~25% size gain).-  BL.writeFile (patchesTar <.> "part") . compress . write =<<-    mapM fileEntry' ((darcsdir </> "meta-filelist-inventories") : ps ++-    reverse is)-  renameFile (patchesTar <.> "part") patchesTar-  -- pack basicTar-  pr <- sortByMTime =<< dirContents "pristine.hashed"-  writeFile (darcsdir </> "meta-filelist-pristine") . unlines $-    map takeFileName pr-  BL.writeFile (basicTar <.> "part") . compress . write =<< mapM fileEntry' (-    [ darcsdir </> "meta-filelist-pristine"-    , darcsdir </> "hashed_inventory"-    ] ++ reverse pr)-  renameFile (basicTar <.> "part") basicTar- where-  packsDir = darcsdir </> "packs"-  basicTar = packsDir </> "basic.tar.gz"-  patchesTar = packsDir </> "patches.tar.gz"-  fileEntry' x = unsafeInterleaveIO $ do-    content <- BL.fromChunks . return <$> gzReadFilePS x-    tp <- either fail return $ toTarPath False x-    return $ fileEntry tp content-  dirContents d = map ((darcsdir </> d) </>) <$>-    filterDirContents d (const True)-  hashedPatchFileName x = case extractHash x of-    Left _ -> fail "unexpected unhashed patch"-    Right h -> darcsdir </> "patches" </> h-  sortByMTime xs = map snd . sort <$> mapM (\x -> (\t -> (t, x)) <$>-    getModificationTime x) xs-  removeFileIfExists x = do-    ex <- doesFileExist x-    when ex $ removeFile x- optimizeBucketed :: [DarcsFlag] -> IO () optimizeBucketed opts = do   putInfo opts "Migrating global cache to bucketed format."-  gOldCacheDir <- oldGlobalCacheDir   gCacheDir <- globalCacheDir    case gCacheDir of@@ -594,13 +516,6 @@       toBucketed gCachePristineDir gCachePristineDir       toBucketed gCacheInventoriesDir gCacheInventoriesDir       toBucketed gCachePatchesDir gCachePatchesDir-      case gOldCacheDir of-        Nothing -> debugMessage "Old global cache doesn't exist."-        Just gOldCacheDir' -> do-          debugMessage "Making bucketed cache from old cache."-          toBucketed (joinPath [gOldCacheDir', pristineDir]) gCachePristineDir-          toBucketed (joinPath [gOldCacheDir', inventoriesDir]) gCacheInventoriesDir-          toBucketed (joinPath [gOldCacheDir', patchesDir]) gCachePatchesDir       putInfo opts "Done making bucketed cache!"   where     toBucketed :: FilePath -> FilePath -> IO ()@@ -613,8 +528,8 @@                   createDirectoryIfMissing True (dest </> subDir)                 fileNames <- getDirectoryContents src                 forM_ fileNames $ \file -> do-                  fileStatus <- getFileStatus (src </> file)-                  if not $ isDirectory fileStatus+                  exists <- doesDirectoryReallyExist (src </> file)+                  if not $ exists                     then renameFile' src dest file                     else return ()         else do@@ -668,11 +583,11 @@   putInfo opts "\nLooking for repositories in the following directories:"   putInfo opts $ text $ unlines dirs   gCacheDir' <- globalCacheDir-  repoPaths'  <- mapM getRecursiveDarcsRepos dirs+  repoPaths'  <- mapM findAllReposInDir dirs    putInfo opts "Finished listing repositories." -  let repoPaths         = unset . set $ concat repoPaths'+  let repoPaths         = nub $ concat repoPaths'       gCache            = fromJust gCacheDir'       gCacheInvDir      = gCache </> inventoriesDir       gCachePatchesDir  = gCache </> patchesDir@@ -696,33 +611,11 @@   remove' dir s1 s2 =     mapM_ (removeFileMayNotExist . (\hashedFile ->       dir </> bucketFolder hashedFile </> hashedFile))-      (unset $ set s1 `difference` set s2)+      (diffHashLists s1 s2)    getPristine :: String -> IO [String]   getPristine darcsDir = do     i <- gzReadFilePS (darcsDir </> darcsdir </> hashedInventory)-    getHashedFiles (darcsDir </> darcsdir </> pristineDir) [inv2pris i]+    getHashedFiles (darcsDir </> darcsdir </> pristineDir) [peekPristineHash i] --- |getRecursiveDarcsRepos returns all paths to repositories under topdir.-getRecursiveDarcsRepos :: FilePath -> IO [FilePath]-getRecursiveDarcsRepos topdir = do-  isDir <- doesDirectoryExist topdir-  if isDir-    then do-      status <- maybeIdentifyRepository NoUseCache topdir-      case status of-        GoodRepository (Repo _ _ pris _)  ->-                                case pris of-                                  HashedPristine -> return [topdir]-                                  _ -> return [] -- old fashioned or broken repo-        _                 -> getRecursiveDarcsRepos' topdir-    else return [] -  where-    getRecursiveDarcsRepos' d = do-      names <- getDirectoryContents d-      let properNames = filter (\x -> head x /= '.') names-      paths <- forM properNames $ \name -> do-        let path = d </> name-        getRecursiveDarcsRepos path-      return (concat paths)
src/Darcs/UI/Commands/Pull.hs view
@@ -15,8 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.UI.Commands.Pull ( -- * Commands.                                 pull, fetch,                                 pullCmd, StandardPatchApplier,@@ -27,44 +25,29 @@ import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) )- import System.Exit ( exitSuccess ) import Control.Monad ( when, unless, (>=>) ) import Data.List ( nub ) import Data.Maybe ( fromMaybe )  import Darcs.UI.Commands-    ( DarcsCommand(..), withStdOpts+    ( DarcsCommand(..)+    , withStdOpts     , putInfo+    , putVerbose     , setEnvDarcsPatches     , defaultRepo     , amInHashedRepository     ) import Darcs.UI.Flags     ( DarcsFlag-        ( AllowConflicts-        , Complement-        , DryRun-        , Intersection-        , MarkConflicts-        , NoAllowConflicts-        , SkipConflicts-        , Verbose-        , XMLOutput-        , Quiet-        , AllowUnrelatedRepos-        )     , fixUrl, getOutput-    , doReverse, verbosity,  dryRun, umask, useCache, selectDeps+    , changesReverse, verbosity,  dryRun, umask, useCache, selectDeps     , remoteRepos, reorder, setDefault-    , isUnified, hasSummary-    , isInteractive-    )-import Darcs.UI.Options-    ( DarcsOption, (^), odesc, ocheck, onormalise-    , defaultFlags, parseFlags+    , withContext, hasXmlOutput+    , isInteractive, quiet     )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Flags ( UpdateWorking (..) ) import Darcs.Repository@@ -73,7 +56,6 @@     , withRepoLock     , RepoJob(..)     , readRepo-    , checkUnrelatedRepos     , modifyCache     , modifyCache     , Cache(..)@@ -84,7 +66,7 @@  import qualified Darcs.Repository.Cache as DarcsCache import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, info, hopefully, patchDesc )-import Darcs.Patch ( IsRepoType, RepoPatch, description, PrimOf )+import Darcs.Patch ( IsRepoType, RepoPatch, description ) import Darcs.Patch.Bundle( makeBundleN, patchFilename ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.Set ( Origin, PatchSet(..), SealedPatchSet )@@ -94,11 +76,12 @@     ( (:>)(..), (:\/:)(..), FL(..), RL(..)     , mapFL, nullFL, reverseFL, mapFL_FL ) import Darcs.Patch.Permutations ( partitionFL )-import Darcs.Repository.Prefs ( addToPreflist, addRepoSource, getPreflist )-import Darcs.Repository.Motd (showMotd )+import Darcs.Repository.Prefs ( addToPreflist, addRepoSource, getPreflist, showMotd ) import Darcs.Patch.Depends ( findUncommon, findCommonWithThem,-                             newsetIntersection, newsetUnion )+                             patchSetIntersection, patchSetUnion ) import Darcs.UI.ApplyPatches ( PatchApplier(..), StandardPatchApplier(..) )+import Darcs.UI.Completion ( prefArgs )+import Darcs.UI.Commands.Util ( checkUnrelatedRepos ) import Darcs.UI.SelectChanges     ( WhichChanges(..)     , runSelection@@ -106,15 +89,13 @@     ) import qualified Darcs.UI.SelectChanges as S ( PatchSelectionOptions (..) ) import Darcs.Util.Exception ( clarifyErrors )-import Darcs.Util.Printer ( putDocLn, vcat, ($$), text, putDoc )+import Darcs.Util.Printer ( vcat, ($$), text, putDoc ) import Darcs.Util.Lock ( writeDocBinFile ) import Darcs.Util.Path ( useAbsoluteOrStd, stdOut, AbsolutePath ) import Darcs.Util.Workaround ( getCurrentDirectory ) import Darcs.Util.Text ( quote ) import Darcs.Util.Tree( Tree )-#include "impossible.h" - pullDescription :: String pullDescription =  "Copy and apply patches from another repository to this one."@@ -154,157 +135,6 @@  , "the help of `pull` to know more."  ] -pullBasicOpts :: DarcsOption a-                 ([O.MatchFlag]-                  -> O.Reorder-                  -> Maybe Bool-                  -> Maybe O.AllowConflicts-                  -> O.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 -- True-    ^ 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.WantGuiPause-                     -> O.NetworkOptions-                     -> a)-pullAdvancedOpts-    = O.repoCombinator-    ^ O.compress-    ^ O.useIndex-    ^ O.remoteRepos-    ^ O.setScriptsExecutable-    ^ O.umask-    ^ O.restrictPaths-    ^ O.changesReverse-    ^ O.pauseForGui-    ^ O.network--pullOpts :: DarcsOption a-            ([O.MatchFlag]-             -> O.Reorder-             -> Maybe Bool-             -> Maybe O.AllowConflicts-             -> O.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.WantGuiPause-             -> O.NetworkOptions-             -> O.UseCache-             -> Maybe String-             -> Bool-             -> Maybe String-             -> Bool-             -> a)-pullOpts = pullBasicOpts `withStdOpts` pullAdvancedOpts--fetchBasicOpts :: DarcsOption a-                  ([O.MatchFlag]-                   -> Maybe Bool-                   -> O.DryRun-                   -> Maybe O.Summary-                   -> O.SelectDeps-                   -> Maybe Bool-                   -> Maybe String-                   -> Maybe O.Output-                   -> Bool-                   -> O.DiffAlgorithm-                   -> a)-fetchBasicOpts-    = O.matchSeveral-    ^ O.interactive -- True-    ^ O.dryRun-    ^ O.summary-    ^ O.selectDeps-    ^ O.setDefault-    ^ O.workingRepoDir-    ^ O.output-    ^ O.allowUnrelatedRepos-    ^ O.diffAlgorithm--fetchAdvancedOpts :: DarcsOption a-                     (O.RepoCombinator -> O.RemoteRepos -> O.NetworkOptions -> a)-fetchAdvancedOpts-    = O.repoCombinator-    ^ O.remoteRepos-    ^ O.network--fetchOpts :: DarcsOption a-             ([O.MatchFlag]-              -> Maybe Bool-              -> O.DryRun-              -> Maybe O.Summary-              -> O.SelectDeps-              -> Maybe Bool-              -> Maybe String-              -> Maybe O.Output-              -> Bool-              -> O.DiffAlgorithm-              -> Maybe O.StdCmdAction-              -> Bool-              -> Bool-              -> O.Verbosity-              -> Bool-              -> O.RepoCombinator-              -> O.RemoteRepos-              -> O.NetworkOptions-              -> O.UseCache-              -> Maybe String-              -> Bool-              -> Maybe String-              -> Bool-              -> a)-fetchOpts = fetchBasicOpts `withStdOpts` fetchAdvancedOpts- fetch :: DarcsCommand [DarcsFlag] fetch = DarcsCommand     { commandProgramName = "darcs"@@ -315,14 +145,31 @@     , commandExtraArgHelp = ["[REPOSITORY]..."]     , commandCommand = fetchCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = getPreflist "repos"+    , commandCompleteArgs = prefArgs "repos"     , commandArgdefaults = defaultRepo-    , commandAdvancedOptions = odesc fetchAdvancedOpts-    , commandBasicOptions = odesc fetchBasicOpts-    , commandDefaults = defaultFlags fetchOpts-    , commandCheckOptions = ocheck fetchOpts-    , commandParseOptions = onormalise fetchOpts+    , commandAdvancedOptions = odesc advancedOpts+    , commandBasicOptions = odesc basicOpts+    , commandDefaults = defaultFlags allOpts+    , commandCheckOptions = ocheck allOpts+    , commandParseOptions = onormalise allOpts     }+  where+    basicOpts+      = O.matchSeveral+      ^ O.interactive -- True+      ^ O.dryRun+      ^ O.summary+      ^ O.selectDeps+      ^ O.setDefault+      ^ O.repoDir+      ^ O.output+      ^ O.allowUnrelatedRepos+      ^ O.diffAlgorithm+    advancedOpts+      = O.repoCombinator+      ^ O.remoteRepos+      ^ O.network+    allOpts = basicOpts `withStdOpts` advancedOpts  pull :: DarcsCommand [DarcsFlag] pull = DarcsCommand@@ -334,44 +181,67 @@     , commandExtraArgHelp = ["[REPOSITORY]..."]     , commandCommand = pullCmd StandardPatchApplier     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = getPreflist "repos"+    , commandCompleteArgs = prefArgs "repos"     , commandArgdefaults = defaultRepo-    , commandAdvancedOptions = odesc pullAdvancedOpts-    , commandBasicOptions = odesc pullBasicOpts-    , commandDefaults = defaultFlags pullOpts-    , commandCheckOptions = ocheck pullOpts-    , commandParseOptions = onormalise pullOpts+    , commandAdvancedOptions = odesc advancedOpts+    , commandBasicOptions = odesc basicOpts+    , commandDefaults = defaultFlags allOpts+    , commandCheckOptions = ocheck allOpts+    , commandParseOptions = onormalise allOpts     }--mergeOpts :: [DarcsFlag] -> [DarcsFlag]-mergeOpts opts | NoAllowConflicts `elem` opts = opts-                | AllowConflicts   `elem` opts = opts-                | otherwise                    = MarkConflicts : opts+  where+    basicOpts+      = O.matchSeveral+      ^ O.reorder+      ^ O.interactive+      ^ O.conflictsYes+      ^ O.externalMerge+      ^ O.runTest+      ^ O.dryRunXml+      ^ O.summary+      ^ O.selectDeps+      ^ O.setDefault+      ^ O.repoDir+      ^ O.allowUnrelatedRepos+      ^ O.diffAlgorithm+    advancedOpts+      = O.repoCombinator+      ^ O.compress+      ^ O.useIndex+      ^ O.remoteRepos+      ^ O.setScriptsExecutable+      ^ O.umask+      ^ O.restrictPaths+      ^ O.changesReverse+      ^ O.pauseForGui+      ^ O.network+    allOpts = basicOpts `withStdOpts` advancedOpts -pullCmd :: PatchApplier pa => pa -> (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()+pullCmd+  :: PatchApplier pa+  => pa -> (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () pullCmd patchApplier (_,o) opts repos =   do     pullingFrom <- mapM (fixUrl o) repos-    withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $+    withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $      repoJob patchApplier opts $ \patchProxy initRepo -> do        let repository = modifyCache initRepo $ addReposToCache pullingFrom       (_, Sealed (us' :\/: to_be_pulled))-          <- fetchPatches o opts' repos "pull" repository+          <- fetchPatches o opts repos "pull" repository       let from_whom = error "Internal error: pull shouldn't need a 'from' address"-      applyPatches patchApplier patchProxy "pull" opts' from_whom repository us' to_be_pulled+      applyPatches patchApplier patchProxy "pull" opts from_whom repository us' to_be_pulled     where-      opts' = mergeOpts opts       addReposToCache repos' (Ca cache) = Ca $ [ toReadOnlyCache r | r <- repos' ] ++  cache       toReadOnlyCache = Cache DarcsCache.Repo NotWritable   fetchCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () fetchCmd (_,o) opts repos =-    withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $+    withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $ RepoJob $         fetchPatches o opts repos "fetch" >=> makeBundle opts -fetchPatches :: forall rt p wR wU . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+fetchPatches :: forall rt p wR wU . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)              => AbsolutePath -> [DarcsFlag] -> [String] -> String              -> Repository rt p wR wU wR              -> IO (SealedPatchSet rt p Origin,@@ -383,15 +253,17 @@   when (null repodirs) $         fail "Can't pull from current repository!"   old_default <- getPreflist "defaultrepo"-  when (old_default == repodirs && XMLOutput `notElem` opts) $-      let pulling = if DryRun `elem` opts then "Would pull" else "Pulling"+  when (old_default == repodirs && not (hasXmlOutput opts)) $+      let pulling = case dryRun ? opts of+                      O.YesDryRun -> "Would pull"+                      O.NoDryRun -> "Pulling"       in  putInfo opts $ text $ pulling++" from "++concatMap quote repodirs++"..."   (Sealed them, Sealed compl) <- readRepos repository opts repodirs-  addRepoSource (head repodirs) (dryRun opts) (remoteRepos opts) (setDefault False opts)+  addRepoSource (head repodirs) (dryRun ? opts) (remoteRepos ? opts) (setDefault False opts)   mapM_ (addToPreflist "repos") repodirs-  unless (Quiet `elem` opts || XMLOutput `elem` opts) $ mapM_ showMotd repodirs+  unless (quiet opts || hasXmlOutput opts) $ mapM_ showMotd repodirs   us <- readRepo repository-  checkUnrelatedRepos (AllowUnrelatedRepos `elem` opts) us them+  checkUnrelatedRepos (parseFlags O.allowUnrelatedRepos opts) us them    common :> _ <- return $ findCommonWithThem us them   us' :\/: them' <- return $ findUncommon us them@@ -399,22 +271,24 @@    let avoided = mapFL info compl'   ps :> _ <- return $ partitionFL (not . (`elem` avoided) . info) them'-  when (Verbose `elem` opts) $-       do case us' of-            (x@(_:>:_)) -> putDocLn $ text "We have the following new (to them) patches:"-                                                             $$ vcat (mapFL description x)-            _ -> return ()-          unless (nullFL ps) $ putDocLn $ text "They have the following patches to pull:"-                                                             $$ vcat (mapFL description ps)+  putVerbose opts $+    case us' of+      (x@(_ :>: _)) ->+        text "We have the following new (to them) patches:" $$+        vcat (mapFL description x)+      _ -> mempty+  unless (nullFL ps) $ putVerbose opts $+      text "They have the following patches to pull:" $$+      vcat (mapFL description ps)   (hadConflicts, Sealed psFiltered)-    <- if SkipConflicts `elem` opts+    <- if O.conflictsYes ? opts == Nothing         then filterOutConflicts (reverseFL us') repository ps         else return (False, Sealed ps)-  when hadConflicts $ putStrLn "Skipping some patches which would cause conflicts."-  when  (nullFL psFiltered) $ do putInfo opts $ text "No remote patches to pull in!"-                                 setEnvDarcsPatches psFiltered-                                 when (reorder opts /= O.Reorder) exitSuccess-  let direction = if doReverse opts then FirstReversed else First+  when hadConflicts $ putInfo opts $ text "Skipping some patches which would cause conflicts."+  when (nullFL psFiltered) $ do putInfo opts $ text "No remote patches to pull in!"+                                setEnvDarcsPatches psFiltered+                                when (reorder ? opts /= O.Reorder) exitSuccess+  let direction = if changesReverse ? opts then FirstReversed else First       context = selectionContext direction jobname (pullPatchSelOpts opts) Nothing Nothing   (to_be_pulled :> _) <- runSelection psFiltered context   return (seal common, seal $ us' :\/: to_be_pulled)@@ -464,26 +338,25 @@ the second patchset(s) to be complemented against Rc. -} -readRepos :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+readRepos :: (IsRepoType rt, RepoPatch p)           => Repository rt p wR wU wT -> [DarcsFlag] -> [String]           -> IO (SealedPatchSet rt p Origin,SealedPatchSet rt p Origin) readRepos _ _ [] = impossible readRepos to_repo opts us =-    do rs <- mapM (\u -> do r <- identifyRepositoryFor to_repo (useCache opts) u+    do rs <- mapM (\u -> do r <- identifyRepositoryFor to_repo (useCache ? opts) u                             ps <- readRepo r                             return $ seal ps) us-       return $ if Intersection `elem` opts-                then (newsetIntersection rs, seal (PatchSet NilRL NilRL))-                else if Complement `elem` opts-                     then (head rs, newsetUnion $ tail rs)-                     else (newsetUnion rs, seal (PatchSet NilRL NilRL))+       return $ case parseFlags O.repoCombinator opts of+                  O.Intersection -> (patchSetIntersection rs, seal (PatchSet NilRL NilRL))+                  O.Complement -> (head rs, patchSetUnion $ tail rs)+                  O.Union -> (patchSetUnion rs, seal (PatchSet NilRL NilRL))  pullPatchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions pullPatchSelOpts flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { S.verbosity = verbosity ? flags     , S.matchFlags = parseFlags O.matchSeveral flags     , S.interactive = isInteractive True flags-    , S.selectDeps = selectDeps flags-    , S.summary = hasSummary O.NoSummary flags-    , S.withContext = isUnified flags+    , S.selectDeps = selectDeps ? flags+    , S.summary = O.summary ? flags+    , S.withContext = withContext ? flags     }
src/Darcs/UI/Commands/Push.hs view
@@ -15,15 +15,13 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, TypeOperators #-}+{-# LANGUAGE TypeOperators #-}  module Darcs.UI.Commands.Push ( push ) where  import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) )- import System.Exit ( exitWith, ExitCode( ExitSuccess, ExitFailure ), exitSuccess ) import Control.Monad ( when, unless ) import Data.Maybe ( isJust )@@ -32,25 +30,26 @@     , putVerbose     , putInfo     , abortRun-    , printDryRunMessageAndExit     , setEnvDarcsPatches     , defaultRepo     , amInHashedRepository     )+import Darcs.UI.Commands.Util ( printDryRunMessageAndExit, checkUnrelatedRepos )+import Darcs.UI.Completion ( prefArgs ) import Darcs.UI.Flags     ( DarcsFlag-    , isInteractive, verbosity, isUnified, hasSummary-    , hasXmlOutput, selectDeps, applyAs, remoteDarcs-    , doReverse, dryRun, useCache, remoteRepos, setDefault, fixUrl )+    , isInteractive, verbosity, withContext+    , xmlOutput, selectDeps, applyAs, remoteDarcs+    , changesReverse, dryRun, useCache, remoteRepos, setDefault, fixUrl ) import Darcs.UI.Options-    ( DarcsOption, (^), odesc, ocheck, onormalise-    , defaultFlags, parseFlags )+    ( (^), odesc, ocheck, onormalise+    , defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Flags ( DryRun (..) ) import qualified Darcs.Repository.Flags as R ( remoteDarcs ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, hopefully ) import Darcs.Repository ( Repository, withRepository, RepoJob(..), identifyRepositoryFor,-                          readRepo, checkUnrelatedRepos )+                          readRepo ) import Darcs.Patch ( IsRepoType, RepoPatch, description ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.Witnesses.Ordered@@ -59,6 +58,7 @@ import Darcs.Repository.Prefs ( addRepoSource, getPreflist ) import Darcs.UI.External ( signString, darcsProgram                          , pipeDoc, pipeDocSSH )+import Darcs.Util.Exception ( die ) import Darcs.Util.URL ( isHttpUrl, isValidLocalPath                       , isSshUrl, splitSshUrl, SshFilePath(..) ) import Darcs.Util.Path ( AbsolutePath )@@ -70,15 +70,14 @@ import qualified Darcs.UI.SelectChanges as S ( PatchSelectionOptions (..) ) import Darcs.Patch.Depends ( findCommonWithThem, countUsThem ) import Darcs.Patch.Bundle ( makeBundleN )-import Darcs.Patch.Patchy( ShowPatch )+import Darcs.Patch.Show( ShowPatch ) import Darcs.Patch.Set ( PatchSet, Origin )-import Darcs.Util.Printer ( Doc, vcat, empty, text, ($$), RenderMode(..) )+import Darcs.Util.Printer ( Doc, vcat, empty, text, ($$) ) import Darcs.UI.Email ( makeEmail ) import Darcs.Util.English (englishNum, Noun(..)) import Darcs.Util.Workaround ( getCurrentDirectory ) import Darcs.Util.Text ( quote ) import Darcs.Util.Tree( Tree )-#include "impossible.h"   pushDescription :: String@@ -103,78 +102,17 @@  , "you should try again with the `--no-compress` option."  ] -pushBasicOpts :: DarcsOption a-                 ([O.MatchFlag]-                  -> O.SelectDeps-                  -> Maybe Bool-                  -> O.Sign-                  -> O.DryRun-                  -> O.XmlOutput-                  -> Maybe O.Summary-                  -> Maybe String-                  -> Maybe Bool-                  -> Bool-                  -> a)-pushBasicOpts-    = O.matchSeveral-    ^ O.selectDeps-    ^ O.interactive-    ^ O.sign-    ^ O.dryRunXml-    ^ O.summary-    ^ O.workingRepoDir-    ^ O.setDefault-    ^ O.allowUnrelatedRepos--pushAdvancedOpts :: DarcsOption a-                    (Maybe String -> O.RemoteRepos -> Bool -> O.Compression -> O.NetworkOptions -> a)-pushAdvancedOpts-    = O.applyAs-    ^ O.remoteRepos-    ^ O.changesReverse-    ^ O.compress-    ^ O.network--pushOpts :: DarcsOption a-            ([O.MatchFlag]-             -> O.SelectDeps-             -> Maybe Bool-             -> O.Sign-             -> DryRun-             -> O.XmlOutput-             -> Maybe O.Summary-             -> Maybe String-             -> Maybe Bool-             -> Bool-             -> Maybe O.StdCmdAction-             -> Bool-             -> Bool-             -> O.Verbosity-             -> Bool-             -> Maybe String-             -> O.RemoteRepos-             -> Bool-             -> O.Compression-             -> O.NetworkOptions-             -> O.UseCache-             -> Maybe String-             -> Bool-             -> Maybe String-             -> Bool-             -> a)-pushOpts = pushBasicOpts `withStdOpts` pushAdvancedOpts- push :: DarcsCommand [DarcsFlag] push = DarcsCommand     { commandProgramName = "darcs"     , commandName = "push"     , commandHelp = pushHelp     , commandDescription = pushDescription-    , commandExtraArgs = 1+    , commandExtraArgs = -1     , commandExtraArgHelp = ["[REPOSITORY]"]     , commandCommand = pushCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = getPreflist "repos"+    , commandCompleteArgs = prefArgs "repos"     , commandArgdefaults = defaultRepo     , commandAdvancedOptions = odesc pushAdvancedOpts     , commandBasicOptions = odesc pushBasicOpts@@ -182,43 +120,61 @@     , commandCheckOptions = ocheck pushOpts     , commandParseOptions = onormalise pushOpts     }+  where+    pushBasicOpts+      = O.matchSeveral+      ^ O.selectDeps+      ^ O.interactive+      ^ O.sign+      ^ O.dryRunXml+      ^ O.summary+      ^ O.repoDir+      ^ O.setDefault+      ^ O.allowUnrelatedRepos+    pushAdvancedOpts+      = O.applyAs+      ^ O.remoteRepos+      ^ O.changesReverse+      ^ O.compress+      ^ O.network+    pushOpts = pushBasicOpts `withStdOpts` pushAdvancedOpts  pushCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-pushCmd _ _ [""] = impossible-pushCmd (_,o) opts [unfixedrepodir] =- do- repodir <- fixUrl o unfixedrepodir- -- Test to make sure we aren't trying to push to the current repo- here <- getCurrentDirectory- checkOptionsSanity opts repodir- when (repodir == here) $-       fail "Cannot push from repository to itself."-       -- absolute '.' also taken into account by fix_filepath- bundle <- withRepository (useCache opts) $ RepoJob $-                          prepareBundle opts repodir- sbundle <- signString (parseFlags O.sign opts) bundle- let body = if isValidLocalPath repodir-            then sbundle-            else makeEmail repodir [] Nothing Nothing sbundle Nothing- rval <- remoteApply opts repodir body- case rval of ExitFailure ec -> do putStrLn "Apply failed!"-                                   exitWith (ExitFailure ec)-              ExitSuccess -> putInfo opts $ text "Push successful."-pushCmd _ _ _ = impossible+pushCmd (_, o) opts [unfixedrepodir] = do+  repodir <- fixUrl o unfixedrepodir+  here <- getCurrentDirectory+  checkOptionsSanity opts repodir+  -- make sure we aren't trying to push to the current repo+  when (repodir == here) $ die "Cannot push from repository to itself."+  bundle <-+    withRepository (useCache ? opts) $ RepoJob $ prepareBundle opts repodir+  sbundle <- signString (parseFlags O.sign opts) bundle+  let body =+        if isValidLocalPath repodir+          then sbundle+          else makeEmail repodir [] Nothing Nothing sbundle Nothing+  rval <- remoteApply opts repodir body+  case rval of+    ExitFailure ec -> do+      putStrLn "Apply failed!"+      exitWith (ExitFailure ec)+    ExitSuccess -> putInfo opts $ text "Push successful."+pushCmd _ _ [] = die "No default repository to push to, please specify one."+pushCmd _ _ _ = die "Cannot push to more than one repo."  prepareBundle :: forall rt p wR wU wT. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)               => [DarcsFlag] -> String -> Repository rt p wR wU wT -> IO Doc prepareBundle opts repodir repository = do   old_default <- getPreflist "defaultrepo"   when (old_default == [repodir]) $-       let pushing = if dryRun opts == YesDryRun then "Would push" else "Pushing"+       let pushing = if dryRun ? opts == YesDryRun then "Would push" else "Pushing"        in  putInfo opts $ text $ pushing++" to "++quote repodir++"..."-  them <- identifyRepositoryFor repository (useCache opts) repodir >>= readRepo-  addRepoSource repodir (dryRun opts) (remoteRepos opts) (setDefault False opts)+  them <- identifyRepositoryFor repository (useCache ? opts) repodir >>= readRepo+  addRepoSource repodir (dryRun ? opts) (remoteRepos ? opts) (setDefault False opts)   us <- readRepo repository   common :> us' <- return $ findCommonWithThem us them   prePushChatter opts us (reverseFL us') them-  let direction = if doReverse opts then FirstReversed else First+  let direction = if changesReverse ? opts then FirstReversed else First       context = selectionContext direction "push" (pushPatchSelOpts opts) Nothing Nothing   runSelection us' context                    >>= bundlePatches opts common@@ -246,10 +202,10 @@     do       setEnvDarcsPatches to_be_pushed       printDryRunMessageAndExit "push"-        (verbosity opts)-        (hasSummary O.NoSummary opts)-        (dryRun opts)-        (hasXmlOutput opts)+        (verbosity ? opts)+        (O.summary ? opts)+        (dryRun ? opts)+        (xmlOutput ? opts)         (isInteractive True opts)         to_be_pushed       when (nullFL to_be_pushed) $ do@@ -261,7 +217,7 @@ checkOptionsSanity :: [DarcsFlag] -> String -> IO () checkOptionsSanity opts repodir =   if isHttpUrl repodir then do-       when (isJust $ applyAs opts) $+       when (isJust $ applyAs ? opts) $            abortRun opts $ text "Cannot --apply-as when pushing to URLs"        let lprot = takeWhile (/= ':') repodir            msg = text ("Pushing to "++lprot++" URLs is not supported.")@@ -272,17 +228,17 @@  pushPatchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions pushPatchSelOpts flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { S.verbosity = verbosity ? flags     , S.matchFlags = parseFlags O.matchSeveral flags     , S.interactive = isInteractive True flags-    , S.selectDeps = selectDeps flags-    , S.summary = hasSummary O.NoSummary flags-    , S.withContext = isUnified flags+    , S.selectDeps = selectDeps ? flags+    , S.summary = O.summary ? flags+    , S.withContext = withContext ? flags     }  remoteApply :: [DarcsFlag] -> String -> Doc -> IO ExitCode remoteApply opts repodir bundle-    = case applyAs opts of+    = case applyAs ? opts of         Nothing             | isSshUrl repodir -> applyViaSsh opts (splitSshUrl repodir) bundle             | otherwise -> applyViaLocal opts repodir bundle@@ -293,22 +249,22 @@ applyViaSudo :: String -> String -> Doc -> IO ExitCode applyViaSudo user repo bundle =     darcsProgram >>= \darcs ->-    pipeDoc Standard "sudo" ["-u",user,darcs,"apply","--all","--repodir",repo] bundle+    pipeDoc "sudo" ["-u",user,darcs,"apply","--all","--repodir",repo] bundle  applyViaLocal :: [DarcsFlag] -> String -> Doc -> IO ExitCode applyViaLocal opts repo bundle =     darcsProgram >>= \darcs ->-    pipeDoc Standard darcs ("apply":"--all":"--repodir":repo:applyopts opts) bundle+    pipeDoc darcs ("apply":"--all":"--repodir":repo:applyopts opts) bundle  applyViaSsh :: [DarcsFlag] -> SshFilePath -> Doc -> IO ExitCode applyViaSsh opts repo =-    pipeDocSSH (parseFlags O.compress opts) Standard repo+    pipeDocSSH (parseFlags O.compress opts) repo            [R.remoteDarcs (remoteDarcs opts) ++" apply --all "++unwords (applyopts opts)++                      " --repodir '"++sshRepo repo++"'"]  applyViaSshAndSudo :: [DarcsFlag] -> SshFilePath -> String -> Doc -> IO ExitCode applyViaSshAndSudo opts repo username =-    pipeDocSSH (parseFlags O.compress opts) Standard repo+    pipeDocSSH (parseFlags O.compress opts) repo            ["sudo -u "++username++" "++R.remoteDarcs (remoteDarcs opts)++                      " apply --all --repodir '"++sshRepo repo++"'"] 
src/Darcs/UI/Commands/Rebase.hs view
@@ -2,7 +2,7 @@ -- --  BSD3 -{-# LANGUAGE CPP, TypeOperators #-}+{-# LANGUAGE TypeOperators #-}  module Darcs.UI.Commands.Rebase ( rebase ) where @@ -16,34 +16,29 @@     , defaultRepo, nodefaults     , putInfo, putVerbose     , setEnvDarcsPatches-    , printDryRunMessageAndExit     , amInHashedRepository     )+import Darcs.UI.Commands.Util ( printDryRunMessageAndExit ) 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.Completion ( fileArgs, prefArgs, noArgs ) import Darcs.UI.Flags     ( DarcsFlag-      ( AllowConflicts-      , NoAllowConflicts-      , MarkConflicts-      , SkipConflicts-      , SetScriptsExecutable)     , externalMerge, allowConflicts-    , compression, diffingOpts-    , dryRun, reorder, verbosity+    , compress, diffingOpts+    , dryRun, reorder, verbosity, verbose     , useCache, wantGuiPause-    , umask, toMatchFlags, doReverse-    , DarcsFlag(XMLOutput)-    , showChangesOnlyToFiles-    , diffAlgorithm, maxCount, hasSummary, isInteractive-    , selectDeps, hasXmlOutput+    , umask, matchAny, changesReverse+    , onlyToFiles+    , diffAlgorithm, maxCount, isInteractive+    , selectDeps, xmlOutput, hasXmlOutput     ) import Darcs.UI.Options-    ( DarcsOption, (^), oid, odesc, ocheck, onormalise-    , defaultFlags, parseFlags+    ( (^), oid, odesc, ocheck, onormalise+    , defaultFlags, parseFlags, (?)     ) import qualified Darcs.UI.Options.All as O import Darcs.UI.PatchHeader ( HijackT, HijackOptions(..), runHijackT@@ -58,18 +53,15 @@     , 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.Merge ( tentativelyMergePatches, announceMergeConflicts ) 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.Info ( displayPatchInfo ) import Darcs.Patch.Match ( firstMatch, secondMatch, splitSecondFL ) import Darcs.Patch.Named ( Named, fmapFL_Named, patchcontents, patch2patchinfo ) import Darcs.Patch.Named.Wrapped ( mkRebase, toRebasing, fromRebasing )@@ -116,9 +108,9 @@ import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP ) import Darcs.Util.English ( englishNum, Noun(Noun) ) import Darcs.Util.Printer-    ( vcat, text, ($$)+    ( vcat, text, ($$), redText     , putDocLnWith, simplePrinters-    , renderString, RenderMode(..)+    , renderString     ) import Darcs.Util.Printer.Color ( fancyPrinters ) import Darcs.Util.Progress ( debugMessage )@@ -131,8 +123,6 @@ import Control.Monad.Trans ( liftIO ) import System.Exit ( exitSuccess ) -#include "impossible.h"- rebaseDescription :: String rebaseDescription = "Edit several patches at once." @@ -160,46 +150,6 @@         ]     } -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"@@ -210,7 +160,7 @@     , commandExtraArgs = 0     , commandExtraArgHelp = []     , commandCommand = suspendCmd-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc suspendAdvancedOpts     , commandBasicOptions = odesc suspendBasicOpts@@ -218,11 +168,22 @@     , commandCheckOptions = ocheck suspendOpts     , commandParseOptions = onormalise suspendOpts     }+  where+    suspendBasicOpts+      = O.matchSeveralOrLast+      ^ O.selectDeps+      ^ O.interactive+      ^ O.summary+      ^ O.diffAlgorithm+    suspendAdvancedOpts+      = O.changesReverse+      ^ O.useIndex+    suspendOpts = suspendBasicOpts `withStdOpts` suspendAdvancedOpts  suspendCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () suspendCmd _ opts _args =-    withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $-    StartRebaseJob (RebaseJobFlags (compression opts) (verbosity opts) YesUpdateWorking) $+    withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $+    StartRebaseJob (RebaseJobFlags (compress ? opts) (verbosity ? opts) YesUpdateWorking) $     \repository -> do     allpatches <- readRepo repository     (rOld, suspended, allpatches_tail) <- return $ takeHeadRebase allpatches@@ -230,7 +191,7 @@         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+    let direction = if changesReverse ? opts then Last else LastReversed         patches_context = selectionContext direction "suspend" (patchSelOpts True opts) Nothing Nothing     (_ :> psToSuspend) <-         runSelection@@ -244,12 +205,12 @@         $ mapM_ (getAuthor "suspend" False Nothing)         $ mapFL info psToSuspend     repository' <- doSuspend opts repository suspended rOld psToSuspend-    finalizeRepositoryChanges repository' YesUpdateWorking (compression opts)+    finalizeRepositoryChanges repository' YesUpdateWorking (compress ? opts)     return ()  doSuspend     :: forall p wR wU wT wX-     . (RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+     . (RepoPatch p, ApplyState p ~ Tree)     => [DarcsFlag]     -> Repository ('RepoType 'IsRebase) p wR wU wT     -> Suspended p wT wT@@ -257,7 +218,9 @@     -> 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+    pend <- unrecordedChanges (diffingOpts opts)+      O.NoLookForMoves O.NoLookForReplaces+      repository Nothing     FlippedSeal psAfterPending <-         let effectPsToSuspend = effect psToSuspend in         case commute (effectPsToSuspend :> pend) of@@ -270,67 +233,30 @@                     case (doPartition invPsEffect pend, doPartition pend invPsEffect) of                         (_ :> invSuspendedConflicts, _ :> pendConflicts) ->                             let suspendedConflicts = invert invSuspendedConflicts in-                            text "these changes in the suspended patches:" $$+                            redText "These changes in the suspended patches:" $$                             showNicely suspendedConflicts $$-                            text "conflict with these local changes:" $$+                            redText "...conflict with these local changes:" $$                             showNicely pendConflicts-                fail $ "Can't suspend selected patches without reverting some unrecorded change. Use --verbose to see the details."+                fail $ "Can't suspend selected patches without reverting some unrecorded change."+                    ++ if (verbose opts) then "" else " 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))+    -- remove the old rebase patch and the patches to suspend+    repository' <- tentativelyRemovePatches repository (compress ? 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)+    -- add the new rebase patch+    repository'' <- tentativelyAddPatch repository' (compress ? opts) (unVerbose (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+-- Certain repository functions will display the rebase patch in verbose mode+-- so we use this function to suppress it when passing the verbosity.+unVerbose :: O.Verbosity -> O.Verbosity+unVerbose O.Verbose = O.NormalVerbosity+unVerbose x = x  unsuspend :: DarcsCommand [DarcsFlag] unsuspend = DarcsCommand@@ -342,7 +268,7 @@     , commandExtraArgs = 0     , commandExtraArgHelp = []     , commandCommand = unsuspendCmd False-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc unsuspendAdvancedOpts     , commandBasicOptions = odesc unsuspendBasicOpts@@ -350,34 +276,18 @@     , 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+  where+    unsuspendBasicOpts+      = O.conflictsYes+      ^ O.matchSeveralOrFirst+      ^ O.interactive+      ^ O.summary+      ^ O.externalMerge+      ^ O.keepDate+      ^ O.author+      ^ O.diffAlgorithm+    unsuspendAdvancedOpts = O.useIndex+    unsuspendOpts = unsuspendBasicOpts `withStdOpts` unsuspendAdvancedOpts  reify :: DarcsCommand [DarcsFlag] reify = DarcsCommand@@ -389,7 +299,7 @@     , commandExtraArgs = 0     , commandExtraArgHelp = []     , commandCommand = unsuspendCmd True-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = odesc reifyBasicOpts@@ -397,14 +307,24 @@     , commandCheckOptions = ocheck reifyOpts     , commandParseOptions = onormalise reifyOpts     }+  where+    reifyBasicOpts+      = O.matchSeveralOrFirst+      ^ O.interactive+      ^ O.keepDate+      ^ O.author+      ^ O.diffAlgorithm+    reifyOpts = reifyBasicOpts `withStdOpts` oid  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) $+    withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RebaseJob (RebaseJobFlags (compress ? opts) (verbosity ? opts) YesUpdateWorking) $     \(repository :: Repository ('RepoType 'IsRebase) p wR wU wR) -> (do     patches <- readRepo repository-    pend <- unrecordedChanges (diffingOpts opts) repository Nothing+    pend <- unrecordedChanges (diffingOpts opts)+      O.NoLookForMoves O.NoLookForReplaces+      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"@@ -413,7 +333,7 @@      let selects = toRebaseSelect ps -    let matchFlags = toMatchFlags opts+    let matchFlags = matchAny ? opts     inRange :> outOfRange <-         return $             if secondMatch matchFlags then@@ -422,9 +342,9 @@      offer :> dontoffer <-         return $-            if SkipConflicts `elem` opts-            then partitionUnconflicted inRange-            else inRange :> NilRL+            case O.conflictsYes ? opts of+              Nothing -> partitionUnconflicted inRange -- skip conflicts+              Just _ -> inRange :> NilRL      let warnSkip :: RL q wX wY -> IO ()         warnSkip NilRL = return ()@@ -440,7 +360,7 @@     (ps_to_unsuspend :: FL (WDDNamed p) wR wZ) :> chosen_fixups            <- (if reifyFixups then reifyRebaseSelect else return . extractRebaseSelect) chosen -    let da = diffAlgorithm opts+    let da = diffAlgorithm ? opts         ps_to_keep = simplifyPushes da chosen_fixups .                      fromRebaseSelect $                      keep +>+ reverseRL dontoffer +>+ outOfRange@@ -450,30 +370,29 @@                                          $ 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+    have_conflicts <- announceMergeConflicts "unsuspend"+        (allowConflicts opts) (externalMerge ? opts) standard_resolved_p     Sealed (resolved_p  :: FL (PrimOf p) wA wB) <--          case (externalMerge opts, have_conflicts) of-          (NoExternalMerge,_) -> return $ if AllowConflicts `elem` opts -- i.e. don't mark them-                                           then seal NilFL-                                           else seal standard_resolved_p-          (_,False) -> return $ seal standard_resolved_p-          (YesExternalMerge _, True) -> error "external resolution for unsuspend not implemented yet"+        case (externalMerge ? opts, have_conflicts) of+            (NoExternalMerge, _) ->+                case O.conflictsYes ? opts of+                    Just O.YesAllowConflicts -> return $ seal NilFL -- i.e. don't mark them+                    _ -> return $ 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)+    repository' <- tentativelyRemovePatches repository (compress ? opts) YesUpdateWorking (rOld :>: NilFL)     -- TODO should catch logfiles (fst value from updatePatchHeader) and clean them up as in AmendRecord     tentativelyAddToPending repository' YesUpdateWorking effect_to_apply     -- we can just let hijack attempts through here because we already asked about them on suspend time     (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) ->+    repository''' <- tentativelyAddPatch repository'' (compress ? opts) (verbosity ? opts) YesUpdateWorking (n2pia rNew)+    finalizeRepositoryChanges repository''' YesUpdateWorking (compress ? opts)+    _ <- applyToWorking repository''' (verbosity ? opts) effect_to_apply `catch` \(e :: IOException) ->         fail ("couldn't apply patch in working dir.\n" ++ show e)     return ()    ) :: IO ()@@ -493,8 +412,8 @@                                  ++ englishNum (length deps) (Noun "dependency") ":\n\n"                       let printIndented n =                               mapM_ (putStrLn . (replicate n ' '++)) . lines .-                              renderString Encode . showPatchInfo-                      putStrLn . renderString Encode . showPatchInfo .+                              renderString . displayPatchInfo+                      putStrLn . renderString . displayPatchInfo .                               patch2patchinfo $ wddPatch p                       putStr " depended on:\n"                       mapM_ (printIndented 2) deps@@ -504,14 +423,14 @@               p' <- snd <$> updatePatchHeader "unsuspend"                       NoAskAboutDeps                       (patchSelOpts True opts)-                      (diffAlgorithm 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'+              repo' <- liftIO $ tentativelyAddPatch repo (compress ? opts) (verbosity ? opts) YesUpdateWorking p'               -- create a rename that undoes the change we just made, so the contexts match up               let rename :: RebaseName p wU wU                   rename = Rename (info p') (patch2patchinfo (wddPatch p))@@ -524,26 +443,6 @@               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"@@ -554,7 +453,7 @@     , commandExtraArgs = 0     , commandExtraArgHelp = []     , commandCommand = injectCmd-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = odesc injectBasicOpts@@ -562,11 +461,14 @@     , commandCheckOptions = ocheck injectOpts     , commandParseOptions = onormalise injectOpts     }+  where+    injectBasicOpts = O.keepDate ^ O.author ^ O.diffAlgorithm+    injectOpts = injectBasicOpts `withStdOpts` oid  injectCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () injectCmd _ opts _args =-    withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $-    RebaseJob (RebaseJobFlags (compression opts) (verbosity opts) YesUpdateWorking) $+    withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RebaseJob (RebaseJobFlags (compress ? opts) (verbosity ? opts) YesUpdateWorking) $     \(repository :: Repository ('RepoType 'IsRebase) p wR wU wR) -> do     patches <- readRepo repository @@ -588,7 +490,7 @@      name_fixups :> prim_fixups <- return $ flToNamesPrims fixups -    let changes_context = selectionContextPrim Last "inject" (patchSelOpts True opts) (Just (primSplitter (diffAlgorithm opts))) Nothing Nothing+    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@@ -596,36 +498,18 @@         exitSuccess      -- Don't bother to update patch header since unsuspend will do that later-    let da = diffAlgorithm opts+    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)+    repository' <- tentativelyRemovePatches repository (compress ? opts) YesUpdateWorking (rOld :>: NilFL)+    repository'' <- tentativelyAddPatch repository' (compress ? opts) (verbosity ? opts) YesUpdateWorking (n2pia rNew)+    finalizeRepositoryChanges repository'' YesUpdateWorking (compress ? 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"@@ -636,7 +520,7 @@     , commandExtraArgs = 0     , commandExtraArgHelp = []     , commandCommand = obliterateCmd-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = odesc obliterateBasicOpts@@ -644,11 +528,14 @@     , commandCheckOptions = ocheck obliterateOpts     , commandParseOptions = onormalise obliterateOpts     }+  where+    obliterateBasicOpts = O.diffAlgorithm+    obliterateOpts = obliterateBasicOpts `withStdOpts` oid  obliterateCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () obliterateCmd _ opts _args =-    withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $-    RebaseJob (RebaseJobFlags (compression opts) (verbosity opts) YesUpdateWorking) $+    withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $+    RebaseJob (RebaseJobFlags (compress ? opts) (verbosity ? opts) YesUpdateWorking) $     \(repository :: Repository ('RepoType 'IsRebase) p wR wU wR) -> (do     patches <- readRepo repository @@ -662,7 +549,7 @@     when (nullFL chosen) $ do putStrLn "No patches selected!"                               exitSuccess -    let da = diffAlgorithm opts+    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@@ -675,9 +562,9 @@     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)+    repository' <- tentativelyRemovePatches repository (compress ? opts) YesUpdateWorking (rOld :>: NilFL)+    repository'' <- tentativelyAddPatch repository' (compress ? opts) (verbosity ? opts) YesUpdateWorking (n2pia rNew)+    finalizeRepositoryChanges repository'' YesUpdateWorking (compress ? opts)     return ()    ) :: IO () @@ -690,96 +577,6 @@ 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"@@ -790,7 +587,7 @@     , commandExtraArgHelp = ["[REPOSITORY]..."]     , commandCommand = pullCmd RebasePatchApplier     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = getPreflist "repos"+    , commandCompleteArgs = prefArgs "repos"     , commandArgdefaults = defaultRepo     , commandAdvancedOptions = odesc pullAdvancedOpts     , commandBasicOptions = odesc pullBasicOpts@@ -798,6 +595,32 @@     , commandCheckOptions = ocheck pullOpts     , commandParseOptions = onormalise pullOpts     }+  where+    pullBasicOpts+      = O.matchSeveral+      ^ O.reorder+      ^ O.interactive+      ^ O.conflictsYes+      ^ O.externalMerge+      ^ O.runTest+      ^ O.dryRunXml+      ^ O.summary+      ^ O.selectDeps+      ^ O.setDefault+      ^ O.repoDir+      ^ O.allowUnrelatedRepos+      ^ O.diffAlgorithm+    pullAdvancedOpts+      = O.repoCombinator+      ^ O.compress+      ^ O.useIndex+      ^ O.remoteRepos+      ^ O.setScriptsExecutable+      ^ O.umask+      ^ O.restrictPaths+      ^ O.changesReverse+      ^ O.network+    pullOpts = pullBasicOpts `withStdOpts` pullAdvancedOpts  applyDescription :: String applyDescription = "Apply a patch bundle, suspending any local patches that conflict."@@ -819,7 +642,7 @@     , commandExtraArgHelp = ["<PATCHFILE>"]     , commandCommand = applyCmd RebasePatchApplier     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = listFiles False+    , commandCompleteArgs = fileArgs     , commandArgdefaults = const stdindefault     , commandAdvancedOptions = odesc applyAdvancedOpts     , commandBasicOptions = odesc applyBasicOpts@@ -827,85 +650,28 @@     , 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+  where+    applyBasicOpts+      = O.verify+      ^ O.reorder+      ^ O.interactive+      ^ O.dryRunXml+      ^ O.matchSeveral+      ^ O.repoDir+      ^ O.diffAlgorithm+    applyAdvancedOpts+      = O.reply+      ^ O.ccApply+      ^ O.happyForwarding+      ^ O.sendmail+      ^ O.useIndex+      ^ O.compress+      ^ O.setScriptsExecutable+      ^ O.umask+      ^ O.restrictPaths+      ^ O.changesReverse+      ^ O.pauseForGui+    applyOpts = applyBasicOpts `withStdOpts` applyAdvancedOpts  data RebasePatchApplier = RebasePatchApplier @@ -914,14 +680,13 @@      repoJob RebasePatchApplier opts f =         StartRebaseJob-          (RebaseJobFlags (compression opts) (verbosity opts) YesUpdateWorking)+          (RebaseJobFlags (compress ? 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-       )+     . ( RepoPatch p, ApplyState p ~ Tree )     => String     -> [DarcsFlag]     -> String@@ -931,10 +696,10 @@     -> IO () applyPatchesForRebaseCmd cmdName opts _from_whom repository us' to_be_applied = do     printDryRunMessageAndExit cmdName-        (verbosity opts)-        (hasSummary O.NoSummary opts)-        (dryRun opts)-        (hasXmlOutput opts)+        (verbosity ? opts)+        (O.summary ? opts)+        (dryRun ? opts)+        (xmlOutput ? opts)         (isInteractive True opts)         to_be_applied     setEnvDarcsPatches to_be_applied@@ -962,27 +727,30 @@      (rOld, suspended, _) <- return $ takeHeadRebaseFL us'     repository' <- doSuspend opts repository suspended rOld usToSuspend+    -- the new rebase patch containing the suspended patches is now in the repo+    -- and the suspended patches have been removed      -- TODO This is a nasty hack, caused by the fact that readUnrecorded     -- claims to read the tentative state but actual reads the committed state     -- as a result we have to commit here so that tentativelyMergePatches does     -- the right thing.-    finalizeRepositoryChanges repository' YesUpdateWorking (compression opts)+    finalizeRepositoryChanges repository' YesUpdateWorking (compress ? opts)         >> revertRepositoryChanges repository' YesUpdateWorking      Sealed pw <-         tentativelyMergePatches             repository' cmdName             (allowConflicts opts) YesUpdateWorking-            (externalMerge opts)-            (wantGuiPause opts) (compression opts) (verbosity opts)-            (reorder opts) (diffingOpts opts)+            (externalMerge ? opts)+            (wantGuiPause opts) (compress ? 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+    finalizeRepositoryChanges repository' YesUpdateWorking (compress ? opts)+    _ <- revertable $ applyToWorking repository' (verbosity ? opts) pw+    when (O.setScriptsExecutable ? opts == O.YesSetScriptsExecutable) $+      setScriptsExecutablePatches pw     putInfo opts $ text $ "Finished " ++ cmdName ++ "ing."  -- TODO I doubt this is right, e.g. withContext should be inherited@@ -1003,11 +771,11 @@  patchSelOpts :: Bool -> [DarcsFlag] -> S.PatchSelectionOptions patchSelOpts defInteractive flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { 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.selectDeps = selectDeps ? flags+    , S.summary = O.summary ? flags     , S.withContext = O.NoContext     } @@ -1021,7 +789,7 @@     , commandExtraArgs = 0     , commandExtraArgHelp = []     , commandCommand = logCmd-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc logAdvancedOpts     , commandBasicOptions = odesc logBasicOpts@@ -1029,39 +797,15 @@     , commandCheckOptions = ocheck logOpts     , commandParseOptions = onormalise logOpts     }--logBasicOpts :: DarcsOption a-                (Maybe O.Summary-                 -> Maybe Bool-                 -> a)-logBasicOpts-    = O.summary-    ^ O.interactive -- False--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+  where+    logBasicOpts = O.summary ^ O.interactive -- False+    logAdvancedOpts = oid+    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+    withRepository (useCache ? opts) $+    RebaseJob (RebaseJobFlags (compress ? opts) (verbosity ? opts) YesUpdateWorking) $ \repository -> do         patches <- readRepo repository         (_, Items ps, _) <- return $ takeHeadRebase patches         let psToShow = toRebaseChanges ps@@ -1069,14 +813,14 @@             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+                let printers = if hasXmlOutput opts then simplePrinters else fancyPrinters                     emptyPatchSet = PatchSet NilRL NilRL                     patchSet = appendPSFL emptyPatchSet psToShow                 logInfo <-                     getLogInfo-                         (maxCount opts)-                         (toMatchFlags opts)-                         (showChangesOnlyToFiles opts)+                         (maxCount ? opts)+                         (matchAny ? opts)+                         (onlyToFiles ? opts)                          Nothing                          (\_ qs -> return qs)                          patchSet
src/Darcs/UI/Commands/Record.hs view
@@ -15,7 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-}  module Darcs.UI.Commands.Record@@ -43,16 +42,13 @@     , tentativelyAddPatch     , finalizeRepositoryChanges     , invalidateIndex-    , unrecordedChangesWithPatches+    , unrecordedChanges     , readRecorded-    , listRegisteredFiles     ) import Darcs.Patch ( IsRepoType, RepoPatch, PrimOf, fromPrims ) import Darcs.Patch.Named.Wrapped ( namepatch, adddeps )-import Darcs.Patch.Witnesses.Sealed import Darcs.Patch.Witnesses.Ordered     ( FL(..), (:>)(..), nullFL )-import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP ) import Darcs.Patch.Info ( PatchInfo ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.Split ( primSplitter )@@ -74,6 +70,7 @@     ) import Darcs.UI.Commands.Util ( announceFiles, filterExistingPaths,                                 testTentativeAndMaybeExit )+import Darcs.UI.Completion ( modifiedFileArgs ) import Darcs.UI.Flags     ( DarcsFlag     , fileHelpAuthor@@ -87,7 +84,6 @@ import Darcs.UI.PatchHeader ( getLog ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Flags ( UpdateWorking (..), DryRun(NoDryRun), ScanKnown(..) )-import Darcs.Repository.State ( getMovesPs, getReplaces ) import Darcs.Util.Exception ( clarifyErrors ) import Darcs.Util.Prompt ( promptYorn ) import Darcs.Util.Progress ( debugMessage )@@ -127,10 +123,10 @@     ^ O.testChanges     ^ O.interactive     ^ O.pipe-    ^ O.askdeps+    ^ O.askDeps     ^ O.askLongComment     ^ O.lookfor-    ^ O.workingRepoDir+    ^ O.repoDir     ^ O.withContext     ^ O.diffAlgorithm @@ -138,37 +134,6 @@                       (O.Logfile -> O.Compression -> O.UseIndex -> O.UMask -> O.SetScriptsExecutable -> O.IncludeBoring -> a) recordAdvancedOpts = O.logfile ^ O.compress ^ O.useIndex ^ O.umask ^ O.setScriptsExecutable ^ O.includeBoring -recordOpts :: DarcsOption a-              (Maybe String-               -> Maybe String-               -> O.TestChanges-               -> Maybe Bool-               -> Bool-               -> Bool-               -> Maybe O.AskLongComment-               -> O.LookFor-               -> Maybe String-               -> O.WithContext-               -> O.DiffAlgorithm-               -> Maybe O.StdCmdAction-               -> Bool-               -> Bool-               -> O.Verbosity-               -> Bool-               -> O.Logfile-               -> O.Compression-               -> O.UseIndex-               -> O.UMask-               -> O.SetScriptsExecutable-               -> O.IncludeBoring-               -> O.UseCache-               -> Maybe String-               -> Bool-               -> Maybe String-               -> Bool-               -> a)-recordOpts = recordBasicOpts `withStdOpts` recordAdvancedOpts- data RecordConfig = RecordConfig     { patchname :: Maybe String     , author :: Maybe String@@ -204,14 +169,16 @@     , commandExtraArgHelp = ["[FILE or DIRECTORY]..."]     , commandCommand = recordCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = listRegisteredFiles+    , commandCompleteArgs = modifiedFileArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc recordAdvancedOpts     , commandBasicOptions = odesc recordBasicOpts     , commandDefaults = defaultFlags recordOpts     , commandCheckOptions = ocheck recordOpts     , commandParseOptions = recordConfig-}+    }+  where+    recordOpts = recordBasicOpts `withStdOpts` recordAdvancedOpts  -- | commit is an alias for record commit :: DarcsCommand RecordConfig@@ -232,7 +199,11 @@         files <- if null args then return Nothing                  else Just . sort <$> fixSubPaths fps args         when (files == Just []) $ fail "No valid arguments were given."-        files' <- traverse (filterExistingPaths repository (verbosity cfg) (useIndex cfg) scan) files+        files' <-+          traverse+            (filterExistingPaths+              repository (verbosity cfg) (useIndex cfg) scan (O.moves (lookfor cfg)))+            files         when (verbosity cfg /= O.Quiet) $             traverse_ (reportNonExisting scan) files'         let files'' = fmap snd files'@@ -241,15 +212,9 @@         return files''       announceFiles (verbosity cfg) existing_files "Recording changes in"       debugMessage "About to get the unrecorded changes."-      Sealed replacePs <- if O.replaces (lookfor cfg) == O.YesLookForReplaces-          then getReplaces (diffingOpts cfg) repository existing_files-          else return (Sealed NilFL)-      movesPs <- if O.moves (lookfor cfg) == O.YesLookForMoves-          then getMovesPs repository existing_files-          else return NilFL-      changes <- unrecordedChangesWithPatches-                   movesPs (unsafeCoerceP replacePs :: FL (PrimOf p) wR wR)-                   (diffingOpts cfg) repository existing_files+      changes <- unrecordedChanges (diffingOpts cfg)+                   (O.moves (lookfor cfg)) (O.replaces (lookfor cfg))+                   repository existing_files       debugMessage "I've got unrecorded changes."       case changes of           NilFL | not (askDeps cfg) -> do@@ -270,7 +235,7 @@         confirmed <- promptYorn $ "You specified " ++ show name ++ " as the patch name. Is that really what you want?"         unless confirmed $ putStrLn "Okay, aborting the record." >> exitFailure -doRecord :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+doRecord :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)          => Repository rt p wR wU wR -> RecordConfig -> Maybe [SubPath] -> FL (PrimOf p) wR wX -> IO () doRecord repository cfg files ps = do     date <- getDate (pipe cfg)@@ -361,7 +326,7 @@  , "record failed and left a `_darcs/patch_description.txt` file."  , ""  , unlines fileHelpAuthor- , "If you want to manually define any extra dependencies for your patch,"+ , "If you want to manually define any explicit dependencies for your patch,"  , "you can use the `--ask-deps` flag. Some dependencies may be automatically"  , "inferred from the patch's content and cannot be removed. A patch with"  , "specific dependencies can be empty."
src/Darcs/UI/Commands/Remove.hs view
@@ -15,25 +15,24 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.UI.Commands.Remove ( remove, rm, unadd ) where  import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) )- import Control.Monad ( when, foldM )-import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults,-                        commandAlias, commandStub,-                        putWarning-                      , amInHashedRepository-                      )-import Darcs.UI.Commands.Add( expandDirs )+import Darcs.UI.Commands+    ( DarcsCommand(..)+    , withStdOpts, nodefaults+    , commandAlias, commandStub+    , putWarning, putInfo+    , amInHashedRepository+    )+import Darcs.UI.Commands.Util ( expandDirs )+import Darcs.UI.Completion ( knownFileArgs ) import Darcs.UI.Flags-    ( DarcsFlag, useCache, dryRun, umask, diffAlgorithm, fixSubPaths, verbosity )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags, parseFlags )+    ( DarcsFlag, useCache, dryRun, umask, diffAlgorithm, fixSubPaths, quiet )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Flags ( UpdateWorking (..) ) import Darcs.Repository@@ -43,7 +42,6 @@     , addToPending     , readRecordedAndPending     , readUnrecorded-    , listRegisteredFiles     ) import Darcs.Repository.Diff( treeDiff ) import Darcs.Patch ( RepoPatch, PrimOf, PrimPatch, adddir, rmdir, addfile, rmfile,@@ -55,8 +53,7 @@ import Darcs.Util.Tree( Tree, TreeItem(..), find, modifyTree, expand, list ) import Darcs.Util.Path( anchorPath, AnchoredPath, fn2fp, SubPath, sp2fn                       , AbsolutePath, floatPath )-import Darcs.Util.Printer ( text )-+import Darcs.Util.Printer ( text, vcat )  removeDescription :: String removeDescription = "Remove files from version control."@@ -72,29 +69,6 @@  "Note that applying a removal patch to a repository (e.g. by pulling\n" ++  "the patch) will ALWAYS affect the working tree of that repository.\n" -removeBasicOpts :: DarcsOption a (Maybe String -> Bool -> a)-removeBasicOpts = O.workingRepoDir ^ O.recursive--removeAdvancedOpts :: DarcsOption a (O.UMask -> a)-removeAdvancedOpts = O.umask--removeOpts :: DarcsOption a-              (Maybe String-               -> Bool-               -> Maybe O.StdCmdAction-               -> Bool-               -> Bool-               -> O.Verbosity-               -> Bool-               -> O.UMask-               -> O.UseCache-               -> Maybe String-               -> Bool-               -> Maybe String-               -> Bool-               -> a)-removeOpts = removeBasicOpts `withStdOpts` removeAdvancedOpts- remove :: DarcsCommand [DarcsFlag] remove = DarcsCommand     { commandProgramName = "darcs"@@ -105,7 +79,7 @@     , commandExtraArgHelp = ["<FILE or DIRECTORY> ..."]     , commandCommand = removeCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = listRegisteredFiles+    , commandCompleteArgs = knownFileArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc removeAdvancedOpts     , commandBasicOptions = odesc removeBasicOpts@@ -113,6 +87,10 @@     , commandCheckOptions = ocheck removeOpts     , commandParseOptions = onormalise removeOpts     }+  where+    removeBasicOpts = O.repoDir ^ O.recursive+    removeAdvancedOpts = O.umask+    removeOpts = removeBasicOpts `withStdOpts` removeAdvancedOpts  removeCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () removeCmd fps opts relargs = do@@ -121,17 +99,17 @@     origfiles <- fixSubPaths fps relargs     when (null origfiles) $         fail "No valid arguments were given."-    withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+    withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $+      RepoJob $ \repository -> do         args <- if parseFlags O.recursive opts                 then reverse `fmap` expandDirs False origfiles                 else return origfiles         Sealed p <- makeRemovePatch opts repository args-        let notQuiet = verbosity opts /= O.Quiet-        when (nullFL p && not (null origfiles) && notQuiet) $+        -- TODO whether command fails depends on verbosity BAD BAD BAD+        when (nullFL p && not (null origfiles) && not (quiet opts)) $             fail "No files were removed."         addToPending repository YesUpdateWorking p-        when notQuiet $-            putStr $ unlines $ ["Will stop tracking:"] ++ listTouchedFiles p+        putInfo opts $ vcat $ map text $ ["Will stop tracking:"] ++ listTouchedFiles p  -- | makeRemovePatch builds a list of patches to remove the given filepaths. --   This function does not recursively process directories. The 'Recursive'@@ -176,7 +154,7 @@               then skipAndWarn "it is not empty"               else return $ Just $ freeGap (rmdir f_fp :>: NilFL)         (Just (File _), Just (File _)) -> do-            Just `fmap` treeDiff (diffAlgorithm opts) ftf unrecorded unrecorded'+            Just `fmap` treeDiff (diffAlgorithm ? opts) ftf unrecorded unrecorded'         (Just (File _), _) ->             return $ Just $ freeGap (addfile f_fp :>: rmfile f_fp :>: NilFL)         (Just (SubTree _), _) ->
src/Darcs/UI/Commands/Repair.hs view
@@ -15,11 +15,8 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -module Darcs.UI.Commands.Repair-    (-      repair-    , check-    ) where+{-# LANGUAGE RecordWildCards #-}+module Darcs.UI.Commands.Repair ( repair, check ) where  import Prelude () import Darcs.Prelude@@ -30,29 +27,39 @@ import System.Directory( renameFile ) import System.FilePath ( (</>) ) -import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, putInfo, commandAlias, amInHashedRepository )-import Darcs.UI.Flags as F-    ( DarcsFlag(Quiet,DryRun)-    , verbosity, dryRun, umask, useIndex-    , useCache, compression, diffAlgorithm )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Commands+    ( DarcsCommand(..), withStdOpts, nodefaults+    , putInfo, amInHashedRepository+    )+import Darcs.UI.Completion ( noArgs )+import Darcs.UI.Flags+    ( DarcsFlag, verbosity, dryRun, umask, useIndex+    , useCache, compress, diffAlgorithm, quiet+    )+import Darcs.UI.Options+    ( DarcsOption, (^), oid+    , odesc, ocheck, onormalise, defaultFlags, (?)+    ) import qualified Darcs.UI.Options.All as O+ import Darcs.Repository.Flags ( UpdateWorking (..) )-import Darcs.Repository.Repair( replayRepository, checkIndex,-                                replayRepositoryInTemp,-                                RepositoryConsistency(..) )-import Darcs.Repository ( Repository, withRepository,-                          readRecorded, RepoJob(..),-                          withRepoLock, replacePristine, writePatchSet )-import Darcs.Patch ( IsRepoType, RepoPatch, showPatch, PrimOf )-import Darcs.Patch.Apply( ApplyState )-import Darcs.Patch.Witnesses.Ordered ( FL(..) )-import Darcs.Patch.Witnesses.Sealed ( Sealed(..), unFreeLeft )+import Darcs.Repository.Repair+    ( replayRepository, checkIndex, replayRepositoryInTemp+    , RepositoryConsistency(..)+    )+import Darcs.Repository+    ( Repository, withRepository, readRecorded, RepoJob(..)+    , withRepoLock, replacePristine, writePatchSet+    ) import Darcs.Repository.Prefs ( filetypeFunction ) import Darcs.Repository.Diff( treeDiff )++import Darcs.Patch ( RepoPatch, showNicely, PrimOf )+import Darcs.Patch.Witnesses.Ordered ( FL(..) )+import Darcs.Patch.Witnesses.Sealed ( Sealed(..), unFreeLeft )+ import Darcs.Util.Global ( darcsdir ) import Darcs.Util.Printer ( text, ($$), (<+>) )-import Darcs.Util.Path ( AbsolutePath ) import Darcs.Util.Tree( Tree )  @@ -71,31 +78,9 @@  "unsuccessfully (with a non-zero exit status) if the rebuilt pristine is\n" ++  "different from the current pristine.\n" -repairBasicOpts :: DarcsOption a-                   (Maybe String -> O.UseIndex -> O.DryRun -> O.DiffAlgorithm -> a)-repairBasicOpts = O.workingRepoDir ^ O.useIndex  ^ O.dryRun  ^ O.diffAlgorithm--repairAdvancedOpts :: DarcsOption a (O.UMask -> a)-repairAdvancedOpts = O.umask--repairOpts :: DarcsOption a-              (Maybe String-               -> O.UseIndex-               -> O.DryRun-               -> O.DiffAlgorithm-               -> Maybe O.StdCmdAction-               -> Bool-               -> Bool-               -> O.Verbosity-               -> Bool-               -> O.UMask-               -> O.UseCache-               -> Maybe String-               -> Bool-               -> Maybe String-               -> Bool-               -> a)-repairOpts = repairBasicOpts `withStdOpts` repairAdvancedOpts+commonBasicOpts :: DarcsOption a+                   (Maybe String -> O.UseIndex -> O.DiffAlgorithm -> a)+commonBasicOpts = O.repoDir ^ O.useIndex ^ O.diffAlgorithm  repair :: DarcsCommand [DarcsFlag] repair = DarcsCommand@@ -105,82 +90,108 @@     , commandDescription = repairDescription     , commandExtraArgs = 0     , commandExtraArgHelp = []-    , commandCommand = repairCmd+    , commandCommand = withFpsAndArgs repairCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults-    , commandAdvancedOptions = odesc repairAdvancedOpts-    , commandBasicOptions = odesc repairBasicOpts-    , commandDefaults = defaultFlags repairOpts-    , commandCheckOptions = ocheck repairOpts-    , commandParseOptions = onormalise repairOpts+    , ..     }+  where+    basicOpts = commonBasicOpts ^ O.dryRun+    advancedOpts = O.umask+    allOpts = basicOpts `withStdOpts` advancedOpts+    commandAdvancedOptions = odesc advancedOpts+    commandBasicOptions = odesc basicOpts+    commandDefaults = defaultFlags allOpts+    commandCheckOptions = ocheck allOpts+    commandParseOptions = onormalise allOpts -repairCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-repairCmd _ opts _- | DryRun `elem` opts = withRepository (useCache opts) (RepoJob (check' opts))- | otherwise = withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do-  replayRepository (F.diffAlgorithm opts) repository (compression opts) (verbosity opts) $ \state ->-    case state of-      RepositoryConsistent ->-        putStrLn "The repository is already consistent, no changes made."-      BrokenPristine tree -> do-        putStrLn "Fixing pristine tree..."-        replacePristine repository tree-      BrokenPatches tree newps  -> do-        putStrLn "Writing out repaired patches..."-        _ <- writePatchSet newps (useCache opts)-        putStrLn "Fixing pristine tree..."-        replacePristine repository tree-  index_ok <- checkIndex repository (Quiet `elem` opts)-  unless index_ok $ do renameFile (darcsdir </> "index") (darcsdir </> "index.bad")-                       putStrLn "Bad index discarded."+withFpsAndArgs :: (b -> d) -> a -> b -> c -> d+withFpsAndArgs cmd _ opts _ = cmd opts -check'-  :: forall rt p wR wU wT . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-  => [DarcsFlag] -> Repository rt p wR wU wT -> IO ()-check' opts repository = do-  state <- replayRepositoryInTemp (F.diffAlgorithm opts) repository (compression opts) (verbosity opts)+repairCmd :: [DarcsFlag] -> IO ()+repairCmd opts = case dryRun ? opts of+ O.YesDryRun -> checkCmd opts+ O.NoDryRun ->+  withRepoLock O.NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts)+  $ RepoJob $ \repository -> do+    replayRepository (diffAlgorithm ? opts) repository (compress ? opts) (verbosity ? opts) $ \state ->+      case state of+        RepositoryConsistent ->+          putStrLn "The repository is already consistent, no changes made."+        BrokenPristine tree -> do+          putStrLn "Fixing pristine tree..."+          replacePristine repository tree+        BrokenPatches tree newps  -> do+          putStrLn "Writing out repaired patches..."+          _ <- writePatchSet newps (useCache ? opts)+          putStrLn "Fixing pristine tree..."+          replacePristine repository tree+    index_ok <- checkIndex repository (quiet opts)+    unless index_ok $ do renameFile (darcsdir </> "index") (darcsdir </> "index.bad")+                         putStrLn "Bad index discarded."++-- |check is an alias for repair, with implicit DryRun flag.+check :: DarcsCommand [DarcsFlag]+check = DarcsCommand+    { commandProgramName = "darcs"+    , commandName = "check"+    , commandHelp = "See `darcs repair` for details."+    , commandExtraArgs = 0+    , commandExtraArgHelp = []+    , commandCommand = withFpsAndArgs checkCmd+    , commandPrereq = amInHashedRepository+    , commandCompleteArgs = noArgs+    , commandArgdefaults = nodefaults+    , ..+    }+  where+    basicOpts = commonBasicOpts+    advancedOpts = oid+    allOpts = basicOpts `withStdOpts` advancedOpts+    commandAdvancedOptions = odesc advancedOpts+    commandBasicOptions = odesc basicOpts+    commandDefaults = defaultFlags allOpts+    commandCheckOptions = ocheck allOpts+    commandParseOptions = onormalise allOpts+    commandDescription = "Alias for `darcs " ++ commandName repair ++ " --dry-run'."++checkCmd :: [DarcsFlag] -> IO ()+checkCmd opts = withRepository (useCache ? opts) $ RepoJob $ \repository -> do+  state <- replayRepositoryInTemp (diffAlgorithm ? opts) repository (compress ? opts) (verbosity ? opts)   failed <-     case state of       RepositoryConsistent -> do         putInfo opts $ text "The repository is consistent!"         return False       BrokenPristine newpris -> do-        brokenPristine newpris+        brokenPristine opts repository newpris         return True       BrokenPatches newpris _ -> do-        brokenPristine newpris+        brokenPristine opts repository newpris         putInfo opts $ text "Found broken patches."         return True-  bad_index <- if useIndex opts == O.IgnoreIndex+  bad_index <- if useIndex ? opts == O.IgnoreIndex                  then return False-                 else not <$> checkIndex repository (Quiet `elem` opts)+                 else not <$> checkIndex repository (quiet opts)   when bad_index $ putInfo opts $ text "Bad index."   exitWith $ if failed || bad_index then ExitFailure 1 else ExitSuccess- where-   brokenPristine newpris = do-     putInfo opts $ text "Looks like we have a difference..."-     mc' <- (Just `fmap` readRecorded repository) `catch` (\(_ :: IOException) -> return Nothing)-     case mc' of-       Nothing -> do-         putInfo opts $ text "cannot compute that difference, try repair"-         putInfo opts $ text "" $$ text "Inconsistent repository"-       Just mc -> do-         ftf <- filetypeFunction-         Sealed (diff :: FL (PrimOf p) wR wR2)-          <- unFreeLeft `fmap` treeDiff (F.diffAlgorithm opts) ftf newpris mc :: IO (Sealed (FL (PrimOf p) wR))-         putInfo opts $ case diff of-                  NilFL -> text "Nothing"-                  patch -> text "Difference: " <+> showPatch patch-         putInfo opts $ text "" $$ text "Inconsistent repository!" --- |check is an alias for repair, with implicit DryRun flag.-check :: DarcsCommand [DarcsFlag]-check = checkAlias { commandCommand = checkCmd-                   , commandDescription = checkDesc-                   }-  where-    checkAlias      = commandAlias "check" Nothing repair-    checkCmd fps fs = commandCommand repair fps (DryRun : fs)-    checkDesc       = "Alias for `darcs " ++ commandName repair ++ " --dry-run'."+brokenPristine+  :: forall rt p wR wU wT . (RepoPatch p)+  => [DarcsFlag] -> Repository rt p wR wU wT -> Tree IO -> IO ()+brokenPristine opts repository newpris = do+  putInfo opts $ text "Looks like we have a difference..."+  mc' <- (Just `fmap` readRecorded repository) `catch` (\(_ :: IOException) -> return Nothing)+  case mc' of+    Nothing -> do+      putInfo opts $ text "cannot compute that difference, try repair"+      putInfo opts $ text "" $$ text "Inconsistent repository"+    Just mc -> do+      ftf <- filetypeFunction+      Sealed (diff :: FL (PrimOf p) wR wR2)+        <- unFreeLeft `fmap` treeDiff (diffAlgorithm ? opts) ftf newpris mc :: IO (Sealed (FL (PrimOf p) wR))+      putInfo opts $ case diff of+        NilFL -> text "Nothing"+        patch -> text "Difference: " <+> showNicely patch+      putInfo opts $ text "" $$ text "Inconsistent repository!"
src/Darcs/UI/Commands/Replace.hs view
@@ -15,8 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.UI.Commands.Replace     ( replace     , defaultToks@@ -27,7 +25,7 @@  import qualified Data.ByteString.Char8 as BC import qualified Data.ByteString.Lazy as BL-import qualified Data.ByteString as BS+import qualified Data.ByteString as B import Data.Char ( isSpace ) import Data.Maybe ( isJust ) import Control.Exception ( catch, IOException )@@ -36,14 +34,15 @@                       , makeBlobBS ) import Darcs.Util.Path( SubPath, toFilePath, AbsolutePath ) import Darcs.UI.Flags-    ( DarcsFlag( ForceReplace, Toks )+    ( DarcsFlag     , verbosity, useCache, dryRun, umask, diffAlgorithm, fixSubPaths )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Flags ( UpdateWorking(..) ) import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository )+import Darcs.UI.Completion ( knownFileArgs ) import Darcs.Repository.Diff( treeDiff )-import Darcs.Patch ( Patchy, PrimPatch, tokreplace, forceTokReplace+import Darcs.Patch ( PrimPatch, tokreplace, forceTokReplace                    , maybeApplyToTree ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.RegChars ( regChars )@@ -53,8 +52,6 @@     , addToPending     , applyToWorking     , readUnrecorded-    , readRecordedAndPending-    , listRegisteredFiles     ) import Darcs.Patch.TokenReplace ( defaultToks ) import Darcs.Repository.Prefs ( FileType(TextFile) )@@ -62,8 +59,6 @@ import Darcs.Patch.Witnesses.Ordered ( FL(..), (+>+), concatFL, toFL, nullFL ) import Darcs.Patch.Witnesses.Sealed ( Sealed(..), mapSeal, FreeLeft, Gap(..), unFreeLeft, unseal ) -#include "impossible.h"- replaceDescription :: String replaceDescription = "Substitute one word for another." @@ -123,31 +118,6 @@  "`[[:alnum:]]`) are NOT supported by `--token-chars`, and will be silently\n" ++  "treated as a simple set of characters.\n" -replaceBasicOpts :: DarcsOption a (Maybe String -> Bool -> Maybe String -> a)-replaceBasicOpts = O.tokens ^ O.forceReplace ^ O.workingRepoDir--replaceAdvancedOpts :: DarcsOption a (O.UseIndex -> O.UMask -> a)-replaceAdvancedOpts = O.useIndex ^ O.umask--replaceOpts :: DarcsOption a-               (Maybe String-                -> Bool-                -> Maybe String-                -> Maybe O.StdCmdAction-                -> Bool-                -> Bool-                -> O.Verbosity-                -> Bool-                -> O.UseIndex-                -> O.UMask-                -> O.UseCache-                -> Maybe String-                -> Bool-                -> Maybe String-                -> Bool-                -> a)-replaceOpts = replaceBasicOpts `withStdOpts` replaceAdvancedOpts- replace :: DarcsCommand [DarcsFlag] replace = DarcsCommand     { commandProgramName = "darcs"@@ -161,7 +131,7 @@                             ]     , commandCommand = replaceCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = listRegisteredFiles+    , commandCompleteArgs = replaceArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc replaceAdvancedOpts     , commandBasicOptions = odesc replaceBasicOpts@@ -169,27 +139,35 @@     , commandCheckOptions = ocheck replaceOpts     , commandParseOptions = onormalise replaceOpts     }+  where+    replaceBasicOpts = O.tokens ^ O.forceReplace ^ O.repoDir+    replaceAdvancedOpts = O.useIndex ^ O.umask+    replaceOpts = replaceBasicOpts `withStdOpts` replaceAdvancedOpts +replaceArgs  :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO [String]+replaceArgs fps flags args =+  if length args < 2+    then return []+    else knownFileArgs fps flags args+ replaceCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () replaceCmd fps opts (old : new : relfs@(_ : _)) =-  withRepoLock  (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $+  withRepoLock  (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $ RepoJob $     \repository -> do         fs <- fixSubPaths fps relfs-        toks <- chooseToks opts old new+        toks <- chooseToks (O.tokens ? opts) old new         let checkToken tok = unless (isTok toks tok) $                                  fail $ "'" ++ tok ++ "' is not a valid token!"         mapM_ checkToken [ old, new ]         working <- readUnrecorded repository Nothing-        pending <- readRecordedAndPending repository         files <- filterM (exists working) fs         Sealed replacePs <- mapSeal concatFL . toFL <$>-            mapM (doReplace toks pending working) files+            mapM (doReplace toks working) files+        -- Note: addToPending takes care of commuting the replace patch and+        -- everything it depends on past the diff between pending and working         addToPending repository YesUpdateWorking replacePs-        void $ applyToWorking repository (verbosity opts) replacePs `catch` \(e :: IOException) ->-            fail $ "Can't do replace on working!\n"-                   ++ "Perhaps one of the files already" ++ " contains '"-                   ++ new ++ "'?\n"-                   ++ show e+        void $ applyToWorking repository (verbosity ? opts) replacePs `catch` \(e :: IOException) ->+            bug $ "Can't do replace on working!\n" ++ show e   where     exists tree file = if isJust $ findFile tree (floatSubPath file)                            then return True@@ -199,20 +177,19 @@     skipmsg f = "Skipping file '" ++ toFilePath f                 ++ "' which isn't in the repository." -    doReplace :: forall prim . (Patchy prim, PrimPatch prim,-              ApplyState prim ~ Tree) => String -> Tree IO -> Tree IO+    doReplace :: forall prim . (PrimPatch prim,+              ApplyState prim ~ Tree) => String -> Tree IO               -> SubPath -> IO (FreeLeft (FL prim))-    doReplace toks pend work f = do-        let maybeReplace p = isJust <$> maybeApplyToTree replacePatch p-        workReplaced <- maybeReplace work-        pendReplaced <- maybeReplace pend-        if workReplaced && pendReplaced-            then return $ joinGap (:>:) (freeGap replacePatch) gapNilFL-            else if ForceReplace `elem` opts-                then getForceReplace f toks work-                else putStrLn existsMsg >> return gapNilFL+    doReplace toks work f = do+        workReplaced <- maybeApplyToTree replacePatch work+        case workReplaced of+          Just _ -> do+            return $ joinGap (:>:) (freeGap replacePatch) gapNilFL+          Nothing+            | O.forceReplace ? opts -> getForceReplace f toks work+            | otherwise -> putStrLn existsMsg >> return gapNilFL       where-        existsMsg = "Skipping file '" ++ fp ++ "'\nPerhaps the recorded"+        existsMsg = "Skipping file '" ++ fp ++ "'\nPerhaps the working"                     ++ " version of this file already contains '" ++ new                     ++ "'?\nUse the --force option to override."         gapNilFL = emptyGap NilFL@@ -231,9 +208,9 @@         let path = floatSubPath f         content <- readBlob $ fromJust $ findFile tree path         let newcontent = forceTokReplace toks (BC.pack new) (BC.pack old)-                            (BS.concat $ BL.toChunks content)+                            (B.concat $ BL.toChunks content)             tree' = modifyTree tree path . Just . File $ makeBlobBS newcontent-        normaliseNewTokPatch <- treeDiff (diffAlgorithm opts) ftf tree tree'+        normaliseNewTokPatch <- treeDiff (diffAlgorithm ? opts) ftf tree tree'         unless (unseal nullFL (unFreeLeft normaliseNewTokPatch)) $             putStrLn $ "Don't be surprised!\n"                        ++ "I've changed all instances of '" ++ new ++ "' to '"@@ -243,7 +220,7 @@         return . joinGap (+>+) normaliseNewTokPatch $ freeGap $             tokreplace (toFilePath f) toks old new :>: NilFL replaceCmd _ _ [_, _] = fail "You need to supply a list of files to replace in!"-replaceCmd _ _ _ = fail "Usage: darcs replace OLD NEW [FILES]"+replaceCmd _ _ _ = fail "Usage: darcs replace <OLD> <NEW> <FILE>..."  filenameToks :: String filenameToks = "A-Za-z_0-9\\-\\."@@ -262,8 +239,8 @@ -- -- Note: Limitations in the current replace patch file format prevents tokens -- and token-char specifiers from containing any whitespace.-chooseToks :: [DarcsFlag] -> String -> String -> IO String-chooseToks (Toks t : _) a b+chooseToks :: Maybe String -> String -> String -> IO String+chooseToks (Just t) a b     | length t <= 2 =         badTokenSpec $ "It must contain more than 2 characters, because it"                        ++ " should be enclosed in square brackets"@@ -284,7 +261,7 @@     spaceyToken x = x ++ " must not contain any space"     notAToken x = x ++ " is not a token, according to your spec" -chooseToks (_ : fs) a b = chooseToks fs a b-chooseToks [] a b = if isTok defaultToks a && isTok defaultToks b-                        then return defaultToks-                        else return filenameToks+chooseToks Nothing a b =+    if isTok defaultToks a && isTok defaultToks b+      then return defaultToks+      else return filenameToks
src/Darcs/UI/Commands/Revert.hs view
@@ -25,14 +25,15 @@ import Data.List ( sort )  import Darcs.UI.Flags-    ( DarcsFlag, diffingOpts, verbosity, diffAlgorithm, isInteractive, isUnified+    ( DarcsFlag, diffingOpts, verbosity, diffAlgorithm, isInteractive, withContext     , dryRun, umask, useCache, fixSubPaths )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Flags ( UpdateWorking(..) ) import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository, putInfo ) import Darcs.UI.Commands.Util ( announceFiles ) import Darcs.UI.Commands.Unrevert ( writeUnrevert )+import Darcs.UI.Completion ( modifiedFileArgs ) import Darcs.Util.Global ( debugMessage ) import Darcs.Util.Path ( toFilePath, AbsolutePath ) import Darcs.Repository@@ -42,7 +43,6 @@     , applyToWorking     , readRecorded     , unrecordedChanges-    , listRegisteredFiles     ) import Darcs.Patch ( invert, effectOnFilePaths, commute ) import Darcs.Patch.Split ( reversePrimSplitter )@@ -74,45 +74,14 @@  "guaranteed to work if the repository has not changed since `darcs\n" ++  "revert` ran.\n" -revertBasicOpts :: DarcsOption a-                   (Maybe Bool -> Maybe String -> O.WithContext -> O.DiffAlgorithm -> a)-revertBasicOpts-    = O.interactive -- True-    ^ O.workingRepoDir-    ^ O.withContext-    ^ O.diffAlgorithm--revertAdvancedOpts :: DarcsOption a (O.UseIndex -> O.UMask -> a)-revertAdvancedOpts = O.useIndex ^ O.umask--revertOpts :: DarcsOption a-              (Maybe Bool-               -> Maybe String-               -> O.WithContext-               -> O.DiffAlgorithm-               -> Maybe O.StdCmdAction-               -> Bool-               -> Bool-               -> O.Verbosity-               -> Bool-               -> O.UseIndex-               -> O.UMask-               -> O.UseCache-               -> Maybe String-               -> Bool-               -> Maybe String-               -> Bool-               -> a)-revertOpts = revertBasicOpts `withStdOpts` revertAdvancedOpts- patchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions patchSelOpts flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { S.verbosity = verbosity ? flags     , S.matchFlags = []     , S.interactive = isInteractive True flags     , S.selectDeps = O.PromptDeps -- option not supported, use default     , S.summary = O.NoSummary -- option not supported, use default-    , S.withContext = isUnified flags+    , S.withContext = withContext ? flags     }  revert :: DarcsCommand [DarcsFlag]@@ -125,7 +94,7 @@     , commandExtraArgHelp = ["[FILE or DIRECTORY]..."]     , commandCommand = revertCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = listRegisteredFiles+    , commandCompleteArgs = modifiedFileArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc revertAdvancedOpts     , commandBasicOptions = odesc revertBasicOpts@@ -133,14 +102,23 @@     , commandCheckOptions = ocheck revertOpts     , commandParseOptions = onormalise revertOpts     }+  where+    revertBasicOpts+      = O.interactive -- True+      ^ O.repoDir+      ^ O.withContext+      ^ O.diffAlgorithm+    revertAdvancedOpts = O.useIndex ^ O.umask+    revertOpts = revertBasicOpts `withStdOpts` revertAdvancedOpts  revertCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () revertCmd fps opts args =- withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+ withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $ RepoJob $ \repository -> do   files <- if null args then return Nothing     else Just . sort <$> fixSubPaths fps args-  announceFiles (verbosity opts) files "Reverting changes in"-  changes <- unrecordedChanges (diffingOpts opts {- always ScanKnown here -}) repository files+  announceFiles (verbosity ? opts) files "Reverting changes in"+  changes <- unrecordedChanges (diffingOpts opts {- always ScanKnown here -})+    O.NoLookForMoves O.NoLookForReplaces repository files   let pre_changed_files = effectOnFilePaths (invert changes) . map toFilePath <$> files   recorded <- readRecorded repository   Sealed touching_changes <- return (chooseTouching pre_changed_files changes)@@ -149,7 +127,7 @@     _ -> do       let context = selectionContextPrim                           Last "revert" (patchSelOpts opts)-                          (Just (reversePrimSplitter (diffAlgorithm opts)))+                          (Just (reversePrimSplitter (diffAlgorithm ? opts)))                           pre_changed_files (Just recorded)       (norevert:>p) <- runSelection changes context       if nullFL p@@ -161,7 +139,7 @@                    Just (p':>_) -> writeUnrevert repository p' recorded NilFL                    Nothing -> writeUnrevert repository (norevert+>+p) recorded NilFL                  debugMessage "About to apply to the working directory."-                 _ <- applyToWorking repository (verbosity opts) (invert p) `catch` \(e :: IOException) ->+                 _ <- applyToWorking repository (verbosity ? opts) (invert p) `catch` \(e :: IOException) ->                      fail ("Unable to apply inverse patch!" ++ show e)                  return ()       putInfo opts "Finished reverting."
src/Darcs/UI/Commands/Rollback.hs view
@@ -15,8 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.UI.Commands.Rollback ( rollback ) where  import Prelude ()@@ -34,7 +32,7 @@ import Darcs.Patch ( IsRepoType, RepoPatch, invert, effect, fromPrims, sortCoalesceFL,                      canonize, PrimOf ) import Darcs.Patch.Named.Wrapped ( anonymous )-import Darcs.Patch.Set ( PatchSet(..), newset2FL )+import Darcs.Patch.Set ( PatchSet(..), patchSet2FL ) import Darcs.Patch.Split ( reversePrimSplitter ) import Darcs.Patch.Witnesses.Ordered ( FL(..), (:>)(..), RL(..), concatFL,                                        nullFL, mapFL_FL )@@ -44,17 +42,18 @@ import Darcs.Repository ( Repository, withRepoLock, RepoJob(..),                           applyToWorking, readRepo,                           finalizeRepositoryChanges, tentativelyAddToPending,-                          considerMergeToWorking, listRegisteredFiles )+                          considerMergeToWorking ) import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, setEnvDarcsPatches,-                           amInHashedRepository )+                           amInHashedRepository, putInfo ) import Darcs.UI.Commands.Unrecord ( getLastPatches ) import Darcs.UI.Commands.Util ( announceFiles )-import Darcs.UI.Flags as F ( DarcsFlag(Quiet), verbosity, umask, useCache,-                        compression, externalMerge, wantGuiPause,+import Darcs.UI.Completion ( knownFileArgs )+import Darcs.UI.Flags ( DarcsFlag, verbosity, umask, useCache,+                        compress, externalMerge, wantGuiPause,                         diffAlgorithm, fixSubPaths, isInteractive ) import Darcs.UI.Options-    ( DarcsOption, (^), odesc, ocheck, onormalise-    , defaultFlags, parseFlags+    ( (^), odesc, ocheck, onormalise+    , defaultFlags, parseFlags, (?)     ) import qualified Darcs.UI.Options.All as O import Darcs.UI.SelectChanges ( WhichChanges(..),@@ -62,6 +61,7 @@                                 runSelection ) import qualified Darcs.UI.SelectChanges as S ( PatchSelectionOptions(..) ) import Darcs.Util.Path ( toFilePath, AbsolutePath )+import Darcs.Util.Printer ( text ) import Darcs.Util.Progress ( debugMessage )  rollbackDescription :: String@@ -82,40 +82,9 @@     , "and run `unrevert` to restore the saved changes into your working tree."     ] -rollbackBasicOpts :: DarcsOption a-                     ([O.MatchFlag]-                      -> Maybe Bool -> Maybe String -> O.DiffAlgorithm -> a)-rollbackBasicOpts-    = O.matchSeveralOrLast-    ^ O.interactive -- True-    ^ O.workingRepoDir-    ^ O.diffAlgorithm--rollbackAdvancedOpts :: DarcsOption a (O.UMask -> a)-rollbackAdvancedOpts = O.umask--rollbackOpts :: DarcsOption a-                ([O.MatchFlag]-                 -> Maybe Bool-                 -> Maybe String-                 -> O.DiffAlgorithm-                 -> Maybe O.StdCmdAction-                 -> Bool-                 -> Bool-                 -> O.Verbosity-                 -> Bool-                 -> O.UMask-                 -> O.UseCache-                 -> Maybe String-                 -> Bool-                 -> Maybe String-                 -> Bool-                 -> a)-rollbackOpts = rollbackBasicOpts `withStdOpts` rollbackAdvancedOpts- patchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions patchSelOpts flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { S.verbosity = verbosity ? flags     , S.matchFlags = parseFlags O.matchSeveralOrLast flags     , S.interactive = isInteractive True flags     , S.selectDeps = O.PromptDeps@@ -133,7 +102,7 @@     , commandExtraArgHelp = ["[FILE or DIRECTORY]..."]     , commandCommand = rollbackCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = listRegisteredFiles+    , commandCompleteArgs = knownFileArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc rollbackAdvancedOpts     , commandBasicOptions = odesc rollbackBasicOpts@@ -141,26 +110,34 @@     , commandCheckOptions = ocheck rollbackOpts     , commandParseOptions = onormalise rollbackOpts     }+  where+    rollbackBasicOpts+      = O.matchSeveralOrLast+      ^ O.interactive -- True+      ^ O.repoDir+      ^ O.diffAlgorithm+    rollbackAdvancedOpts = O.umask+    rollbackOpts = rollbackBasicOpts `withStdOpts` rollbackAdvancedOpts  exitIfNothingSelected :: FL p wX wY -> String -> IO () exitIfNothingSelected ps what =     when (nullFL ps) $ putStrLn ("No " ++ what ++ " selected!") >> exitSuccess  rollbackCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-rollbackCmd fps opts args = withRepoLock NoDryRun (useCache opts)-    YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+rollbackCmd fps opts args = withRepoLock NoDryRun (useCache ? opts)+    YesUpdateWorking (umask ? opts) $ RepoJob $ \repository -> do         files <- if null args                      then return Nothing                      else Just . sort <$> fixSubPaths fps args         when (files == Just []) $             fail "No valid arguments were given."-        announceFiles (verbosity opts) files "Rolling back changes in"+        announceFiles (verbosity ? opts) files "Rolling back changes in"         allpatches <- readRepo repository         let matchFlags = parseFlags O.matchSeveralOrLast opts         (_ :> patches) <- return $             if firstMatch matchFlags                 then getLastPatches matchFlags allpatches-                else PatchSet NilRL NilRL :> newset2FL allpatches+                else PatchSet NilRL NilRL :> patchSet2FL allpatches         let filesFps = map toFilePath <$> files             patchCtx = selectionContext LastReversed "rollback" (patchSelOpts opts) Nothing filesFps         (_ :> ps) <-@@ -168,13 +145,13 @@         exitIfNothingSelected ps "patches"         setEnvDarcsPatches ps         let hunkContext = selectionContextPrim Last "rollback" (patchSelOpts opts)-                              (Just (reversePrimSplitter (diffAlgorithm opts)))+                              (Just (reversePrimSplitter (diffAlgorithm ? opts)))                               filesFps Nothing-            hunks = concatFL . mapFL_FL (canonize $ F.diffAlgorithm opts) . sortCoalesceFL . effect $ ps+            hunks = concatFL . mapFL_FL (canonize $ diffAlgorithm ? opts) . sortCoalesceFL . effect $ ps         whatToUndo <- runSelection hunks hunkContext         undoItNow opts repository whatToUndo -undoItNow :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)+undoItNow :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)           => [DarcsFlag] -> Repository rt p wR wU wT           -> (q :> FL (PrimOf p)) wA wT -> IO () undoItNow opts repo (_ :> prims) = do@@ -182,19 +159,18 @@     rbp <- n2pia `fmap` anonymous (fromPrims $ invert prims)     Sealed pw <- considerMergeToWorking repo "rollback"                      YesAllowConflictsAndMark YesUpdateWorking-                     (externalMerge opts) (wantGuiPause opts)-                     (compression opts) (verbosity opts) NoReorder-                     (UseIndex, ScanKnown, F.diffAlgorithm opts)+                     (externalMerge ? opts) (wantGuiPause opts)+                     (compress ? opts) (verbosity ? opts) NoReorder+                     (UseIndex, ScanKnown, diffAlgorithm ? opts)                      NilFL (rbp :>: NilFL)     tentativelyAddToPending repo YesUpdateWorking pw     finalizeRepositoryChanges repo YesUpdateWorking-        (compression opts)-    _ <- applyToWorking repo (verbosity opts) pw+        (compress ? opts)+    _ <- applyToWorking repo (verbosity ? opts) pw             `catch`             \(e :: IOException) -> fail $                 "error applying rolled back patch to working directory\n"                 ++ show e     debugMessage "Finished applying unrecorded rollback patch"-    when (F.Quiet `notElem` opts) $-        putStrLn "Changes rolled back in working directory"+    putInfo opts $ text "Changes rolled back in working directory" 
src/Darcs/UI/Commands/Send.hs view
@@ -22,8 +22,6 @@ import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) )- import System.Exit     ( exitSuccess #ifndef HAVE_MAPI@@ -44,20 +42,14 @@     ( DarcsCommand(..), withStdOpts     , putInfo     , putVerbose-    , printDryRunMessageAndExit     , setEnvDarcsPatches     , defaultRepo     , amInHashedRepository     )+import Darcs.UI.Commands.Util ( printDryRunMessageAndExit, checkUnrelatedRepos ) import Darcs.UI.Flags-    ( DarcsFlag( Target-               , Context-               , Mail-               , DryRun-               , Quiet-               , AllowUnrelatedRepos-               )-    , willRemoveLogFile, doReverse, dryRun, useCache, remoteRepos, setDefault+    ( DarcsFlag+    , willRemoveLogFile, changesReverse, dryRun, useCache, remoteRepos, setDefault     , fixUrl     , getCc     , getAuthor@@ -65,26 +57,32 @@     , getInReplyTo     , getSendmailCmd     , getOutput-    , getCharset+    , charset     , verbosity-    , hasSummary     , isInteractive-    , hasAuthor+    , author     , hasLogfile     , selectDeps     , minimize     , editDescription     ) import Darcs.UI.Options-    ( DarcsOption, (^), odesc, ocheck, onormalise-    , defaultFlags, parseFlags+    ( (^), odesc, ocheck, onormalise+    , defaultFlags, parseFlags, (?)     ) import qualified Darcs.UI.Options.All as O  import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, hopefully, patchDesc )-import Darcs.Repository ( PatchSet, Repository,-                          identifyRepositoryFor, withRepository, RepoJob(..),-                          readRepo, readRecorded, prefsUrl, checkUnrelatedRepos )+import Darcs.Repository+    ( Repository+    , repoLocation+    , PatchSet+    , identifyRepositoryFor+    , withRepository+    , RepoJob(..)+    , readRepo+    , readRecorded+    , prefsUrl ) import Darcs.Patch.Set ( Origin ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch ( IsRepoType, RepoPatch, description, applyToTree, invert )@@ -95,6 +93,7 @@     mapFL, mapFL_FL, lengthFL, nullFL ) import Darcs.Patch.Bundle ( minContext, makeBundleN, scanContextFile, patchFilename ) import Darcs.Repository.Prefs ( addRepoSource, getPreflist )+import Darcs.Repository.Flags ( DryRun(..) ) import Darcs.Util.External ( fetchFilePS, Cachable(..) ) import Darcs.UI.External     ( signString@@ -127,11 +126,13 @@ import Data.Text.Encoding       ( decodeUtf8' ) import Darcs.Util.Progress ( debugMessage ) import Darcs.UI.Email ( makeEmail )+import Darcs.UI.Completion ( prefArgs ) import Darcs.Util.Printer     ( Doc, vsep, text, ($$), (<+>), (<>), putDoc, putDocLn-    , renderPS, RenderMode(..)+    , renderPS, vcat     ) import Darcs.Util.English ( englishNum, Noun(..) )+import Darcs.Util.Text ( sentence, quote ) import Darcs.Util.Path ( FilePathLike, toFilePath, AbsolutePath, AbsolutePathOrStd,                         getCurrentDirectory, useAbsoluteOrStd, makeAbsoluteOrStd ) import Darcs.Util.Download.HTTP ( postUrl )@@ -139,103 +140,13 @@ import Darcs.Util.Global ( darcsSendMessage, darcsSendMessageFinal ) import Darcs.Util.SignalHandler ( catchInterrupt ) -import qualified Darcs.UI.Message.Send as Msg-#include "impossible.h"--sendBasicOpts :: DarcsOption a-                 ([O.MatchFlag]-                  -> O.SelectDeps-                  -> Maybe Bool-                  -> O.HeaderFields-                  -> Maybe String-                  -> Maybe String-                  -> (Bool, Maybe String)-                  -> Maybe O.Output-                  -> O.Sign-                  -> O.DryRun-                  -> O.XmlOutput-                  -> Maybe O.Summary-                  -> Bool-                  -> Maybe Bool-                  -> Maybe String-                  -> Bool-                  -> Bool-                  -> a)-sendBasicOpts-    = O.matchSeveral-    ^ O.selectDeps-    ^ O.interactive -- True-    ^ O.headerFields-    ^ O.author-    ^ O.charset-    ^ O.sendmail-    ^ O.output-    ^ O.sign-    ^ O.dryRunXml-    ^ O.summary-    ^ O.editDescription-    ^ O.setDefault-    ^ O.workingRepoDir-    ^ O.minimize-    ^ O.allowUnrelatedRepos--sendAdvancedOpts :: DarcsOption a-                    (O.Logfile-                     -> O.RemoteRepos-                     -> Maybe AbsolutePath-                     -> Bool-                     -> O.NetworkOptions-                     -> a)-sendAdvancedOpts-    = O.logfile-    ^ O.remoteRepos-    ^ O.sendToContext -    ^ O.changesReverse-    ^ O.network--sendOpts :: DarcsOption a-            ([O.MatchFlag]-             -> O.SelectDeps-             -> Maybe Bool-             -> O.HeaderFields-             -> Maybe String-             -> Maybe String-             -> (Bool, Maybe String)-             -> Maybe O.Output-             -> O.Sign-             -> O.DryRun-             -> O.XmlOutput-             -> Maybe O.Summary-             -> Bool-             -> Maybe Bool-             -> Maybe String-             -> Bool-             -> Bool-             -> Maybe O.StdCmdAction-             -> Bool-             -> Bool-             -> O.Verbosity-             -> Bool-             -> O.Logfile-             -> O.RemoteRepos-             -> Maybe AbsolutePath-             -> Bool-             -> O.NetworkOptions-             -> O.UseCache-             -> Maybe String-             -> Bool-             -> Maybe String-             -> Bool-             -> a)-sendOpts = sendBasicOpts `withStdOpts` sendAdvancedOpts- patchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions patchSelOpts flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { S.verbosity = verbosity ? flags     , S.matchFlags = parseFlags O.matchSeveral flags     , S.interactive = isInteractive True flags-    , S.selectDeps = selectDeps flags-    , S.summary = hasSummary O.NoSummary flags+    , S.selectDeps = selectDeps ? flags+    , S.summary = O.summary ? flags     , S.withContext = O.NoContext     } @@ -243,13 +154,13 @@ send = DarcsCommand     { commandProgramName = "darcs"     , commandName = "send"-    , commandHelp = Msg.cmdHelp-    , commandDescription = Msg.cmdDescription+    , commandHelp = cmdHelp+    , commandDescription = cmdDescription     , commandExtraArgs = 1     , commandExtraArgHelp = ["[REPOSITORY]"]     , commandCommand = sendCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = getPreflist "repos"+    , commandCompleteArgs = prefArgs "repos"     , commandArgdefaults = defaultRepo     , commandAdvancedOptions = odesc sendAdvancedOpts     , commandBasicOptions = odesc sendBasicOpts@@ -257,35 +168,59 @@     , commandCheckOptions = ocheck sendOpts     , commandParseOptions = onormalise sendOpts     }+  where+    sendBasicOpts+      = O.matchSeveral+      ^ O.selectDeps+      ^ O.interactive -- True+      ^ O.headerFields+      ^ O.author+      ^ O.charset+      ^ O.sendmail+      ^ O.output+      ^ O.sign+      ^ O.dryRunXml+      ^ O.summary+      ^ O.editDescription+      ^ O.setDefault+      ^ O.repoDir+      ^ O.minimize+      ^ O.allowUnrelatedRepos+    sendAdvancedOpts+      = O.logfile+      ^ O.remoteRepos+      ^ O.sendToContext +      ^ O.changesReverse+      ^ O.network+    sendOpts = sendBasicOpts `withStdOpts` sendAdvancedOpts  sendCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-sendCmd fps input_opts [""] = sendCmd fps input_opts []-sendCmd (_,o) input_opts [unfixedrepodir] =- withRepository (useCache input_opts) $ RepoJob $+sendCmd fps opts [""] = sendCmd fps opts []+sendCmd (_,o) opts [unfixedrepodir] =+ withRepository (useCache ? opts) $ RepoJob $   \(repository :: Repository rt p wR wU wR) -> do-  context_ps <- the_context input_opts+  context_ps <- the_context (O.sendToContext ? opts)   case context_ps of     Just them -> do-        wtds <- decideOnBehavior input_opts (Nothing :: Maybe (Repository rt p wR wU wR))-        sendToThem repository input_opts wtds "CONTEXT" them+        wtds <- decideOnBehavior opts (Nothing :: Maybe (Repository rt p wR wU wR))+        sendToThem repository opts wtds "CONTEXT" them     Nothing -> do         repodir <- fixUrl o unfixedrepodir         -- Test to make sure we aren't trying to push to the current repo         here <- getCurrentDirectory         when (repodir == toFilePath here) $-           fail Msg.cannotSendToSelf+           fail cannotSendToSelf         old_default <- getPreflist "defaultrepo"-        when (old_default == [repodir] && Quiet `notElem` input_opts) $-             putDocLn (Msg.creatingPatch repodir)-        repo <- identifyRepositoryFor repository (useCache input_opts) repodir+        when (old_default == [repodir]) $+            putInfo opts (creatingPatch repodir)+        repo <- identifyRepositoryFor repository (useCache ? opts) repodir         them <- readRepo repo-        addRepoSource repodir (dryRun input_opts) (remoteRepos input_opts) (setDefault False input_opts)-        wtds <- decideOnBehavior input_opts (Just repo)-        sendToThem repository input_opts wtds repodir them-    where the_context [] = return Nothing-          the_context (Context foo:_)-              = Just `fmap` scanContextFile (toFilePath foo)-          the_context (_:fs) = the_context fs+        addRepoSource repodir (dryRun ? opts) (remoteRepos ? opts) (setDefault False opts)+        wtds <- decideOnBehavior opts (Just repo)+        sendToThem repository opts wtds repodir them+    where+        the_context Nothing = return Nothing+        the_context (Just foo) = Just `fmap` scanContextFile (toFilePath foo) sendCmd _ _ _ = impossible  sendToThem :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)@@ -293,40 +228,40 @@            -> PatchSet rt p Origin wX -> IO () sendToThem repo opts wtds their_name them = do #ifndef HAVE_MAPI-  -- Check if the user has sendmail or provided a --sendmail-cmd-  -- (unless -o/-O or --dry-run is used)-  sendmail <- haveSendmail-  sm_cmd <- getSendmailCmd opts-  when (isNothing (getOutput opts "") && DryRun `notElem` opts &&-        not sendmail && sm_cmd == "") $ do-      putInfo opts Msg.noWorkingSendmail-      exitWith $ ExitFailure 1+  when (fst (O.sendmail ? opts) && dryRun ? opts == O.NoDryRun) $ do+    -- If --mail is used, check if the user has sendmail or+    -- provided a --sendmail-cmd+    sendmail <- haveSendmail+    sm_cmd <- getSendmailCmd opts+    when (not sendmail && sm_cmd == "") $ do+        putInfo opts noWorkingSendmail+        exitWith $ ExitFailure 1 #endif   us <- readRepo repo   common :> us' <- return $ findCommonWithThem us them-  checkUnrelatedRepos (AllowUnrelatedRepos `elem` opts) us them+  checkUnrelatedRepos (O.allowUnrelatedRepos ? opts) us them   case us' of-      NilFL -> do putInfo opts Msg.nothingSendable+      NilFL -> do putInfo opts nothingSendable                   exitSuccess-      _     -> putVerbose opts $ Msg.selectionIs (mapFL description us')+      _     -> putVerbose opts $ selectionIs (mapFL description us')   pristine <- readRecorded repo-  let direction = if doReverse opts then FirstReversed else First+  let direction = if changesReverse ? opts then FirstReversed else First       context = selectionContext direction "send" (patchSelOpts opts) Nothing Nothing   (to_be_sent :> _) <- runSelection us' context   printDryRunMessageAndExit "send"-      (verbosity opts)-      (hasSummary O.NoSummary opts)-      (dryRun opts)+      (verbosity ? opts)+      (O.summary ? opts)+      (dryRun ? opts)       O.NoXml       (isInteractive True opts)       to_be_sent   when (nullFL to_be_sent) $ do-      putInfo opts Msg.selectionIsNull+      putInfo opts selectionIsNull       exitSuccess   setEnvDarcsPatches to_be_sent    let genFullBundle = prepareBundle opts common  (Right (pristine, us':\/:to_be_sent))-  bundle <- if not (minimize opts)+  bundle <- if not (minimize ? opts)              then genFullBundle              else do putInfo opts "Minimizing context, to send with full context hit ctrl-C..."                      ( case minContext common to_be_sent of@@ -338,7 +273,7 @@       fname = make_fname to_be_sent       outname = case getOutput opts fname of                     Just f  -> Just f-                    Nothing | Mail `elem` opts -> Nothing+                    Nothing | fst (O.sendmail ? opts) -> Nothing                             | not $ null [ p | Post p <- wtds] -> Nothing                             | otherwise        -> Just (makeAbsoluteOrStd here fname)   case outname of@@ -378,35 +313,35 @@                        else take (n-3) st ++ "..."            in do            thetargets <- getTargets wtds-           from <- getAuthor (hasAuthor opts) False+           from <- getAuthor (author ? opts) False            let thesubject = fromMaybe (auto_subject to_be_sent) $ getSubject opts            (mailcontents, mailfile, mailcharset) <- getDescription opts their_name to_be_sent             let warnMailBody = case mailfile of-                                  Just mf -> putDocLn $ Msg.emailBackedUp mf+                                  Just mf -> putDocLn $ emailBackedUp mf                                   Nothing -> return ()                 warnCharset msg = do-                 confirmed <- promptYorn $ Msg.promptCharSetWarning msg+                 confirmed <- promptYorn $ promptCharSetWarning msg                  unless confirmed $ do-                    putDocLn Msg.charsetAborted+                    putDocLn charsetAborted                     warnMailBody                     exitSuccess -           thecharset <- case getCharset opts of+           thecharset <- case charset ? opts of                               -- Always trust provided charset                               providedCset@(Just _) -> return providedCset                               Nothing ->                                 case mailcharset of                                 Nothing -> do-                                  warnCharset Msg.charsetCouldNotGuess+                                  warnCharset charsetCouldNotGuess                                   return mailcharset                                 Just "utf-8" -> do                                   -- Check the locale encoding for consistency                                   encoding <- getSystemEncoding-                                  debugMessage $ Msg.currentEncodingIs encoding+                                  debugMessage $ currentEncodingIs encoding                                   unless (isUTF8Locale encoding) $-                                    warnCharset Msg.charsetUtf8MailDiffLocale+                                    warnCharset charsetUtf8MailDiffLocale                                   return mailcharset                                 -- Trust other cases (us-ascii)                                 Just _ -> return mailcharset@@ -424,7 +359,7 @@                  let to = generateEmailToString thetargets                  sendEmailDoc from to thesubject (getCc opts)                                sm_cmd contentAndBundle body >>-                  putInfo opts (Msg.success to (getCc opts))+                  putInfo opts (success to (getCc opts))                  `catch` \e -> do warnMailBody                                   fail $ ioeGetErrorString e @@ -436,7 +371,7 @@                mmapFilePS fn            forM_ [ p | Post p <- thetargets]              (\url -> do-                putInfo opts $ Msg.postingPatch url+                putInfo opts $ postingPatch url                 postUrl url (BC.unpack nbody) "message/rfc822")              `catch` (\(_ :: IOException) -> sendmail)            cleanup opts mailfile@@ -458,18 +393,18 @@ writeBundleToFile opts to_be_sent bundle fname wtds their_name =     do (d,f,_) <- getDescription opts their_name to_be_sent        let putabs a = do writeDocBinFile a (d $$ bundle)-                         putDocLn (Msg.wroteBundle a)+                         putDocLn (wroteBundle a)            putstd = putDoc (d $$ bundle)        useAbsoluteOrStd putabs putstd fname        let to = generateEmailToString wtds-       unless (null to) $ putInfo opts $ Msg.savedButNotSent to+       unless (null to) $ putInfo opts $ savedButNotSent to        cleanup opts f  data WhatToDo     = Post String        -- ^ POST the patch via HTTP     | SendMail String    -- ^ send patch via email -decideOnBehavior :: RepoPatch p => [DarcsFlag] -> Maybe (Repository rt p wR wU wT) -> IO [WhatToDo]+decideOnBehavior :: [DarcsFlag] -> Maybe (Repository rt p wR wU wT) -> IO [WhatToDo] decideOnBehavior opts remote_repo =     case the_targets of     [] -> do wtds <- case remote_repo of@@ -480,20 +415,17 @@     ts -> do announce_recipients ts              return ts     where the_targets = collectTargets opts-          -- the ifdef above is to so that darcs only checks the remote-          -- _darcs/post if we have an implementation of postUrl.  See-          -- our HTTP module for more details           check_post the_remote_repo =                        do p <- ((readPost . BC.unpack) `fmap`-                                fetchFilePS (prefsUrl the_remote_repo++"/post")+                                fetchFilePS (prefsUrl (repoLocation the_remote_repo) ++ "/post")                                 (MaxAge 600)) `catchall` return []                           emails <- who_to_email the_remote_repo                           return (p++emails)           readPost = map parseLine . lines where               parseLine t = maybe (Post t) SendMail $ stripPrefix "mailto:" t-          who_to_email the_remote_repo =+          who_to_email repo =               do email <- (BC.unpack `fmap`-                           fetchFilePS (prefsUrl the_remote_repo++"/email")+                           fetchFilePS (prefsUrl (repoLocation repo) ++ "/email")                                        (MaxAge 600))                           `catchall` return ""                  if '@' `elem` email then return . map SendMail $ lines email@@ -501,18 +433,18 @@           announce_recipients emails =             let pn (SendMail s) = s                 pn (Post p) = p-                msg = Msg.willSendTo (dryRun opts) (map pn emails)-            in if DryRun `elem` opts-            then putInfo opts msg-            else when (null the_targets && isNothing (getOutput opts "")) $-                 putInfo opts msg+                msg = willSendTo (dryRun ? opts) (map pn emails)+            in case dryRun ? opts of+                O.YesDryRun -> putInfo opts msg+                O.NoDryRun  -> when (null the_targets && isNothing (getOutput opts "")) $+                                putInfo opts msg  getTargets :: [WhatToDo] -> IO [WhatToDo]-getTargets [] = fmap ((:[]) . SendMail) $ askUser Msg.promptTarget+getTargets [] = fmap ((:[]) . SendMail) $ askUser promptTarget getTargets wtds = return wtds  collectTargets :: [DarcsFlag] -> [WhatToDo]-collectTargets flags = [ f t | Target t <- flags ] where+collectTargets flags = [ f t | t <- O._to (O.headerFields ? flags) ] where     f url | "http:" `isPrefixOf` url = Post url     f em = SendMail em @@ -521,14 +453,14 @@ getDescription opts their_name patches =     case get_filename of         Just file -> do-                     when (editDescription opts) $ do+                     when (editDescription ? opts) $ do                        when (isNothing $ hasLogfile opts) $                             writeDocBinFile file patchdesc-                       debugMessage $ Msg.aboutToEdit file+                       debugMessage $ aboutToEdit file                        (_, changed) <- editFile file                        unless changed $ do-                         confirmed <- promptYorn Msg.promptNoDescriptionChange-                         unless confirmed $ do putDocLn Msg.aborted+                         confirmed <- promptYorn promptNoDescriptionChange+                         unless confirmed $ do putDocLn aborted                                                exitSuccess                        return ()                      @@ -549,12 +481,168 @@                        return darcsSendMessageFinal) (return . toFilePath) $ hasLogfile opts           get_filename = case hasLogfile opts of                                 Just f -> Just $ toFilePath f-                                Nothing -> if editDescription opts+                                Nothing -> if editDescription ? opts                                               then Just darcsSendMessage                                               else Nothing-          tryGetCharset content = let body = renderPS Standard content in+          tryGetCharset content = let body = renderPS content in                                   if isAscii body                                   then Just "us-ascii"                                   else either (const Nothing)                                               (const $ Just "utf-8")                                               (decodeUtf8' body)++cmdDescription :: String+cmdDescription =+    "Prepare a bundle of patches to be applied to some target repository."++cmdHelp :: String+cmdHelp = unlines+    [ "Send is used to prepare a bundle of patches that can be applied to a target"+    , "repository.  Send accepts the URL of the repository as an argument.  When"+    , "called without an argument, send will use the most recent repository that"+    , "was either pushed to, pulled from or sent to.  By default, the patch bundle"+    , "is saved to a file, although you may directly send it by mail."+    , ""+    , "The `--output`, `--output-auto-name`, and `--to` flags determine"+    , "what darcs does with the patch bundle after creating it.  If you provide an"+    , "`--output` argument, the patch bundle is saved to that file.  If you"+    , "specify `--output-auto-name`, the patch bundle is saved to a file with an"+    , "automatically generated name.  If you give one or more `--to` arguments,"+    , "the bundle of patches is sent to those locations. The locations may either"+    , "be email addresses or urls that the patch should be submitted to via HTTP."+    , ""+    , "If you provide the `--mail` flag, darcs will look at the contents"+    , "of the `_darcs/prefs/email` file in the target repository (if it exists),"+    , "and send the patch by email to that address.  In this case, you may use"+    , "the `--cc` option to specify additional recipients without overriding the"+    , "default repository email address."+    , ""+    , "If `_darcs/prefs/post` exists in the target repository, darcs will"+    , "upload to the URL contained in that file, which may either be a"+    , "`mailto:` URL, or an `http://` URL.  In the latter case, the"+    , "patch is posted to that URL."+    , ""+    , "If there is no email address associated with the repository, darcs will"+    , "prompt you for an email address."+    , ""+    , "Use the `--subject` flag to set the subject of the e-mail to be sent."+    , "If you don't provide a subject on the command line, darcs will make one up"+    , "based on names of the patches in the patch bundle."+    , ""+    , "Use the `--in-reply-to` flag to set the In-Reply-To and References headers"+    , "of the e-mail to be sent. By default no additional headers are included so"+    , "e-mail will not be treated as reply by mail readers."+    , ""+    , "If you want to include a description or explanation along with the bundle"+    , "of patches, you need to specify the `--edit-description` flag, which"+    , "will cause darcs to open up an editor with which you can compose a message"+    , "to go along with your patches."+    , ""+    , "If you want to use a command different from the default one for sending"+    , "email, you need to specify a command line with the `--sendmail-command`"+    , "option. The command line can contain some format specifiers which are"+    , "replaced by the actual values. Accepted format specifiers are `%s` for"+    , "subject, `%t` for to, `%c` for cc, `%b` for the body of the mail, `%f` for"+    , "from, `%a` for the patch bundle and the same specifiers in uppercase for the"+    , "URL-encoded values."+    , "Additionally you can add `%<` to the end of the command line if the command"+    , "expects the complete email message on standard input. E.g. the command lines"+    , "for evolution and msmtp look like this:"+    , ""+    , "    evolution \"mailto:%T?subject=%S&attach=%A&cc=%C&body=%B\""+    , "    msmtp -t %<"+    , ""+    , "Do not confuse the `--author` options with the return address"+    , "that `darcs send` will set for your patch bundle."+    , ""+    , "For example, if you have two email addresses A and B:"+    , ""+    , "* If you use `--author A` but your machine is configured to send mail from"+    , "  address B by default, then the return address on your message will be B."+    , "* If you use `--from A` and your mail client supports setting the"+    , "  From: address arbitrarily (some non-Unix-like mail clients, especially,"+    , "  may not support this), then the return address will be A; if it does"+    , "  not support this, then the return address will be B."+    , "* If you supply neither `--from` nor `--author` then the return"+    , "  address will be B."+    , ""+    , "In addition, unless you specify the sendmail command with"+    , "`--sendmail-command`, darcs sends email using the default email"+    , "command on your computer. This default command is determined by the"+    , "`configure` script. Thus, on some non-Unix-like OSes,"+    , "`--from` is likely to not work at all."+    ]++cannotSendToSelf :: String+cannotSendToSelf = "Can't send to current repository! Did you mean send --context?"++creatingPatch :: String -> Doc+creatingPatch repodir = "Creating patch to" <+> text (quote repodir) <> "..."++noWorkingSendmail :: Doc+noWorkingSendmail = "No working sendmail instance on your machine!"++nothingSendable :: Doc+nothingSendable = "No recorded local changes to send!"++selectionIs :: [Doc] -> Doc+selectionIs descs = text "We have the following patches to send:" $$ vcat descs++selectionIsNull :: Doc+selectionIsNull = text "You don't want to send any patches, and that's fine with me!"++emailBackedUp :: String -> Doc+emailBackedUp mf = sentence $ "Email body left in" <+> text mf++promptCharSetWarning :: String -> String+promptCharSetWarning msg = "Warning: " ++ msg ++ "  Send anyway?"++charsetAborted :: Doc+charsetAborted = "Aborted.  You can specify charset with the --charset option."++charsetCouldNotGuess :: String+charsetCouldNotGuess = "darcs could not guess the charset of your mail."++currentEncodingIs :: String -> String+currentEncodingIs e = "Current locale encoding: " ++ e++charsetUtf8MailDiffLocale :: String+charsetUtf8MailDiffLocale = "your mail is valid UTF-8 but your locale differs."++aborted :: Doc+aborted = "Aborted."++success :: String -> String -> Doc+success to cc = sentence $+    "Successfully sent patch bundle to:" <+> text to <+> copies cc+  where+    copies "" = ""+    copies x  = "and cc'ed" <+> text x++postingPatch :: String -> Doc+postingPatch url = "Posting patch to" <+> text url++wroteBundle :: FilePathLike a => a -> Doc+wroteBundle a = sentence $ "Wrote patch to" <+> text (toFilePath a)++savedButNotSent :: String -> Doc+savedButNotSent to =+        text ("The usual recipent for this bundle is: " ++ to)+    $$  text "To send it automatically, make sure sendmail is working,"+    <+> text "and add 'send mail' to _darcs/prefs/defaults or"+    <+> text " ~/.darcs/defaults"++willSendTo :: DryRun -> [String] -> Doc+willSendTo dr addresses =+    "Patch bundle" <+> will <+> " be sent to:" <+> text (unwords addresses)+  where+    will = case dr of { YesDryRun -> "would"; NoDryRun  -> "will" }++promptTarget :: String+promptTarget = "What is the target email address? "++aboutToEdit :: FilePath -> String+aboutToEdit file = "About to edit file " ++ file++promptNoDescriptionChange :: String+promptNoDescriptionChange = "File content did not change. Continue anyway?"
src/Darcs/UI/Commands/SetPref.hs view
@@ -15,29 +15,27 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.UI.Commands.SetPref ( setpref ) where  import Prelude () import Darcs.Prelude  import System.Exit ( exitWith, ExitCode(..) )-import Control.Monad (when)-import Data.Maybe (fromMaybe)+import Control.Monad ( when )+import Data.Maybe ( fromMaybe )  import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository ) import Darcs.UI.Flags ( DarcsFlag, useCache, dryRun, umask)-import Darcs.UI.Options ( DarcsOption, PrimDarcsOption, odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Options+    ( odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository.Flags ( UpdateWorking (..) ) import Darcs.Repository ( addToPending, withRepoLock, RepoJob(..) ) import Darcs.Patch ( changepref ) import Darcs.Patch.Witnesses.Ordered ( FL(..) )-import Darcs.Repository.Prefs ( getPrefval, changePrefval, )+import Darcs.Repository.Prefs ( getPrefval, changePrefval ) import Darcs.Util.English ( orClauses ) import Darcs.Util.Path ( AbsolutePath )-#include "impossible.h"  -- | A list of all valid preferences for @_darcs/prefs/prefs@. validPrefData :: [(String, String)] -- ^ (name, one line description)@@ -77,28 +75,6 @@  "the repository will always take precedence.  This is considered a\n" ++  "low-priority bug, because preferences are seldom set.\n" -setprefBasicOpts :: PrimDarcsOption (Maybe String)-setprefBasicOpts = O.workingRepoDir--setprefAdvancedOpts :: PrimDarcsOption O.UMask-setprefAdvancedOpts = O.umask--setprefOpts :: DarcsOption a-               (Maybe String-                -> Maybe O.StdCmdAction-                -> Bool-                -> Bool-                -> O.Verbosity-                -> Bool-                -> O.UMask-                -> O.UseCache-                -> Maybe String-                -> Bool-                -> Maybe String-                -> Bool-                -> a)-setprefOpts = setprefBasicOpts `withStdOpts` setprefAdvancedOpts- setpref :: DarcsCommand [DarcsFlag] setpref = DarcsCommand     { commandProgramName = "darcs"@@ -109,7 +85,7 @@     , commandExtraArgHelp = ["<PREF>", "<VALUE>"]     , commandCommand = setprefCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return validPrefs+    , commandCompleteArgs = completeArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc setprefAdvancedOpts     , commandBasicOptions = odesc setprefBasicOpts@@ -117,13 +93,19 @@     , commandCheckOptions = ocheck setprefOpts     , commandParseOptions = onormalise setprefOpts     }+  where+    setprefBasicOpts = O.repoDir+    setprefAdvancedOpts = O.umask+    setprefOpts = setprefBasicOpts `withStdOpts` setprefAdvancedOpts+    completeArgs _ _ [] = return validPrefs+    completeArgs _ _ _args = return []  setprefCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () setprefCmd _ opts [pref,val] =- withRepoLock (dryRun opts) (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+ withRepoLock (dryRun ? opts) (useCache ? opts) YesUpdateWorking (umask ? opts) $ RepoJob $ \repository -> do   when (' ' `elem` pref) $ do     putStrLn $ "'"++pref++-               "' is not a valid preference name:  no spaces allowed!"+               "' is not a valid preference name: no spaces allowed!"     exitWith $ ExitFailure 1   when (pref `notElem` validPrefs) $ do     putStrLn $ "'"++pref++"' is not a valid preference name!"
src/Darcs/UI/Commands/Show.hs view
@@ -21,11 +21,10 @@ import Darcs.Prelude  import Darcs.UI.Commands ( DarcsCommand(..)-                         , normalCommand, hiddenCommand+                         , normalCommand                          , commandAlias, amInRepository                          ) import Darcs.UI.Commands.ShowAuthors ( showAuthors )-import Darcs.UI.Commands.ShowBug ( showBug ) import Darcs.UI.Commands.ShowContents ( showContents ) import Darcs.UI.Commands.ShowDependencies ( showDeps ) import Darcs.UI.Commands.ShowFiles ( showFiles )@@ -51,8 +50,7 @@     , commandDescription = showDescription     , commandPrereq = amInRepository     , commandSubCommands =-      [ hiddenCommand showBug-      , normalCommand showContents+      [ normalCommand showContents       , normalCommand showDeps       , normalCommand showFiles       , normalCommand showIndex
src/Darcs/UI/Commands/ShowAuthors.hs view
@@ -22,32 +22,33 @@ import Prelude () import Darcs.Prelude -import Prelude hiding ( (^), catch )+import Prelude hiding ( (^) )  import Control.Arrow ( (&&&), (***) )-import Control.Exception ( catch, IOException ) import Data.Char ( toLower, isSpace ) import Data.Function ( on ) import Data.List ( isInfixOf, sortBy, groupBy, group, sort ) import Data.Maybe( isJust ) import Data.Ord ( comparing )+import System.IO.Error ( catchIOError ) import Text.ParserCombinators.Parsec hiding ( lower, count, Line ) import Text.ParserCombinators.Parsec.Error import Text.Regex ( Regex, mkRegexWithOpts, matchRegex ) -import Darcs.UI.Flags ( DarcsFlag(Verbose), useCache )-import Darcs.UI.Options ( DarcsOption, oid, odesc, ocheck, onormalise, defaultFlags )-import qualified Darcs.UI.Options.All as O ( workingRepoDir, StdCmdAction, Verbosity, UseCache )+import Darcs.UI.Flags ( DarcsFlag, useCache, verbose )+import Darcs.UI.Options ( oid, odesc, ocheck, onormalise, defaultFlags, (?) )+import qualified Darcs.UI.Options.All as O import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, putWarning, amInRepository )+import Darcs.UI.Completion ( noArgs ) import Darcs.UI.External ( viewDoc ) import Darcs.Patch.PatchInfoAnd ( info ) import Darcs.Patch.Info ( piAuthor )-import Darcs.Patch.Set ( newset2RL )+import Darcs.Patch.Set ( patchSet2RL ) import Darcs.Repository ( readRepo, withRepository, RepoJob(..) ) import Darcs.Patch.Witnesses.Ordered ( mapRL )+import Darcs.Util.Lock ( readTextFile ) import Darcs.Util.Printer ( text ) import Darcs.Util.Path ( AbsolutePath )-import qualified Darcs.Util.Ratified as Ratified ( readFile )  data Spelling = Spelling String String [Regex] -- name, email, regexps type ParsedLine = Maybe Spelling -- Nothing for blank lines@@ -95,24 +96,6 @@  "    John Snagge <snagge@bbc.co.uk>, John, snagge@, js@(si|mit).edu\n" ++  "    Chuck Jones\\, Jr. <chuck@pobox.com>, cj\\+user@example.com\n" -showAuthorsBasicOpts :: DarcsOption a (Maybe String -> a)-showAuthorsBasicOpts = O.workingRepoDir--showAuthorsOpts :: DarcsOption a-                   (Maybe String-                    -> Maybe O.StdCmdAction-                    -> Bool-                    -> Bool-                    -> O.Verbosity-                    -> Bool-                    -> O.UseCache-                    -> Maybe String-                    -> Bool-                    -> Maybe String-                    -> Bool-                    -> a)-showAuthorsOpts = showAuthorsBasicOpts `withStdOpts` oid- showAuthors :: DarcsCommand [DarcsFlag] showAuthors = DarcsCommand     { commandProgramName = "darcs"@@ -123,7 +106,7 @@     , commandExtraArgHelp = []     , commandCommand = authorsCmd     , commandPrereq = amInRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = odesc showAuthorsBasicOpts@@ -131,14 +114,17 @@     , commandCheckOptions = ocheck showAuthorsOpts     , commandParseOptions = onormalise showAuthorsOpts     }+  where+    showAuthorsBasicOpts = O.repoDir+    showAuthorsOpts = showAuthorsBasicOpts `withStdOpts` oid  authorsCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-authorsCmd _ flags _ = withRepository (useCache flags) $ RepoJob $ \repository -> do+authorsCmd _ flags _ = withRepository (useCache ? flags) $ RepoJob $ \repository -> do     patches <- readRepo repository     spellings <- compiledAuthorSpellings flags-    let authors = mapRL (piAuthor . info) $ newset2RL patches+    let authors = mapRL (piAuthor . info) $ patchSet2RL patches     viewDoc $ text $ unlines $-        if Verbose `elem` flags+        if verbose flags             then authors             else rankAuthors spellings authors @@ -177,9 +163,8 @@ compiledAuthorSpellings :: [DarcsFlag] -> IO [Spelling] compiledAuthorSpellings flags = do     let as_file = ".authorspellings"-    contents <- Ratified.readFile -- never unlinked from within darcs-                 as_file `catch` (\(_ :: IOException) -> return "")-    let parse_results = map (parse sentence as_file) $ lines contents+    content_lines <- readTextFile as_file `catchIOError` (const (return []))+    let parse_results = map (parse sentence as_file) content_lines     clean 1 parse_results   where     clean :: Int -> [Either ParseError ParsedLine] -> IO [Spelling]
− src/Darcs/UI/Commands/ShowBug.hs
@@ -1,80 +0,0 @@---  Copyright (C) 2007 Eric Kow------  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.--{-# LANGUAGE CPP #-}--module Darcs.UI.Commands.ShowBug ( showBug ) where--import Prelude ()-import Darcs.Prelude--import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, findRepository )-import Darcs.UI.Flags ( DarcsFlag )-import Darcs.UI.Options ( DarcsOption, oid, odesc, ocheck, onormalise, defaultFlags )-import qualified Darcs.UI.Options.All as O ( workingRepoDir, StdCmdAction, Verbosity, UseCache )-import Darcs.Util.Path ( AbsolutePath )-#include "impossible.h"--showBugDescription :: String-showBugDescription = "Simulate a run-time failure."--showBugHelp :: String-showBugHelp =-  "Show bug can be used to see what darcs would show you if you encountered.\n"-  ++"a bug in darcs.\n"--showBugBasicOpts :: DarcsOption a (Maybe String -> a)-showBugBasicOpts = O.workingRepoDir--showBugOpts :: DarcsOption a-               (Maybe String-                -> Maybe O.StdCmdAction-                -> Bool-                -> Bool-                -> O.Verbosity-                -> Bool-                -> O.UseCache-                -> Maybe String-                -> Bool-                -> Maybe String-                -> Bool-                -> a)--showBugOpts = showBugBasicOpts `withStdOpts` oid--showBug :: DarcsCommand [DarcsFlag]-showBug = DarcsCommand-    { commandProgramName = "darcs"-    , commandName = "bug"-    , commandHelp = showBugHelp-    , commandDescription = showBugDescription-    , commandExtraArgs = 0-    , commandExtraArgHelp = []-    , commandCommand = showBugCmd-    , commandPrereq = findRepository-    , commandGetArgPossibilities = return []-    , commandArgdefaults = nodefaults-    , commandAdvancedOptions = []-    , commandBasicOptions = odesc showBugBasicOpts-    , commandDefaults = defaultFlags showBugOpts-    , commandCheckOptions = ocheck showBugOpts-    , commandParseOptions = onormalise showBugOpts-    }--showBugCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-showBugCmd _ _ _ = bug "This is actually a fake bug in darcs."-
src/Darcs/UI/Commands/ShowContents.hs view
@@ -29,15 +29,10 @@ import qualified Data.ByteString.Lazy as BL  import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, findRepository )+import Darcs.UI.Completion ( noArgs ) import Darcs.UI.Flags ( DarcsFlag, useCache, fixSubPaths )-import Darcs.UI.Options ( DarcsOption, (^), oid, odesc, ocheck, onormalise, defaultFlags, parseFlags )+import Darcs.UI.Options ( (^), oid, odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O-    ( MatchFlag-    , matchUpToOne-    , workingRepoDir-    , StdCmdAction-    , Verbosity-    , UseCache ) import Darcs.Patch.Match ( haveNonrangeMatch ) import Darcs.Repository ( withRepository, RepoJob(..), readRecorded, repoPatchType ) import Darcs.Util.Lock ( withDelayedDir )@@ -55,25 +50,6 @@   "If you give show contents no version arguments, it displays the recorded\n"++   "version of the file(s).\n" -showContentsBasicOpts :: DarcsOption a ([O.MatchFlag] -> Maybe String -> a)-showContentsBasicOpts = O.matchUpToOne ^ O.workingRepoDir--showContentsOpts :: DarcsOption a-                    ([O.MatchFlag]-                     -> Maybe String-                     -> Maybe O.StdCmdAction-                     -> Bool-                     -> Bool-                     -> O.Verbosity-                     -> Bool-                     -> O.UseCache-                     -> Maybe String-                     -> Bool-                     -> Maybe String-                     -> Bool-                     -> a)-showContentsOpts = O.matchUpToOne ^ O.workingRepoDir `withStdOpts` oid- showContents :: DarcsCommand [DarcsFlag] showContents = DarcsCommand     { commandProgramName = "darcs"@@ -84,7 +60,7 @@     , commandExtraArgHelp = ["[FILE]..."]     , commandCommand = showContentsCmd     , commandPrereq = findRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = odesc showContentsBasicOpts@@ -92,13 +68,16 @@     , commandCheckOptions = ocheck showContentsOpts     , commandParseOptions = onormalise showContentsOpts     }+  where+    showContentsBasicOpts = O.matchUpToOne ^ O.repoDir+    showContentsOpts = O.matchUpToOne ^ O.repoDir `withStdOpts` oid  showContentsCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () showContentsCmd _ _ [] = fail "show contents needs at least one argument." showContentsCmd fps opts args = do   floatedPaths <- map (floatPath . toFilePath . sp2fn) `fmap` fixSubPaths fps args   let matchFlags = parseFlags O.matchUpToOne opts-  withRepository (useCache opts) $ RepoJob $ \repository -> do+  withRepository (useCache ? opts) $ RepoJob $ \repository -> do     let readContents = do           okpaths <- filterM TM.fileExists floatedPaths           forM okpaths $ \f -> (B.concat . BL.toChunks) `fmap` TM.readFile f
src/Darcs/UI/Commands/ShowDependencies.hs view
@@ -12,35 +12,28 @@ import Data.Graph.Inductive.PatriciaTree ( Gr )  import qualified Data.Text.Lazy as T-import qualified Data.ByteString.Char8 as BC ( unpack ) -import Darcs.Util.Tree ( Tree )--import Darcs.Repository ( readRepo, withRepositoryDirectory, RepoJob(..) )+import Darcs.Repository ( readRepo, withRepositoryLocation, RepoJob(..) ) import Darcs.UI.Flags ( DarcsFlag(..), getRepourl-                      , useCache, toMatchFlags )-import Darcs.UI.Options ( PrimDarcsOption, oid, odesc, ocheck, onormalise, defaultFlags  )+                      , useCache )+import Darcs.UI.Options ( oid, odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.UI.Commands ( DarcsCommand(..), nodefaults, findRepository, withStdOpts ) import Darcs.UI.Commands.Unrecord ( matchingHead )+import Darcs.UI.Completion ( noArgs )  import Darcs.Util.Text ( formatText ) import Darcs.Util.Path ( AbsolutePath ) -import Darcs.Patch ( RepoPatch )-import Darcs.Patch.Set ( PatchSet(..), newset2FL )-import Darcs.Patch.Info ( _piName )+import Darcs.Patch.Info ( piName ) import Darcs.Patch.PatchInfoAnd ( hopefully )-import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.Named ( Named (..), patch2patchinfo ) import Darcs.Patch.Named.Wrapped ( removeInternalFL ) import Darcs.Patch.Match ( firstMatch, matchFirstPatchset )-import Darcs.Patch.Choices ( lpPatch, LabelledPatch, label, getLabelInt )+import Darcs.Patch.Choices ( unLabel, LabelledPatch, label, getLabelInt ) import Darcs.Patch.Depends ( SPatchAndDeps, getDeps, findCommonWithThem ) import Darcs.Patch.Witnesses.Sealed ( Sealed2(..), seal2, Sealed(..) )-import Darcs.Patch.Witnesses.Ordered ( (:>)(..), (:>)(..), RL(..)-                                     , reverseFL, foldlFL, mapFL_FL )-import Darcs.Repository.Flags ( Verbosity(..), UseCache(..) ) +import Darcs.Patch.Witnesses.Ordered ( (:>)(..), (:>)(..), foldlFL, mapFL_FL )  showDepsDescription :: String showDepsDescription = "Generate the graph of dependencies."@@ -57,25 +50,6 @@         , "darcs show dependencies | dot -Tpdf -o FILE.pdf"         ] -showDepsBasicOpts ::  PrimDarcsOption [O.MatchFlag]-showDepsBasicOpts = O.matchSeveralOrLast--showDepsOpts :: O.DarcsOption-                  a-                  ([O.MatchFlag]-                   -> Maybe O.StdCmdAction-                   -> Bool-                   -> Bool-                   -> Verbosity-                   -> Bool-                   -> UseCache-                   -> Maybe String-                   -> Bool-                   -> Maybe String-                   -> Bool-                   -> a)-showDepsOpts = showDepsBasicOpts `withStdOpts` oid- showDeps :: DarcsCommand [DarcsFlag] showDeps = DarcsCommand     { commandProgramName = "darcs"@@ -86,7 +60,7 @@     , commandExtraArgHelp = []     , commandCommand = depsCmd     , commandPrereq = findRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = odesc showDepsBasicOpts@@ -94,16 +68,18 @@     , commandCheckOptions = ocheck showDepsOpts     , commandParseOptions = onormalise showDepsOpts     }+  where+    showDepsBasicOpts = O.matchSeveralOrLast+    showDepsOpts = showDepsBasicOpts `withStdOpts` oid  type DepsGraph = Gr String ()  depsCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () depsCmd _ opts _ = do     let repodir = fromMaybe "." (getRepourl opts)-    withRepositoryDirectory (useCache opts) repodir $ RepoJob $ \repo -> do-        Sealed2 r <- readRepo repo >>= pruneRepo-        let rFl    = newset2FL r-            deps   = getDeps+    withRepositoryLocation (useCache ? opts) repodir $ RepoJob $ \repo -> do+        Sealed2 rFl <- readRepo repo >>= pruneRepo+        let deps   = getDeps                         (removeInternalFL . mapFL_FL hopefully $ rFl)                         rFl             dGraph = transitiveReduction $@@ -119,29 +95,29 @@                                     , ImageScale UniformScale                                     ]                               }-        pruneRepo r = let matchFlags = toMatchFlags opts in+        pruneRepo r = let matchFlags = O.matchSeveralOrLast ? opts in                       if firstMatch matchFlags                          then case getLastPatches matchFlags r of-                                Sealed2 ps -> return $ seal2 $ PatchSet NilRL ps+                                Sealed2 ps -> return $ seal2 ps                          else case matchingHead matchFlags r of-                                _ :> patches -> return $ seal2 $ PatchSet NilRL $ reverseFL patches+                                _ :> patches -> return $ seal2 patches         getLastPatches matchFlags ps =                 case matchFirstPatchset matchFlags ps of                     Sealed p1s -> case findCommonWithThem ps p1s of-                                    _ :> ps' -> seal2 $ reverseFL ps'+                                    _ :> ps' -> seal2 ps' -makeGraph :: (RepoPatch p,ApplyState p ~ Tree) => [SPatchAndDeps p] -> DepsGraph+makeGraph :: [SPatchAndDeps p] -> DepsGraph makeGraph = uncurry mkGraph . (id *** concat) . unzip . map mkNodeWithEdges     where     mkNodeWithEdges :: SPatchAndDeps p -> (LNode String, [UEdge])     mkNodeWithEdges (Sealed2 father, Sealed2 childs) = (mkLNode father,mkUEdges)         where             mkNode :: LabelledPatch (Named p) wX wY -> Int-            mkNode = fromInteger . getLabelInt . label+            mkNode = getLabelInt . label             mkUEdge :: [UEdge] -> LabelledPatch (Named p) wX wY -> [UEdge]             mkUEdge les child = (mkNode father, mkNode child,()) : les             mkLabel :: LabelledPatch (Named p) wX wY -> String-            mkLabel = formatText 20 . (:[]) . BC.unpack . _piName . patch2patchinfo . lpPatch+            mkLabel = formatText 20 . (:[]) . piName . patch2patchinfo . unLabel             mkLNode :: LabelledPatch (Named p) wX wY -> LNode String             mkLNode p = (mkNode p, mkLabel p)             mkUEdges :: [UEdge]
src/Darcs/UI/Commands/ShowFiles.hs view
@@ -15,18 +15,17 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-} module Darcs.UI.Commands.ShowFiles ( showFiles ) where  import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) ) import Darcs.UI.Flags ( DarcsFlag, useCache )-import Darcs.UI.Options ( DarcsOption, (^), oid, odesc, ocheck, onormalise-                        , defaultFlags, parseFlags )+import Darcs.UI.Options ( (^), oid, odesc, ocheck, onormalise+                        , defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInRepository )+import Darcs.UI.Completion ( knownFileArgs ) import Darcs.Repository ( Repository, withRepository,                           RepoJob(..), repoPatchType ) import Darcs.Patch ( IsRepoType, RepoPatch )@@ -39,7 +38,7 @@  import Data.List( isPrefixOf ) -import Darcs.Patch.Match ( haveNonrangeMatch )+import Darcs.Patch.Match ( haveNonrangeExplicitMatch ) import Darcs.Repository.Match ( getNonrangeMatch ) import Darcs.Util.Lock ( withDelayedDir ) @@ -70,53 +69,33 @@  "\n" ++  "    darcs show files -0 | xargs -0 ls -ldS\n" -showFilesBasicOpts :: DarcsOption a-                      (Bool -> Bool -> Bool -> Bool -> [O.MatchFlag] -> Maybe String -> a)-showFilesBasicOpts-    = O.files-    ^ O.directories-    ^ O.pending-    ^ O.nullFlag-    ^ O.matchUpToOne-    ^ O.workingRepoDir--showFilesOpts :: DarcsOption a-                 (Bool-                  -> Bool-                  -> Bool-                  -> Bool-                  -> [O.MatchFlag]-                  -> Maybe String-                  -> Maybe O.StdCmdAction-                  -> Bool-                  -> Bool-                  -> O.Verbosity-                  -> Bool-                  -> O.UseCache-                  -> Maybe String-                  -> Bool-                  -> Maybe String-                  -> Bool-                  -> a)-showFilesOpts = showFilesBasicOpts `withStdOpts` oid- showFiles :: DarcsCommand [DarcsFlag]-showFiles = DarcsCommand {-  commandProgramName = "darcs",-  commandName = "files",-  commandHelp = showFilesHelp,-  commandDescription = showFilesDescription,-  commandExtraArgs = -1,-  commandExtraArgHelp = ["[FILE or DIRECTORY]..."],-  commandCommand = manifestCmd toListFiles,-  commandPrereq = amInRepository,-  commandGetArgPossibilities = return [],-  commandArgdefaults = nodefaults,-  commandAdvancedOptions = [],-  commandBasicOptions = odesc showFilesBasicOpts,-  commandDefaults = defaultFlags showFilesOpts,-  commandCheckOptions = ocheck showFilesOpts,-  commandParseOptions = onormalise showFilesOpts }+showFiles = DarcsCommand+    { commandProgramName = "darcs"+    , commandName = "files"+    , commandHelp = showFilesHelp+    , commandDescription = showFilesDescription+    , commandExtraArgs = -1+    , commandExtraArgHelp = ["[FILE or DIRECTORY]..."]+    , commandCommand = manifestCmd toListFiles+    , commandPrereq = amInRepository+    , commandCompleteArgs = knownFileArgs+    , commandArgdefaults = nodefaults+    , commandAdvancedOptions = []+    , commandBasicOptions = odesc showFilesBasicOpts+    , commandDefaults = defaultFlags showFilesOpts+    , commandCheckOptions = ocheck showFilesOpts+    , commandParseOptions = onormalise showFilesOpts+    }+  where+    showFilesBasicOpts+      = O.files+      ^ O.directories+      ^ O.pending+      ^ O.nullFlag+      ^ O.matchUpToOne+      ^ O.repoDir+    showFilesOpts = showFilesBasicOpts `withStdOpts` oid  toListFiles :: [DarcsFlag] -> Tree m -> [FilePath] toListFiles    opts = filesDirs (parseFlags O.files opts) (parseFlags O.directories opts)@@ -137,7 +116,7 @@  manifestHelper :: ([DarcsFlag] -> Tree IO -> [FilePath]) -> [DarcsFlag] -> [String] -> IO [FilePath] manifestHelper to_list opts argList = do-    list' <- to_list opts `fmap` withRepository (useCache opts) (RepoJob slurp)+    list' <- to_list opts `fmap` withRepository (useCache ? opts) (RepoJob slurp)     case argList of         []       -> return list'         prefixes -> return (onlysubdirs prefixes list')@@ -146,7 +125,7 @@     slurp :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)           => Repository rt p wR wU wR -> IO (Tree IO)     slurp r = do-      let fUpto = haveNonrangeMatch (repoPatchType r) matchFlags+      let fUpto = haveNonrangeExplicitMatch (repoPatchType r) matchFlags           fPending = parseFlags O.pending opts       -- this covers all 4 possibilities       case (fUpto,fPending) of
src/Darcs/UI/Commands/ShowIndex.hs view
@@ -20,7 +20,6 @@ -- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -- SOFTWARE. -{-# LANGUAGE CPP #-} module Darcs.UI.Commands.ShowIndex     ( showIndex     , showPristineCmd -- for alias@@ -30,9 +29,10 @@ import Darcs.Prelude  import Control.Monad ( (>=>) )-import Darcs.UI.Flags ( DarcsFlag(NullFlag), useCache )+import Darcs.UI.Flags ( DarcsFlag, useCache ) import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInRepository )-import Darcs.UI.Options ( DarcsOption, (^), oid, odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Completion ( noArgs )+import Darcs.UI.Options ( (^), oid, odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository ( withRepository, RepoJob(..), readIndex ) import Darcs.Repository.State ( readRecorded )@@ -44,62 +44,44 @@  import System.Posix.Types ( FileID ) -import qualified Data.ByteString.Char8 as BS+import qualified Data.ByteString.Char8 as BC import Data.Maybe ( fromJust ) import qualified Data.Map as M ( Map, lookup, fromList ) -showIndexBasicOpts :: DarcsOption a-                      (Bool -> Bool -> Bool -> Maybe String -> a)-showIndexBasicOpts = O.files ^ O.directories ^ O.nullFlag ^ O.workingRepoDir--showIndexOpts :: DarcsOption a-                 (Bool-                  -> Bool-                  -> Bool-                  -> Maybe String-                  -> Maybe O.StdCmdAction-                  -> Bool-                  -> Bool-                  -> O.Verbosity-                  -> Bool-                  -> O.UseCache-                  -> Maybe String-                  -> Bool-                  -> Maybe String-                  -> Bool-                  -> a)-showIndexOpts = showIndexBasicOpts `withStdOpts` oid- showIndex :: DarcsCommand [DarcsFlag]-showIndex = DarcsCommand {-  commandProgramName = "darcs",-  commandName = "index",-  commandDescription = "Dump contents of working tree index.",-  commandHelp =-      "The `darcs show index` command lists all version-controlled files and " ++-      "directories along with their hashes as stored in `_darcs/index`. " ++-      "For files, the fields correspond to file size, sha256 of the current " ++-      "file content and the filename.",-  commandExtraArgs = 0,-  commandExtraArgHelp = [],-  commandCommand = showIndexCmd,-  commandPrereq = amInRepository,-  commandGetArgPossibilities = return [],-  commandArgdefaults = nodefaults,-  commandAdvancedOptions = [],-  commandBasicOptions = odesc showIndexBasicOpts,-  commandDefaults = defaultFlags showIndexOpts,-  commandCheckOptions = ocheck showIndexOpts,-  commandParseOptions = onormalise showIndexOpts }+showIndex = DarcsCommand+    { commandProgramName = "darcs"+    , commandName = "index"+    , commandDescription = "Dump contents of working tree index."+    , commandHelp =+        "The `darcs show index` command lists all version-controlled files and " +++        "directories along with their hashes as stored in `_darcs/index`. " +++        "For files, the fields correspond to file size, sha256 of the current " +++        "file content and the filename."+    , commandExtraArgs = 0+    , commandExtraArgHelp = []+    , commandCommand = showIndexCmd+    , commandPrereq = amInRepository+    , commandCompleteArgs = noArgs+    , commandArgdefaults = nodefaults+    , commandAdvancedOptions = []+    , commandBasicOptions = odesc showIndexBasicOpts+    , commandDefaults = defaultFlags showIndexOpts+    , commandCheckOptions = ocheck showIndexOpts+    , commandParseOptions = onormalise showIndexOpts+    }+  where+    showIndexBasicOpts = O.nullFlag ^ O.repoDir+    showIndexOpts = showIndexBasicOpts `withStdOpts` oid  dump :: [DarcsFlag] -> Maybe (M.Map FilePath FileID) -> Tree IO -> IO () dump opts fileids tree = do-  let line | NullFlag `elem` opts = \t -> putStr t >> putChar '\0'+  let line | O.nullFlag ? opts = \t -> putStr t >> putChar '\0'            | otherwise = putStrLn       output (p, i) = do         let hash = case itemHash i of                      NoHash -> "(no hash available)"-                     h -> BS.unpack $ encodeBase16 h+                     h -> BC.unpack $ encodeBase16 h             path = anchorPath "" p             isdir = case i of                       SubTree _ -> "/"@@ -112,13 +94,13 @@   mapM_ output $ (floatPath ".", SubTree x) : list x  showIndexCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-showIndexCmd _ opts _ = withRepository (useCache opts) $ RepoJob $ \repo ->+showIndexCmd _ opts _ = withRepository (useCache ? opts) $ RepoJob $ \repo ->   do index <- readIndex repo      index_tree <- updateIndex index      fileids <- (M.fromList . map (\((a,_),b) -> (anchorPath "" a,b))) <$> listFileIDs index      dump opts (Just fileids) index_tree  showPristineCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-showPristineCmd _ opts _ = withRepository (useCache opts) $ RepoJob $+showPristineCmd _ opts _ = withRepository (useCache ? opts) $ RepoJob $   readRecorded >=> dump opts Nothing 
src/Darcs/UI/Commands/ShowPatchIndex.hs view
@@ -3,67 +3,51 @@ import Prelude () import Darcs.Prelude -import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository )-import Darcs.UI.Flags ( DarcsFlag(Verbose), useCache )+import Darcs.UI.Commands+    ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository )+import Darcs.UI.Completion ( noArgs )+import Darcs.UI.Flags ( DarcsFlag, useCache, verbose ) import Prelude hiding ( (^) )-import Darcs.UI.Options ( DarcsOption, (^), oid, odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Options+    ( (^), oid, odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Util.Path ( AbsolutePath )-import Darcs.Repository.InternalTypes ( Repository(..) )-import Darcs.Repository ( withRepository, RepoJob(..) )+import Darcs.Repository ( withRepository, RepoJob(..), repoLocation ) import Darcs.Repository.PatchIndex-import Control.Arrow ()--showPatchIndexBasicOpts :: DarcsOption a-                           (Bool -> Bool -> Bool -> Maybe String -> a)-showPatchIndexBasicOpts = O.files ^ O.directories ^ O.nullFlag ^ O.workingRepoDir--showPatchIndexOpts :: DarcsOption a-                      (Bool-                       -> Bool-                       -> Bool-                       -> Maybe String-                       -> Maybe O.StdCmdAction-                       -> Bool-                       -> Bool-                       -> O.Verbosity-                       -> Bool-                       -> O.UseCache-                       -> Maybe String-                       -> Bool-                       -> Maybe String-                       -> Bool-                       -> a)-showPatchIndexOpts = showPatchIndexBasicOpts `withStdOpts` oid+    ( dumpPatchIndex, piTest, doesPatchIndexExist, isPatchIndexInSync)  showPatchIndex :: DarcsCommand [DarcsFlag]-showPatchIndex = DarcsCommand {-  commandProgramName = "darcs",-  commandName = "patch-index",-  commandDescription = "Check integrity of patch index",-  commandHelp =-      "When given the `--verbose` flag, the command dumps the complete content\n"-   ++ "of the patch index and checks its integrity.",-  commandExtraArgs = 0,-  commandExtraArgHelp = [],-  commandCommand = showPatchIndexCmd,-  commandPrereq = amInHashedRepository,-  commandGetArgPossibilities = return [],-  commandArgdefaults = nodefaults,-  commandAdvancedOptions = [],-  commandBasicOptions = odesc showPatchIndexBasicOpts,-  commandDefaults = defaultFlags showPatchIndexOpts,-  commandCheckOptions = ocheck showPatchIndexOpts,-  commandParseOptions = onormalise showPatchIndexOpts }+showPatchIndex = DarcsCommand+    { commandProgramName = "darcs"+    , commandName = "patch-index"+    , commandDescription = "Check integrity of patch index"+    , commandHelp =+        "When given the `--verbose` flag, the command dumps the complete content\n" +++        "of the patch index and checks its integrity."+    , commandExtraArgs = 0+    , commandExtraArgHelp = []+    , commandCommand = showPatchIndexCmd+    , commandPrereq = amInHashedRepository+    , commandCompleteArgs = noArgs+    , commandArgdefaults = nodefaults+    , commandAdvancedOptions = []+    , commandBasicOptions = odesc showPatchIndexBasicOpts+    , commandDefaults = defaultFlags showPatchIndexOpts+    , commandCheckOptions = ocheck showPatchIndexOpts+    , commandParseOptions = onormalise showPatchIndexOpts+    }+  where+    showPatchIndexBasicOpts = O.nullFlag ^ O.repoDir+    showPatchIndexOpts = showPatchIndexBasicOpts `withStdOpts` oid  showPatchIndexCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () showPatchIndexCmd _ opts _-  | Verbose `elem` opts = do-    withRepository (useCache opts) $ RepoJob $ \repo@(Repo repodir _ _ _) ->-      dumpPatchIndex repodir >> piTest repo+  | verbose opts =+    withRepository (useCache ? opts) $ RepoJob $ \repo ->+      let loc = repoLocation repo in dumpPatchIndex loc >> piTest loc   | otherwise =-    withRepository (useCache opts) $ RepoJob $ \(repo@(Repo repodir _ _ _)) -> do-    ex <- doesPatchIndexExist repodir+    withRepository (useCache ? opts) $ RepoJob $ \repo -> do+    ex <- doesPatchIndexExist (repoLocation repo)     if ex then do           sy <- isPatchIndexInSync repo           if sy
src/Darcs/UI/Commands/ShowRepo.hs view
@@ -15,31 +15,35 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-} module Darcs.UI.Commands.ShowRepo ( showRepo ) where  import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) ) import Data.Char ( toLower, isSpace ) import Data.List ( intercalate ) import Control.Monad ( when, unless, liftM ) import Text.Html ( tag, stringToHtml ) import Darcs.Util.Path ( AbsolutePath )-import Darcs.UI.Flags ( DarcsFlag(XMLOutput, Verbose, NoFiles), useCache )-import Darcs.UI.Options ( DarcsOption, (^), oid, odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Flags ( DarcsFlag, useCache, hasXmlOutput, verbose, enumeratePatches )+import Darcs.UI.Options ( (^), oid, odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInRepository )-import Darcs.Repository ( withRepository, RepoJob(..), readRepo )-import Darcs.Repository.Internal ( Repository(..), repoXor )-import Darcs.Repository.InternalTypes ( Pristine(..) )-import Darcs.Repository.Cache ( Cache(..) )-import Darcs.Repository.Format ( RepoFormat(..) )-import Darcs.Repository.Prefs ( getPreflist )-import Darcs.Repository.Motd ( getMotd )+import Darcs.UI.Completion ( noArgs )+import Darcs.Repository+    ( Repository+    , repoFormat+    , repoLocation+    , repoPristineType+    , repoCache+    , withRepository+    , RepoJob(..)+    , readRepo )+import Darcs.Repository.Hashed( repoXor )+import Darcs.Repository.PatchIndex ( isPatchIndexDisabled, doesPatchIndexExist )+import Darcs.Repository.Prefs ( getPreflist, getMotd ) import Darcs.Patch ( IsRepoType, RepoPatch )-import Darcs.Patch.Set ( newset2RL )+import Darcs.Patch.Set ( patchSet2RL ) import Darcs.Patch.Witnesses.Ordered ( lengthRL ) import qualified Data.ByteString.Char8 as BC  (unpack) import Darcs.Patch.Apply( ApplyState )@@ -52,39 +56,21 @@  "without inspecting `_darcs` directly (and without breaking when the\n" ++  "`_darcs` format changes).\n" ++  "\n" ++- "By default, the number of patches is shown.  If this data isn't\n" ++- "needed, use `--no-files` to accelerate this command from O(n) to O(1).\n" ++- "\n" ++  "The 'Weak Hash' identifies the set of patches of a repository independently\n" ++  "of ordering. It can be used to easily compare two repositories of a same\n" ++  "project. It is not cryptographically secure.\n" ++  "\n" +++ "By default, output includes statistics that require walking through the patches\n" +++ "recorded in the repository, namely the 'Weak Hash' and the count of patches.\n" +++ "If this data isn't needed, use `--no-enum-patches` to accelerate this command\n" +++ "from O(n) to O(1).\n" +++ "\n" ++  "By default, output is in a human-readable format.  The `--xml-output`\n" ++  "option can be used to generate output for machine postprocessing.\n"  showRepoDescription :: String showRepoDescription = "Show repository summary information" -showRepoBasicOpts :: DarcsOption a (Maybe String -> Bool -> O.XmlOutput -> a)-showRepoBasicOpts = O.workingRepoDir ^ O.files ^ O.xmloutput--showRepoOpts :: DarcsOption a-                (Maybe String-                 -> Bool-                 -> O.XmlOutput-                 -> Maybe O.StdCmdAction-                 -> Bool-                 -> Bool-                 -> O.Verbosity-                 -> Bool-                 -> O.UseCache-                 -> Maybe String-                 -> Bool-                 -> Maybe String-                 -> Bool-                 -> a)-showRepoOpts = showRepoBasicOpts `withStdOpts` oid- showRepo :: DarcsCommand [DarcsFlag] showRepo = DarcsCommand     { commandProgramName = "darcs"@@ -95,7 +81,7 @@     , commandExtraArgHelp = []     , commandCommand = repoCmd     , commandPrereq = amInRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = odesc showRepoBasicOpts@@ -103,10 +89,16 @@     , commandCheckOptions = ocheck showRepoOpts     , commandParseOptions = onormalise showRepoOpts     }+  where+    showRepoBasicOpts = O.repoDir ^ O.xmlOutput ^ O.enumPatches+    showRepoOpts = showRepoBasicOpts `withStdOpts` oid  repoCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO ()-repoCmd _ opts _ = let put_mode = if XMLOutput `elem` opts then showInfoXML else showInfoUsr-                    in withRepository (useCache opts) $ RepoJob $ \repository -> actuallyShowRepo (putInfo put_mode) repository opts+repoCmd _ opts _ =+  let put_mode = if hasXmlOutput opts then showInfoXML else showInfoUsr+  in withRepository (useCache ? opts) $+     RepoJob $ \repository ->+       actuallyShowRepo (putInfo put_mode) repository opts  -- Some convenience functions to output a labelled text string or an -- XML tag + value (same API).  If no value, output is suppressed@@ -123,11 +115,11 @@ safeTag ('#':cs) = "num_" ++ safeTag cs safeTag (c:cs) = toLower c : safeTag cs --- labelled strings: labels are right-aligned at 14 characters;+-- labelled strings: labels are right-aligned at 15 characters; -- subsequent lines in multi-line output are indented accordingly. showInfoUsr :: ShowInfo-showInfoUsr t i = replicate (14 - length t) ' ' ++ t ++ ": " ++-                  intercalate ('\n' : replicate 16 ' ') (lines i) ++ "\n"+showInfoUsr t i = replicate (15 - length t) ' ' ++ t ++ ": " +++                  intercalate ('\n' : replicate 17 ' ') (lines i) ++ "\n"  type PutInfo = String -> String -> IO () putInfo :: ShowInfo -> PutInfo@@ -137,19 +129,29 @@ -- sub-displays.  The `out' argument is one of the above operations to -- output a labelled text string or an XML tag and contained value. -actuallyShowRepo :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                 => PutInfo -> Repository rt p wR wU wR -> [DarcsFlag] -> IO ()-actuallyShowRepo out r@(Repo loc rf pris cs) opts = do-         when (XMLOutput `elem` opts) (putStr "<repository>\n")-         when (Verbose `elem` opts) (out "Show" $ show r)-         showRepoFormat out rf-         out "Root" loc-         showRepoAux out pris cs-         showRepoPrefs out-         unless (NoFiles `elem` opts) (numPatches r >>= (out "Num Patches" . show ))-         unless (NoFiles `elem` opts) (showXor out r)-         showRepoMOTD out r-         when (XMLOutput `elem` opts) (putStr "</repository>\n")+actuallyShowRepo+  :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+  => PutInfo -> Repository rt p wR wU wR -> [DarcsFlag] -> IO ()+actuallyShowRepo out r opts = do+  when (hasXmlOutput opts) (putStr "<repository>\n")+  when (verbose opts) (out "Show" $ show r)+  out "Format" $ showInOneLine $ repoFormat r+  let loc = repoLocation r+  out "Root" loc+  out "PristineType" $ show $ repoPristineType r+  out "Cache" $ showInOneLine $ repoCache r+  piExists <- doesPatchIndexExist loc+  piDisabled <- isPatchIndexDisabled loc+  out "PatchIndex" $+    case (piExists, piDisabled) of+      (_, True) -> "disabled"+      (True, False) -> "enabled"+      (False, False) -> "enabled, but not yet created"+  showRepoPrefs out+  when (enumeratePatches opts) (do numPatches r >>= (out "Num Patches" . show)+                                   showXor out r)+  showRepoMOTD out r+  when (hasXmlOutput opts) (putStr "</repository>\n")  showXor :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)         => PutInfo -> Repository rt p wR wU wR -> IO ()@@ -162,14 +164,8 @@ -- the routines below work to provide more human-readable information -- regarding the repository elements. -showRepoFormat :: PutInfo -> RepoFormat -> IO ()-showRepoFormat out rf = out "Format" . intercalate ", " . lines . show $ rf--showRepoAux :: PutInfo -> Pristine -> Cache -> IO ()-showRepoAux out pris cs =-    do out "Pristine" $ show pris-       out "Cache" $ intercalate ", " $ lines $ show cs-+showInOneLine :: Show a => a -> String+showInOneLine = intercalate ", " . lines . show  showRepoPrefs :: PutInfo -> IO () showRepoPrefs out = do@@ -179,10 +175,9 @@   where prefOut = uncurry out . (\(p,v) -> (p++" Pref", dropWhile isSpace v)) . break isSpace  showRepoMOTD :: RepoPatch p => PutInfo -> Repository rt p wR wU wR -> IO ()-showRepoMOTD out (Repo loc _ _ _) = getMotd loc >>= out "MOTD" . BC.unpack+showRepoMOTD out repo = getMotd (repoLocation repo) >>= out "MOTD" . BC.unpack  -- Support routines to provide information used by the PutInfo operations above.  numPatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree) => Repository rt p wR wU wR -> IO Int-numPatches r = (lengthRL . newset2RL) `liftM` readRepo r-+numPatches r = (lengthRL . patchSet2RL) `liftM` readRepo r
src/Darcs/UI/Commands/ShowTags.hs view
@@ -27,14 +27,12 @@ import System.IO ( stderr, hPutStrLn )  import Darcs.Patch.Set ( PatchSet(..) )-import Darcs.Repository ( readRepo, withRepositoryDirectory, RepoJob(..) )+import Darcs.Repository ( readRepo, withRepositoryLocation, RepoJob(..) ) import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, findRepository )-import Darcs.UI.Commands.Tag ( getTags )+import Darcs.UI.Commands.Util ( repoTags )+import Darcs.UI.Completion ( noArgs ) import Darcs.UI.Flags ( DarcsFlag, useCache, getRepourl )-import Darcs.UI.Options-    ( DarcsOption, PrimDarcsOption-    , oid, odesc, ocheck, onormalise, defaultFlags-    )+import Darcs.UI.Options ( oid, odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Util.Text ( formatText ) import Darcs.Util.Path ( AbsolutePath )@@ -51,24 +49,6 @@       ++ "if this happens."     ] -showTagsBasicOpts :: PrimDarcsOption (Maybe String)-showTagsBasicOpts = O.possiblyRemoteRepo--showTagsOpts :: DarcsOption a-                (Maybe String-                 -> Maybe O.StdCmdAction-                 -> Bool-                 -> Bool-                 -> O.Verbosity-                 -> Bool-                 -> O.UseCache-                 -> Maybe String-                 -> Bool-                 -> Maybe String-                 -> Bool-                 -> a)-showTagsOpts = showTagsBasicOpts `withStdOpts` oid- showTags :: DarcsCommand [DarcsFlag] showTags = DarcsCommand     { commandProgramName = "darcs"@@ -79,7 +59,7 @@     , commandExtraArgHelp = []     , commandCommand = tagsCmd     , commandPrereq = findRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = []     , commandBasicOptions = odesc showTagsBasicOpts@@ -87,14 +67,17 @@     , commandCheckOptions = ocheck showTagsOpts     , commandParseOptions = onormalise showTagsOpts     }+  where+    showTagsBasicOpts = O.possiblyRemoteRepo+    showTagsOpts = showTagsBasicOpts `withStdOpts` oid  tagsCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () tagsCmd _ opts _ = let repodir = fromMaybe "." (getRepourl opts) in-    withRepositoryDirectory (useCache opts) repodir $ RepoJob $ \repo ->+    withRepositoryLocation (useCache ? opts) repodir $ RepoJob $ \repo ->         readRepo repo >>= printTags   where     printTags :: PatchSet rt p wW wZ -> IO ()-    printTags = join . fmap (sequence_ . map process) . getTags+    printTags = join . fmap (sequence_ . map process) . repoTags     process :: String -> IO ()     process t = normalize t t False >>= putStrLn     normalize :: String -> String -> Bool -> IO String
src/Darcs/UI/Commands/Tag.hs view
@@ -15,37 +15,45 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -module Darcs.UI.Commands.Tag ( tag, getTags ) where+module Darcs.UI.Commands.Tag ( tag ) where  import Prelude () import Darcs.Prelude  import Control.Monad ( when )-import Data.Maybe ( catMaybes )+import System.IO ( hPutStr, stderr ) -import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository )-import Darcs.UI.Flags-    ( DarcsFlag(AskDeps), getDate, compression, verbosity, useCache, umask, getAuthor-    , hasAuthor )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags, parseFlags )-import qualified Darcs.UI.Options.All as O-import Darcs.UI.PatchHeader ( getLog )-import Darcs.Patch.PatchInfoAnd ( n2pia, hopefully )-import Darcs.Repository ( withRepoLock, Repository, RepoJob(..), readRepo,-                    tentativelyAddPatch, finalizeRepositoryChanges,-                  )+import Darcs.Patch.Apply ( ApplyState )+import Darcs.Patch.Info ( patchinfo )+import Darcs.Patch.Depends ( getUncovered ) import Darcs.Patch-    ( Patchy, PrimPatch, PrimOf+    ( PrimPatch, PrimOf     , IsRepoType, RepoPatch     )-import Darcs.Patch.Apply ( ApplyState )-import Darcs.Patch.Info ( patchinfo, piTag )-import Darcs.Patch.Depends ( getUncovered )-import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, info )-import Darcs.Patch.Named.Wrapped ( infopatch, adddeps, runInternalChecker, namedInternalChecker )-import Darcs.Patch.Set ( PatchSet(..), emptyPatchSet, appendPSFL, newset2FL, patchSetfMap )+import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, n2pia, hopefully )+import Darcs.Patch.Named.Wrapped+    ( infopatch, adddeps, runInternalChecker, namedInternalChecker )+import Darcs.Patch.Set+    ( PatchSet(..), emptyPatchSet, appendPSFL, patchSet2FL ) import Darcs.Patch.Witnesses.Ordered ( FL(..), filterOutRLRL, (:>)(..) ) import Darcs.Patch.Witnesses.Sealed ( Sealed(..), mapSeal )++import Darcs.Repository+    ( withRepoLock, Repository, RepoJob(..), readRepo+    , tentativelyAddPatch, finalizeRepositoryChanges,+    )+import Darcs.Repository.Flags ( UpdateWorking(..), DryRun(NoDryRun) )++import Darcs.UI.Commands+    ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository )+import Darcs.UI.Commands.Util ( repoTags )+import Darcs.UI.Completion ( noArgs )+import Darcs.UI.Flags+    ( DarcsFlag, getDate, compress, verbosity, useCache, umask, getAuthor, author )+import Darcs.UI.Options+    ( (^), odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) )+import qualified Darcs.UI.Options.All as O+import Darcs.UI.PatchHeader ( getLog ) import Darcs.UI.SelectChanges     ( WhichChanges(..)     , selectionContext@@ -53,12 +61,10 @@     , PatchSelectionContext(allowSkipAll)     ) import qualified Darcs.UI.SelectChanges as S-import Darcs.Repository.Flags ( UpdateWorking(..), DryRun(NoDryRun) )-import Darcs.Util.Path ( AbsolutePath ) +import Darcs.Util.Path ( AbsolutePath ) import Darcs.Util.Tree( Tree ) -import System.IO ( hPutStr, stderr )  tagDescription :: String tagDescription = "Name the current repository state for future reference."@@ -91,47 +97,6 @@  "The `darcs tag` command accepts the `--pipe` option, which behaves as\n" ++  "described in `darcs record`.\n" -tagBasicOpts :: DarcsOption a-                (Maybe String-                 -> Maybe String-                 -> Bool-                 -> Maybe O.AskLongComment-                 -> Bool-                 -> Maybe String-                 -> a)-tagBasicOpts-    = O.patchname-    ^ O.author-    ^ O.pipe-    ^ O.askLongComment-    ^ O.askdeps-    ^ O.workingRepoDir--tagAdvancedOpts :: DarcsOption a (O.Compression -> O.UMask -> a)-tagAdvancedOpts = O.compress ^ O.umask--tagOpts :: DarcsOption a-           (Maybe String-            -> Maybe String-            -> Bool-            -> Maybe O.AskLongComment-            -> Bool-            -> Maybe String-            -> Maybe O.StdCmdAction-            -> Bool-            -> Bool-            -> O.Verbosity-            -> Bool-            -> O.Compression-            -> O.UMask-            -> O.UseCache-            -> Maybe String-            -> Bool-            -> Maybe String-            -> Bool-            -> a)-tagOpts = tagBasicOpts `withStdOpts` tagAdvancedOpts- tag :: DarcsCommand [DarcsFlag] tag = DarcsCommand     { commandProgramName = "darcs"@@ -142,7 +107,7 @@     , commandExtraArgHelp = ["[TAGNAME]"]     , commandCommand = tagCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc tagAdvancedOpts     , commandBasicOptions = odesc tagBasicOpts@@ -150,6 +115,16 @@     , commandCheckOptions = ocheck tagOpts     , commandParseOptions = onormalise tagOpts     }+  where+    tagBasicOpts+      = O.patchname+      ^ O.author+      ^ O.pipe+      ^ O.askLongComment+      ^ O.askDeps+      ^ O.repoDir+    tagAdvancedOpts = O.compress ^ O.umask+    tagOpts = tagBasicOpts `withStdOpts` tagAdvancedOpts  filterNonInternal :: IsRepoType rt => PatchSet rt p wX wY -> PatchSet rt p wX wY filterNonInternal =@@ -159,25 +134,25 @@  tagCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () tagCmd _ opts args =-  withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \(repository :: Repository rt p wR wU wR) -> do+  withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $ RepoJob $ \(repository :: Repository rt p wR wU wR) -> do     date <- getDate (hasPipe opts)-    the_author <- getAuthor (hasAuthor opts) (hasPipe opts)+    the_author <- getAuthor (author ? opts) (hasPipe opts)     patches <- readRepo repository-    tags <- getTags patches+    tags <- repoTags patches     let nonInternalPatches = filterNonInternal patches     Sealed chosenPatches <--        if AskDeps `elem` opts-            then mapSeal (appendPSFL emptyPatchSet) <$> askAboutTagDepends opts (newset2FL nonInternalPatches)+        if O.askDeps ? opts+            then mapSeal (appendPSFL emptyPatchSet) <$> askAboutTagDepends opts (patchSet2FL nonInternalPatches)             else return $ Sealed nonInternalPatches     let deps = getUncovered chosenPatches     (name, long_comment)  <- get_name_log (NilFL :: FL (PrimOf p) wA wA) args tags     myinfo <- patchinfo date name the_author long_comment     let mypatch = infopatch myinfo NilFL-    _ <- tentativelyAddPatch repository (compression opts) (verbosity opts) YesUpdateWorking+    _ <- tentativelyAddPatch repository (compress ? opts) (verbosity ? opts) YesUpdateWorking              $ n2pia $ adddeps mypatch deps-    finalizeRepositoryChanges repository YesUpdateWorking (compression opts)+    finalizeRepositoryChanges repository YesUpdateWorking (compress ? opts)     putStrLn $ "Finished tagging patch '"++name++"'"-  where  get_name_log ::(Patchy prim, PrimPatch prim) => FL prim wA wA -> [String] -> [String] -> IO (String, [String])+  where  get_name_log ::(PrimPatch prim) => FL prim wA wA -> [String] -> [String] -> IO (String, [String])          get_name_log nilFL a tags                           = do (name, comment, _) <- getLog                                   (case parseFlags O.patchname opts of@@ -196,9 +171,6 @@                                              " already exists."                                return ("TAG " ++ name, comment) -getTags :: PatchSet rt p wW wR -> IO [String]-getTags ps = catMaybes `fmap` patchSetfMap (return . piTag . info) ps- -- This may be useful for developers, but users don't care about -- internals: --@@ -217,7 +189,7 @@      -> IO (Sealed (FL (PatchInfoAnd rt p) wX)) askAboutTagDepends flags ps = do   let opts = S.PatchSelectionOptions-             { S.verbosity = verbosity flags+             { S.verbosity = verbosity ? flags              , S.matchFlags = []              , S.interactive = True              , S.selectDeps = O.PromptDeps
src/Darcs/UI/Commands/Test.hs view
@@ -37,14 +37,9 @@     , nodefaults     , putInfo     , amInHashedRepository )-import Darcs.UI.Flags ( DarcsFlag( SetScriptsExecutable-                                  , Linear-                                  , Backoff-                                  , Bisect-                                  , LeaveTestDir-                                  )-                      , useCache, verbosity )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Completion ( noArgs )+import Darcs.UI.Flags ( DarcsFlag, useCache, verbosity )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Patch.PatchInfoAnd ( hopefully ) import Darcs.Repository (@@ -66,24 +61,17 @@     , mapFL     , mapRL_RL     )-import Darcs.Patch.Conflict ( Conflict )-import Darcs.Patch.FileHunk ( IsHunk ) import Darcs.Patch.ApplyMonad ( ApplyMonad )-import Darcs.Patch.Apply ( ApplyState )-import Darcs.Patch.Format ( PatchListFormat )+import Darcs.Patch.Apply ( Apply, ApplyState ) import Darcs.Patch.Inspect ( PatchInspect )-import Darcs.Patch.Patchy ( Patchy-                          , Invert-                          , Apply-                          , ShowPatch-                          )+import Darcs.Patch.Invert ( Invert ) import Darcs.Patch ( RepoPatch                    , apply                    , description                    , invert                    ) import Darcs.Patch.Named.Wrapped ( WrappedNamed )-import Darcs.Patch.Set ( newset2RL )+import Darcs.Patch.Set ( patchSet2RL ) import Darcs.Util.Printer ( putDocLn                , text                )@@ -131,31 +119,6 @@   ,"break the test is found at random."  ] -testBasicOpts :: DarcsOption a-                 (O.TestStrategy -> O.LeaveTestDir -> Maybe String -> a)-testBasicOpts = O.testStrategy ^ O.leaveTestDir ^ O.workingRepoDir--testAdvancedOpts :: DarcsOption a (O.SetScriptsExecutable -> a)-testAdvancedOpts = O.setScriptsExecutable--testOpts :: DarcsOption a-            (O.TestStrategy-             -> O.LeaveTestDir-             -> Maybe String-             -> Maybe O.StdCmdAction-             -> Bool-             -> Bool-             -> O.Verbosity-             -> Bool-             -> O.SetScriptsExecutable-             -> O.UseCache-             -> Maybe String-             -> Bool-             -> Maybe String-             -> Bool-             -> a)-testOpts = testBasicOpts `withStdOpts` testAdvancedOpts- test :: DarcsCommand [DarcsFlag] test = DarcsCommand     { commandProgramName = "darcs"@@ -166,7 +129,7 @@     , commandExtraArgHelp = ["[[INITIALIZATION]", "COMMAND]"]     , commandCommand = testCommand     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc testAdvancedOpts     , commandBasicOptions = odesc testBasicOpts@@ -174,6 +137,10 @@     , commandCheckOptions = ocheck testOpts     , commandParseOptions = onormalise testOpts     }+  where+    testBasicOpts = O.testStrategy ^ O.leaveTestDir ^ O.repoDir+    testAdvancedOpts = O.setScriptsExecutable+    testOpts = testBasicOpts `withStdOpts` testAdvancedOpts  -- | Functions defining a strategy for executing a test type Strategy = forall rt p wX wY@@ -186,11 +153,11 @@  testCommand :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () testCommand _ opts args =- withRepository (useCache opts) $ RepoJob $ \repository -> do+ withRepository (useCache ? opts) $ RepoJob $ \repository -> do   patches <- readRepo repository   (init,testCmd) <- case args of     [] ->-      do t <- getTest (verbosity opts)+      do t <- getTest (verbosity ? opts)          return (return ExitSuccess, t)     [cmd] ->       do putStrLn $ "Using test command:\n"++cmd@@ -200,21 +167,22 @@          putStrLn $ "Using test command:\n"++cmd          return (system init, system cmd)     _ -> fail "Test expects zero to two arguments."-  let wd = if LeaveTestDir `elem` opts then withPermDir else withTempDir+  let wd = case O.leaveTestDir ? opts of+            O.YesLeaveTestDir -> withPermDir+            O.NoLeaveTestDir -> withTempDir   withRecorded repository (wd "testing") $ \_ -> do-    when (SetScriptsExecutable `elem` opts) setScriptsExecutable+    when (O.yes (O.setScriptsExecutable ? opts)) setScriptsExecutable     _ <- init     putInfo opts $ text "Running test...\n"     testResult <- testCmd-    let track = chooseStrategy opts-    track opts testCmd testResult (mapRL_RL hopefully . newset2RL $ patches)+    let track = chooseStrategy (O.testStrategy ? opts)+    track opts testCmd testResult (mapRL_RL hopefully . patchSet2RL $ patches) -chooseStrategy :: [DarcsFlag] -> Strategy-chooseStrategy opts-    | Bisect `elem` opts = trackBisect-    | Linear `elem` opts = trackLinear-    | Backoff `elem` opts = trackBackoff-    | otherwise = oneTest+chooseStrategy :: O.TestStrategy -> Strategy+chooseStrategy O.Bisect = trackBisect+chooseStrategy O.Linear = trackLinear+chooseStrategy O.Backoff = trackBackoff+chooseStrategy O.Once = oneTest  -- | test only the last recorded state oneTest :: Strategy@@ -229,7 +197,7 @@ trackLinear opts testCmd (ExitFailure _) (ps:<:p) = do     let ip = invert p     safeApply ip-    when (SetScriptsExecutable `elem` opts) $ setScriptsExecutablePatches ip+    when (O.yes (O.setScriptsExecutable ? opts)) $ setScriptsExecutablePatches ip     putStrLn "Trying without the patch:"     putDocLn $ description ip     hFlush stdout@@ -260,7 +228,7 @@     case splitAtRL n ahead of         ( ahead' :> skipped' ) -> do             unapplyRL skipped'-            when (SetScriptsExecutable `elem` opts) $ setScriptsExecutablePatches skipped'+            when (O.yes (O.setScriptsExecutable ? opts)) $ setScriptsExecutablePatches skipped'             testResult <- testCmd             case testResult of                 ExitFailure _ ->@@ -300,13 +268,13 @@ type BisectState = (Int, Int)  -- | Create Bisect PatchTree from the RL-patchTreeFromRL :: (Patchy p) => RL p wX wY -> PatchTree p wX wY+patchTreeFromRL :: RL p wX wY -> PatchTree p wX wY patchTreeFromRL (NilRL :<: l) = Leaf l patchTreeFromRL xs = case splitAtRL (lengthRL xs `div` 2) xs of                        (r :> l) -> Fork (patchTreeFromRL l) (patchTreeFromRL r)  -- | Convert PatchTree back to RL-patchTree2RL :: (Patchy p) => PatchTree p wX wY -> RL p wX wY+patchTree2RL :: PatchTree p wX wY -> RL p wX wY patchTree2RL (Leaf p)   = NilRL :<: p patchTree2RL (Fork l r) = patchTree2RL r +<+ patchTree2RL l @@ -334,31 +302,29 @@   putStrLn "Last recent patch that fails the test (assuming monotony in the given range):"   putDocLn (description p) -jumpHalfOnRight :: (IsHunk p, Conflict p,-                    PatchListFormat p, ShowPatch p, PatchInspect p,-                    Patchy p, ApplyMonad (ApplyState p) DefaultIO)+jumpHalfOnRight :: (Invert p, Apply p, PatchInspect p,+                    ApplyMonad (ApplyState p) DefaultIO)                 => [DarcsFlag] -> PatchTree p wX wY -> IO () jumpHalfOnRight opts l = do unapplyRL ps-                            when (SetScriptsExecutable `elem` opts) $ setScriptsExecutablePatches ps+                            when (O.yes (O.setScriptsExecutable ? opts)) $ setScriptsExecutablePatches ps   where ps = patchTree2RL l -jumpHalfOnLeft :: (IsHunk p, Conflict p,-                   PatchListFormat p, ShowPatch p, PatchInspect p,-                   Patchy p, ApplyMonad (ApplyState p) DefaultIO)+jumpHalfOnLeft :: (Apply p, PatchInspect p,+                   ApplyMonad (ApplyState p) DefaultIO)                => [DarcsFlag] -> PatchTree p wX wY -> IO () jumpHalfOnLeft opts r = do applyRL p-                           when (SetScriptsExecutable `elem` opts) $ setScriptsExecutablePatches p+                           when (O.yes (O.setScriptsExecutable ? opts)) $ setScriptsExecutablePatches p    where p = patchTree2RL r -applyRL :: (Invert p, ShowPatch p, Apply p, ApplyMonad (ApplyState p) DefaultIO)+applyRL :: (Apply p, ApplyMonad (ApplyState p) DefaultIO)         => RL p wX wY -> IO () applyRL   patches = sequence_ (mapFL safeApply (reverseRL patches)) -unapplyRL :: (Invert p, ShowPatch p, Apply p, ApplyMonad (ApplyState p) DefaultIO)+unapplyRL :: (Invert p, Apply p, ApplyMonad (ApplyState p) DefaultIO)            => RL p wX wY -> IO () unapplyRL patches = sequence_ (mapRL (safeApply . invert) patches) -safeApply :: (Invert p, ShowPatch p, Apply p, ApplyMonad (ApplyState p) DefaultIO)+safeApply :: (Apply p, ApplyMonad (ApplyState p) DefaultIO)           => p wX wY -> IO () safeApply p = runDefault (apply p) `catch` \(msg :: IOException) -> fail $ "Bad patch:\n" ++ show msg
src/Darcs/UI/Commands/TransferMode.hs view
@@ -27,8 +27,9 @@ import Darcs.Util.File ( withCurrentDirectory ) import Darcs.Util.Exception ( prettyException ) import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInRepository )+import Darcs.UI.Completion ( noArgs ) import Darcs.UI.Flags ( DarcsFlag )-import Darcs.UI.Options ( DarcsOption, oid, odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Options ( oid, odesc, ocheck, onormalise, defaultFlags ) import qualified Darcs.UI.Options.All as O import Darcs.Util.Progress ( setProgressMode ) import Darcs.Util.Global ( darcsdir )@@ -52,24 +53,6 @@  "who do not run ssh-agent will be prompted for the ssh password tens or\n" ++  "hundreds of times!\n" -transferModeBasicOpts :: DarcsOption a (Maybe String -> a)-transferModeBasicOpts = O.workingRepoDir--transferModeOpts :: DarcsOption a-                    (Maybe String-                     -> Maybe O.StdCmdAction-                     -> Bool-                     -> Bool-                     -> O.Verbosity-                     -> Bool-                     -> O.UseCache-                     -> Maybe String-                     -> Bool-                     -> Maybe String-                     -> Bool-                     -> a)-transferModeOpts = transferModeBasicOpts `withStdOpts` oid- transferMode :: DarcsCommand [DarcsFlag] transferMode = DarcsCommand     { commandProgramName = "darcs"@@ -78,7 +61,7 @@     , commandDescription = transferModeDescription     , commandExtraArgs = 0     , commandExtraArgHelp = []-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandCommand = transferModeCmd     , commandPrereq = amInRepository     , commandArgdefaults = nodefaults@@ -88,6 +71,9 @@     , commandCheckOptions = ocheck transferModeOpts     , commandParseOptions = onormalise transferModeOpts     }+  where+    transferModeBasicOpts = O.repoDir+    transferModeOpts = transferModeBasicOpts `withStdOpts` oid  transferModeCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () transferModeCmd _ _ _ = do setProgressMode False
src/Darcs/UI/Commands/Unrecord.hs view
@@ -15,7 +15,7 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings #-}  module Darcs.UI.Commands.Unrecord     ( unrecord@@ -31,17 +31,16 @@ import Prelude hiding ( (^) )  import Control.Exception ( catch, IOException )-import Control.Monad ( when, unless )-import Data.Maybe( isJust, mapMaybe )-import Data.List ( intercalate )+import Control.Monad ( when )+import Data.Maybe( isJust ) import Darcs.Util.Tree( Tree ) import System.Exit ( exitSuccess )  import Darcs.Patch ( IsRepoType, RepoPatch, invert, commute, effect ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.Bundle ( makeBundleN, contextPatches, minContext )-import Darcs.Patch.Depends ( findCommonWithThem, newsetUnion )-import Darcs.Patch.Match ( firstMatch, matchFirstPatchset, matchAPatchread, MatchFlag )+import Darcs.Patch.Depends ( findCommonWithThem, patchSetUnion )+import Darcs.Patch.Match ( firstMatch, matchFirstPatchset, matchAPatch, MatchFlag ) import Darcs.Patch.PatchInfoAnd ( hopefully, patchDesc ) import Darcs.Patch.Set ( PatchSet(..), Tagged(..), appendPSFL, Origin,                          SealedPatchSet )@@ -59,22 +58,23 @@ import Darcs.Util.Lock( writeDocBinFile ) import Darcs.Repository.Prefs ( getDefaultRepoPath ) import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, commandAlias-                         , putVerbose, printDryRunMessageAndExit+                         , putVerbose                          , setEnvDarcsPatches, amInHashedRepository                          , putInfo )-import Darcs.UI.Commands.Util ( getUniqueDPatchName )+import Darcs.UI.Commands.Util ( getUniqueDPatchName, printDryRunMessageAndExit )+import Darcs.UI.Completion ( noArgs ) import Darcs.UI.Flags-    ( doReverse, compression, verbosity, getOutput-    , useCache, dryRun, umask, DarcsFlag ( NotInRemote ), minimize-    , diffAlgorithm, hasXmlOutput, hasSummary, isInteractive, selectDeps )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags, parseFlags )+    ( DarcsFlag, changesReverse, compress, verbosity, getOutput+    , useCache, dryRun, umask, minimize+    , diffAlgorithm, xmlOutput, isInteractive, selectDeps )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) ) import Darcs.UI.Options.All ( notInRemoteFlagName ) import qualified Darcs.UI.Options.All as O import Darcs.UI.SelectChanges ( WhichChanges(..),                                 selectionContext, runSelection ) import qualified Darcs.UI.SelectChanges as S ( PatchSelectionOptions (..) ) import Darcs.Util.English ( presentParticiple )-import Darcs.Util.Printer ( text, putDoc, (<>), (<+>) )+import Darcs.Util.Printer ( text, putDoc, vcat, (<>), (<+>), ($$) ) import Darcs.Util.Progress ( debugMessage )  unrecordDescription :: String@@ -91,41 +91,6 @@  , "possibility that another user may have already pulled the patch."  ] -unrecordBasicOpts :: DarcsOption a-                     ([MatchFlag] -> O.SelectDeps -> Maybe Bool -> Maybe String -> a)-unrecordBasicOpts-    = O.matchSeveralOrLast-    ^ O.selectDeps-    ^ O.interactive -- True-    ^ O.workingRepoDir--unrecordAdvancedOpts :: DarcsOption a (O.Compression -> O.UMask -> Bool -> a)-unrecordAdvancedOpts-    = O.compress-    ^ O.umask-    ^ O.changesReverse--unrecordOpts :: DarcsOption a-                ([MatchFlag]-                 -> O.SelectDeps-                 -> Maybe Bool-                 -> Maybe String-                 -> Maybe O.StdCmdAction-                 -> Bool-                 -> Bool-                 -> O.Verbosity-                 -> Bool-                 -> O.Compression-                 -> O.UMask-                 -> Bool-                 -> O.UseCache-                 -> Maybe String-                 -> Bool-                 -> Maybe String-                 -> Bool-                 -> a)-unrecordOpts = unrecordBasicOpts `withStdOpts` unrecordAdvancedOpts- unrecord :: DarcsCommand [DarcsFlag] unrecord = DarcsCommand     { commandProgramName = "darcs"@@ -136,7 +101,7 @@     , commandExtraArgHelp = []     , commandCommand = unrecordCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc unrecordAdvancedOpts     , commandBasicOptions = odesc unrecordBasicOpts@@ -144,20 +109,27 @@     , commandCheckOptions = ocheck unrecordOpts     , commandParseOptions = onormalise unrecordOpts     }+  where+    unrecordBasicOpts+      = O.notInRemote+      ^ O.matchSeveralOrLast+      ^ O.selectDeps+      ^ O.interactive -- True+      ^ O.repoDir+    unrecordAdvancedOpts+      = O.compress+      ^ O.umask+      ^ O.changesReverse+    unrecordOpts = unrecordBasicOpts `withStdOpts` unrecordAdvancedOpts  unrecordCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () unrecordCmd _ opts _ =-    withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $+    withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $         RepoJob $ \repository -> do-            allpatches <- readRepo repository-            let matchFlags = parseFlags O.matchSeveralOrLast opts-            (_ :> patches) <- return $-                if firstMatch matchFlags-                    then getLastPatches matchFlags allpatches-                    else matchingHead matchFlags allpatches-            let direction = if doReverse opts then Last else LastReversed+            (_ :> removal_candidates) <- preselectPatches opts repository+            let direction = if changesReverse ? opts then Last else LastReversed                 context = selectionContext direction "unrecord" (patchSelOpts opts) Nothing Nothing-            (_ :> to_unrecord) <- runSelection patches context+            (_ :> to_unrecord) <- runSelection removal_candidates context             when (nullFL to_unrecord) $ do                 putInfo opts "No patches selected!"                 exitSuccess@@ -165,9 +137,9 @@                 text "About to write out (potentially) modified patches..."             setEnvDarcsPatches to_unrecord             invalidateIndex repository-            _ <- tentativelyRemovePatches repository (compression opts)+            _ <- tentativelyRemovePatches repository (compress ? opts)                      YesUpdateWorking to_unrecord-            finalizeRepositoryChanges repository YesUpdateWorking (compression opts)+            finalizeRepositoryChanges repository YesUpdateWorking (compress ? opts)             putInfo opts "Finished unrecording."  getLastPatches :: (IsRepoType rt, RepoPatch p) => [MatchFlag] -> PatchSet rt p Origin wR@@ -218,68 +190,6 @@  , "later to your repository with `darcs apply`."  ] -obliterateBasicOpts :: DarcsOption a-                       ([Maybe String]-                        -> [MatchFlag]-                        -> O.SelectDeps-                        -> Maybe Bool-                        -> Maybe String-                        -> Maybe O.Summary-                        -> Maybe O.Output-                        -> Bool-                        -> O.DiffAlgorithm-                        -> O.DryRun-                        -> O.XmlOutput-                        -> a)-obliterateBasicOpts-    = O.notInRemote-    ^ O.matchSeveralOrLast-    ^ O.selectDeps-    ^ O.interactive-    ^ O.workingRepoDir-    ^ O.summary-    ^ O.output-    ^ O.minimize-    ^ O.diffAlgorithm-    ^ O.dryRunXml--obliterateAdvancedOpts :: DarcsOption a-                          (O.Compression -> O.UseIndex -> O.UMask -> Bool -> a)-obliterateAdvancedOpts-    = O.compress-    ^ O.useIndex-    ^ O.umask-    ^ O.changesReverse--obliterateOpts :: DarcsOption a-                  ([Maybe String]-                   -> [MatchFlag]-                   -> O.SelectDeps-                   -> Maybe Bool-                   -> Maybe String-                   -> Maybe O.Summary-                   -> Maybe O.Output-                   -> Bool-                   -> O.DiffAlgorithm-                   -> DryRun-                   -> O.XmlOutput-                   -> Maybe O.StdCmdAction-                   -> Bool-                   -> Bool-                   -> O.Verbosity-                   -> Bool-                   -> O.Compression-                   -> UseIndex-                   -> O.UMask-                   -> Bool-                   -> O.UseCache-                   -> Maybe String-                   -> Bool-                   -> Maybe String-                   -> Bool-                   -> a)-obliterateOpts = obliterateBasicOpts `withStdOpts` obliterateAdvancedOpts- obliterate :: DarcsCommand [DarcsFlag] obliterate = DarcsCommand     { commandProgramName = "darcs"@@ -290,7 +200,7 @@     , commandExtraArgHelp = []     , commandCommand = obliterateCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc obliterateAdvancedOpts     , commandBasicOptions = odesc obliterateBasicOpts@@ -298,13 +208,28 @@     , commandCheckOptions = ocheck obliterateOpts     , commandParseOptions = onormalise obliterateOpts     }+  where+    obliterateBasicOpts+      = O.notInRemote+      ^ O.matchSeveralOrLast+      ^ O.selectDeps+      ^ O.interactive+      ^ O.repoDir+      ^ O.summary+      ^ O.output+      ^ O.minimize+      ^ O.diffAlgorithm+      ^ O.dryRunXml+    obliterateAdvancedOpts+      = O.compress+      ^ O.useIndex+      ^ O.umask+      ^ O.changesReverse+    obliterateOpts = obliterateBasicOpts `withStdOpts` obliterateAdvancedOpts  obliterateCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () obliterateCmd = genericObliterateCmd "obliterate" -data NotInRemoteLocation = NotInDefaultRepo-                         | NotInRemotePath String- -- | genericObliterateCmd is the function that executes the "obliterate" and -- "unpull" commands. The first argument is the name under which the command is -- invoked (@unpull@ or @obliterate@).@@ -314,31 +239,17 @@                      -> [String]                      -> IO () genericObliterateCmd cmdname _ opts _ =-    let cacheOpt = useCache opts-        verbOpt = verbosity opts-    in withRepoLock (dryRun opts) cacheOpt YesUpdateWorking (umask opts) $+    let cacheOpt = useCache ? opts+        verbOpt = verbosity ? opts+    in withRepoLock (dryRun ? opts) cacheOpt YesUpdateWorking (umask ? opts) $         RepoJob $ \repository -> do             -- FIXME we may need to honour --ignore-times here, although this             -- command does not take that option (yet)-            pend <- unrecordedChanges (UseIndex, ScanKnown, diffAlgorithm opts) repository Nothing-            allpatches <- readRepo repository-            let collectNotIns (NotInRemote nir) = case nir of-                    Just p -> Just $ NotInRemotePath p-                    Nothing -> Just NotInDefaultRepo-                collectNotIns _ = Nothing-                notIns = mapMaybe collectNotIns opts-            (auto_kept :> removal_candidates) <- case notIns of-                [] -> do-                    let matchFlags = parseFlags O.matchSeveralOrLast opts-                    return $ if firstMatch matchFlags-                                   then getLastPatches matchFlags allpatches-                                   else matchingHead matchFlags allpatches-                nirs -> do-                    (Sealed thems) <--                      getNotInRemotePatches verbOpt cacheOpt repository nirs-                    return $ findCommonWithThem allpatches thems+            pend <- unrecordedChanges (UseIndex, ScanKnown, diffAlgorithm ? opts)+              O.NoLookForMoves O.NoLookForReplaces repository Nothing+            (auto_kept :> removal_candidates) <- preselectPatches opts repository -            let direction = if doReverse opts then Last else LastReversed+            let direction = if changesReverse ? opts then Last else LastReversed                 context = selectionContext direction cmdname (patchSelOpts opts) Nothing Nothing             (kept :> removed) <-                 runSelection removal_candidates context@@ -352,9 +263,9 @@                 Just (_ :> p_after_pending) -> do                     printDryRunMessageAndExit "obliterate"                       verbOpt-                      (hasSummary O.NoSummary opts)-                      (dryRun opts)-                      (hasXmlOutput opts)+                      (O.summary ? opts)+                      (dryRun ? opts)+                      (xmlOutput ? opts)                       (isInteractive True opts)                       removed                     setEnvDarcsPatches removed@@ -362,11 +273,11 @@                         savetoBundle opts (auto_kept `appendPSFL` kept) removed                     invalidateIndex repository                     _ <- tentativelyRemovePatches repository-                        (compression opts) YesUpdateWorking removed+                        (compress ? opts) YesUpdateWorking removed                     tentativelyAddToPending repository                         YesUpdateWorking $ invert $ effect removed                     finalizeRepositoryChanges repository-                        YesUpdateWorking (compression opts)+                        YesUpdateWorking (compress ? opts)                     debugMessage "Applying patches to working directory..."                     _ <- applyToWorking repository verbOpt                         (invert p_after_pending)@@ -376,30 +287,27 @@                     putInfo opts $ "Finished" <+> text (presentParticiple cmdname) <> "."  -- | Get the union of the set of patches in each specified location-getNotInRemotePatches :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)-                      => O.Verbosity -> O.UseCache-                      -> Repository rt p wX wU wT -> [NotInRemoteLocation]-                      -> IO (SealedPatchSet rt p Origin)-getNotInRemotePatches verbOpt cacheOpt repository nirs = do-    unless (verbOpt == O.Quiet) $-      putStrLn $ "Determining patches not in" ++ pluralExtra ++ ":\n" ++ names+remotePatches :: (IsRepoType rt, RepoPatch p)+              => [DarcsFlag]+              -> Repository rt p wX wU wT -> [O.NotInRemote]+              -> IO (SealedPatchSet rt p Origin)+remotePatches opts repository nirs = do     nirsPaths <- mapM getNotInRemotePath nirs-    newsetUnion `fmap` mapM readNir nirsPaths+    putInfo opts $ "Determining patches not in" <+> pluralExtra nirsPaths $$+        itemize nirsPaths+    patchSetUnion `fmap` mapM readNir nirsPaths   where-    toName (NotInRemotePath s) = "'" ++ s ++ "'"-    toName NotInDefaultRepo = "Default push/pull repo"--    pluralExtra = if length names > 1 then " any of" else ""-    names = intercalate "\n" $ map ((leader ++) . toName) nirs-    leader = "    - "+    pluralExtra names = if length names > 1 then "any of" else mempty+    itemize = vcat . map (text . ("  - " ++))      readNir n = do-        r <- identifyRepositoryFor repository cacheOpt n+        r <- identifyRepositoryFor repository (useCache ? opts) n         rps <- readRepo r         return $ seal rps -    getNotInRemotePath (NotInRemotePath p) = return p-    getNotInRemotePath NotInDefaultRepo = do+    getNotInRemotePath :: O.NotInRemote -> IO String+    getNotInRemotePath (O.NotInRemotePath p) = return p+    getNotInRemotePath O.NotInDefaultRepo = do         defaultRepo <- getDefaultRepoPath         let err = fail $ "No default push/pull repo configured, please pass a "                          ++ "repo name to --" ++ notInRemoteFlagName@@ -418,7 +326,7 @@     mh :: forall wX . PatchSet rt p Origin wX        -> (PatchSet rt p :> RL (PatchInfoAnd rt p)) Origin wX     mh s@(PatchSet _ x)-        | or (mapRL (matchAPatchread matchFlags) x) = contextPatches s+        | or (mapRL (matchAPatch matchFlags) x) = contextPatches s     mh (PatchSet (ts :<: Tagged t _ ps) x) =         case mh (PatchSet ts (ps :<: t)) of             (start :> patches) -> start :> patches +<+ x@@ -428,7 +336,7 @@              -> PatchSet rt p Origin wZ -> FL (PatchInfoAnd rt p) wZ wT -> IO () savetoBundle opts kept removed@(x :>: _) = do     let genFullBundle = makeBundleN Nothing kept (mapFL_FL hopefully removed)-    bundle <- if not (minimize opts)+    bundle <- if not (minimize ? opts)                then genFullBundle                else do putInfo opts "Minimizing context, to generate bundle with full context hit ctrl-C..."                        ( case minContext kept removed of@@ -441,12 +349,33 @@     useAbsoluteOrStd writeDocBinFile putDoc outname bundle savetoBundle _ _ NilFL = return () +preselectPatches+  :: (IsRepoType rt, RepoPatch p)+  => [DarcsFlag]+  -> Repository rt p wR wU wT+  -> IO ((PatchSet rt p :> FL (PatchInfoAnd rt p)) Origin wR)+preselectPatches opts repo = do+  allpatches <- readRepo repo+  let matchFlags = parseFlags O.matchSeveralOrLast opts+  case O.notInRemote ? opts of+    [] -> do+      return $+        if firstMatch matchFlags+          then getLastPatches matchFlags allpatches+          else matchingHead matchFlags allpatches+    -- FIXME what about match options when we have --not-in-remote?+    -- It looks like they are simply ignored.+    nirs -> do+      (Sealed thems) <-+        remotePatches opts repo nirs+      return $ findCommonWithThem allpatches thems+ patchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions patchSelOpts flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { S.verbosity = verbosity ? flags     , S.matchFlags = parseFlags O.matchSeveralOrLast flags     , S.interactive = isInteractive True flags-    , S.selectDeps = selectDeps flags-    , S.summary = hasSummary O.NoSummary flags+    , S.selectDeps = selectDeps ? flags+    , S.summary = O.summary ? flags     , S.withContext = O.NoContext     }
src/Darcs/UI/Commands/Unrevert.hs view
@@ -15,29 +15,25 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP, GADTs #-}-- module Darcs.UI.Commands.Unrevert ( unrevert, writeUnrevert ) where  import Prelude () import Darcs.Prelude -import Prelude hiding ( (^), catch )- import Control.Exception ( catch, IOException ) import System.Exit ( exitSuccess ) import Darcs.Util.Tree( Tree )  import Darcs.UI.Commands ( DarcsCommand(..), withStdOpts, nodefaults, amInHashedRepository )+import Darcs.UI.Completion ( noArgs ) import Darcs.UI.Flags-    ( diffingOpts, verbosity, useCache, umask, compression, diffAlgorithm-    , isInteractive, isUnified )+    ( diffingOpts, verbosity, useCache, umask, compress, diffAlgorithm+    , isInteractive, withContext ) import Darcs.Repository.Flags     ( UseIndex(..), ScanKnown (..), Reorder(..), AllowConflicts(..), ExternalMerge(..)     , WantGuiPause(..), UpdateWorking(..), DryRun(NoDryRun) ) import Darcs.UI.Flags ( DarcsFlag )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags )+import Darcs.UI.Options ( (^), odesc, ocheck, onormalise, defaultFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.Repository ( SealedPatchSet, Repository, withRepoLock, RepoJob(..),                           unrevertUrl, considerMergeToWorking,@@ -48,6 +44,7 @@ import Darcs.Patch ( IsRepoType, RepoPatch, PrimOf, commute, fromPrims ) import Darcs.Patch.Apply( ApplyState ) import Darcs.Patch.Named.Wrapped ( namepatch )+import Darcs.Patch.Rebase ( dropAnyRebase ) import Darcs.Patch.Set ( Origin ) import Darcs.Patch.Witnesses.Sealed ( Sealed(Sealed) ) import Darcs.Patch.Witnesses.Ordered ( FL(..), (:>)(..), (+>+) )@@ -67,7 +64,6 @@ import Darcs.Util.SignalHandler ( withSignalsBlocked ) import Darcs.Util.Progress ( debugMessage ) import Darcs.Util.Path ( AbsolutePath )-#include "impossible.h"  unrevertDescription :: String unrevertDescription =@@ -83,51 +79,14 @@  "took place.  Darcs will ask for confirmation before executing an\n" ++  "interactive command that will DEFINITELY prevent unreversion.\n" -unrevertBasicOpts :: DarcsOption a-                     (O.UseIndex-                      -> Maybe Bool-                      -> Maybe String-                      -> O.WithContext-                      -> O.DiffAlgorithm-                      -> a)-unrevertBasicOpts-    = O.useIndex-    ^ O.interactive -- True-    ^ O.workingRepoDir-    ^ O.withContext-    ^ O.diffAlgorithm--unrevertAdvancedOpts :: DarcsOption a (O.UMask -> a)-unrevertAdvancedOpts = O.umask--unrevertOpts :: DarcsOption a-                (UseIndex-                 -> Maybe Bool-                 -> Maybe String-                 -> O.WithContext-                 -> O.DiffAlgorithm-                 -> Maybe O.StdCmdAction-                 -> Bool-                 -> Bool-                 -> O.Verbosity-                 -> Bool-                 -> O.UMask-                 -> O.UseCache-                 -> Maybe String-                 -> Bool-                 -> Maybe String-                 -> Bool-                 -> a)-unrevertOpts = unrevertBasicOpts `withStdOpts` unrevertAdvancedOpts- patchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions patchSelOpts flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { S.verbosity = verbosity ? flags     , S.matchFlags = []     , S.interactive = isInteractive True flags     , S.selectDeps = O.PromptDeps -- option not supported, use default     , S.summary = O.NoSummary -- option not supported, use default-    , S.withContext = isUnified flags+    , S.withContext = withContext ? flags     }  unrevert :: DarcsCommand [DarcsFlag]@@ -140,7 +99,7 @@     , commandExtraArgHelp = []     , commandCommand = unrevertCmd     , commandPrereq = amInHashedRepository-    , commandGetArgPossibilities = return []+    , commandCompleteArgs = noArgs     , commandArgdefaults = nodefaults     , commandAdvancedOptions = odesc unrevertAdvancedOpts     , commandBasicOptions = odesc unrevertBasicOpts@@ -148,27 +107,37 @@     , commandCheckOptions = ocheck unrevertOpts     , commandParseOptions = onormalise unrevertOpts     }+  where+    unrevertBasicOpts+      = O.useIndex+      ^ O.interactive -- True+      ^ O.repoDir+      ^ O.withContext+      ^ O.diffAlgorithm+    unrevertAdvancedOpts = O.umask+    unrevertOpts = unrevertBasicOpts `withStdOpts` unrevertAdvancedOpts  unrevertCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () unrevertCmd _ opts [] =- withRepoLock NoDryRun (useCache opts) YesUpdateWorking (umask opts) $ RepoJob $ \repository -> do+ withRepoLock NoDryRun (useCache ? opts) YesUpdateWorking (umask ? opts) $ RepoJob $ \repository -> do   us <- readRepo repository   Sealed them <- unrevertPatchBundle repository   recorded <- readRecorded repository-  unrecorded <- unrecordedChanges (diffingOpts opts {- always ScanKnown here -}) repository Nothing+  unrecorded <- unrecordedChanges (diffingOpts opts {- always ScanKnown here -})+    O.NoLookForMoves O.NoLookForReplaces repository Nothing   Sealed h_them <- return $ mergeThem us them   Sealed pw <- considerMergeToWorking repository "unrevert"                       YesAllowConflictsAndMark YesUpdateWorking                       NoExternalMerge NoWantGuiPause-                      (compression opts) (verbosity opts) NoReorder-                      ( UseIndex, ScanKnown, diffAlgorithm opts )+                      (compress ? opts) (verbosity ? opts) NoReorder+                      ( UseIndex, ScanKnown, diffAlgorithm ? opts )                       NilFL h_them   let context = selectionContextPrim First "unrevert" (patchSelOpts opts) Nothing Nothing (Just recorded)   (p :> skipped) <- runSelection pw context   tentativelyAddToPending repository YesUpdateWorking p   withSignalsBlocked $-      do finalizeRepositoryChanges repository YesUpdateWorking (compression opts)-         _ <- applyToWorking repository (verbosity opts) p `catch` \(e :: IOException) ->+      do finalizeRepositoryChanges repository YesUpdateWorking (compress ? opts)+         _ <- applyToWorking repository (verbosity ? opts) p `catch` \(e :: IOException) ->              fail ("Error applying unrevert to working directory...\n"                    ++ show e)          debugMessage "I'm about to writeUnrevert."@@ -187,7 +156,7 @@                                  _ -> exitSuccess                   writeUnrevert repository NilFL recorded pend     Just (p' :> _) -> do-        rep <- readRepo repository+        rep <- dropAnyRebase <$> readRepo repository         date <- getIsoDateTime         np <- namepatch date "unrevert" "anon" [] (fromRepoPrims repository p')         bundle <- makeBundleN (Just recorded) rep (np :>: NilFL)
src/Darcs/UI/Commands/Util.hs view
@@ -15,49 +15,76 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Darcs.UI.Commands.Util     ( announceFiles     , filterExistingPaths     , testTentativeAndMaybeExit+    , printDryRunMessageAndExit     , getUniqueRepositoryName     , getUniqueDPatchName+    , expandDirs+    , doesDirectoryReallyExist+    , checkUnrelatedRepos+    , repoTags     ) where -import Control.Monad ( unless )+import Control.Monad ( when, unless )+import Data.Maybe ( catMaybes )  import Prelude () import Darcs.Prelude -import System.Exit ( ExitCode(..), exitWith )+import System.Exit ( ExitCode(..), exitWith, exitSuccess )+import System.FilePath.Posix ( (</>) )+import System.Posix.Files ( isDirectory ) -import Darcs.Util.Tree.Monad ( virtualTreeIO, exists )-import Darcs.Util.Tree ( Tree )+import Darcs.Patch ( RepoPatch, xmlSummary )+import Darcs.Patch.Depends ( areUnrelatedRepos )+import Darcs.Patch.Info ( toXml, piTag )+import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, info, hopefullyM )+import Darcs.Patch.Set ( PatchSet(..), patchSetfMap )+import Darcs.Patch.Witnesses.Ordered ( FL, mapFL ) -import Darcs.Patch ( RepoPatch ) import Darcs.Repository ( Repository, readRecorded, testTentative )-import Darcs.Repository.State ( readUnrecordedFiltered )+import Darcs.Repository.State+    ( readUnrecordedFiltered, readWorking, restrictBoring+    , TreeFilter(..), applyTreeFilter+    ) import Darcs.Patch.Apply ( ApplyState ) import Darcs.Patch.Bundle ( patchFilename )++import Darcs.UI.PrintPatch ( showFriendly ) import Darcs.UI.Options.All     ( Verbosity(..), SetScriptsExecutable, TestChanges (..)-    , RunTest(..), LeaveTestDir(..), UseIndex, ScanKnown(..) )+    , RunTest(..), LeaveTestDir(..), UseIndex, ScanKnown(..)+    , Summary(..), DryRun(..), XmlOutput(..), LookForMoves+    )+ import Darcs.Util.Exception ( clarifyErrors )+import Darcs.Util.File ( getFileStatus, withCurrentDirectory ) import Darcs.Util.Path-    ( SubPath, toFilePath, getUniquePathName, floatPath )-import Darcs.Util.Printer ( putDocLn, text, (<>), (<+>) )-import Darcs.Util.Prompt ( PromptConfig(..), promptChar )+    ( SubPath, toFilePath, getUniquePathName, floatPath+    , simpleSubPath, toPath, anchorPath+    )+import Darcs.Util.Printer+    ( text, (<>), (<+>), hsep, ($$), vcat, vsep+    , putDocLn, insertBeforeLastline, prefix+    )+import Darcs.Util.Prompt ( PromptConfig(..), promptChar, promptYorn ) import Darcs.Util.Text ( pathlist )+import Darcs.Util.Tree.Monad ( virtualTreeIO, exists )+import Darcs.Util.Tree ( Tree )+import qualified Darcs.Util.Tree as Tree + announceFiles :: Verbosity -> Maybe [SubPath] -> String -> IO () announceFiles Quiet _ _ = return () announceFiles _ (Just subpaths) message = putDocLn $     text message <> text ":" <+> pathlist (map toFilePath subpaths) announceFiles _ _ _ = return () -testTentativeAndMaybeExit :: (RepoPatch p, ApplyState p ~ Tree)-                          => Repository rt p wR wU wT+testTentativeAndMaybeExit :: Repository rt p wR wU wT                           -> Verbosity                           -> TestChanges                           -> SetScriptsExecutable@@ -78,6 +105,47 @@         yn <- promptChar (PromptConfig prompt "yn" [] (Just 'n') [])         unless (yn == 'y') doExit +-- | @'printDryRunMessageAndExit' action flags patches@ prints a string+-- representing the action that would be taken if the @--dry-run@ option had+-- not been passed to darcs. Then darcs exits successfully.  @action@ is the+-- name of the action being taken, like @\"push\"@ @flags@ is the list of flags+-- which were sent to darcs @patches@ is the sequence of patches which would be+-- touched by @action@.+printDryRunMessageAndExit :: (RepoPatch p, ApplyState p ~ Tree)+                          => String+                          -> Verbosity -> Summary -> DryRun -> XmlOutput+                          -> Bool -- interactive+                          -> FL (PatchInfoAnd rt p) wX wY+                          -> IO ()+printDryRunMessageAndExit action v s d x interactive patches = do+    when (d == YesDryRun) $ do+        putInfoX $ hsep [ "Would", text action, "the following changes:" ]+        putDocLn put_mode+        putInfoX $ text ""+        putInfoX $ text "Making no changes: this is a dry run."+        exitSuccess+    when (not interactive && s == YesSummary) $ do+        putInfoX $ hsep [ "Will", text action, "the following changes:" ]+        putDocLn put_mode+  where+    put_mode = if x == YesXml+                   then text "<patches>" $$+                        vcat (mapFL (indent . xml_info s) patches) $$+                        text "</patches>"+                   else vsep $ mapFL (showFriendly v s) patches++    putInfoX = if x == YesXml then const (return ()) else putDocLn++    xml_info YesSummary = xml_with_summary+    xml_info NoSummary  = toXml . info++    xml_with_summary hp+        | Just p <- hopefullyM hp = insertBeforeLastline (toXml $ info hp)+                                        (indent $ xmlSummary p)+    xml_with_summary hp = toXml (info hp)++    indent = prefix "    "+ -- | Given a repository and two common command options, classify the given list -- of subpaths according to whether they exist in the pristine or working tree. -- Paths which are neither in working nor pristine are reported and dropped.@@ -88,11 +156,12 @@                     -> Verbosity                     -> UseIndex                     -> ScanKnown+                    -> LookForMoves                     -> [SubPath]                     -> IO ([SubPath],[SubPath])-filterExistingPaths repo verb useidx scan paths = do+filterExistingPaths repo verb useidx scan lfm paths = do       pristine <- readRecorded repo-      working <- readUnrecordedFiltered repo useidx scan (Just paths)+      working <- readUnrecordedFiltered repo useidx scan lfm (Just paths)       let filepaths = map toFilePath paths           check = virtualTreeIO $ mapM (exists . floatPath) filepaths       (in_pristine, _) <- check pristine@@ -122,3 +191,46 @@     buildMsg n = "Directory or file '"++ name ++                  "' already exists, creating dpatch as '"++                  n ++"'"++-- | For each directory in the list of 'SubPath's, add all paths+-- under that directory to the list. If the first argument is 'True', then+-- include even boring files.+--+-- This is used by the add and remove commands to handle the --recursive option.+expandDirs :: Bool -> [SubPath] -> IO [SubPath]+expandDirs includeBoring subpaths =+  do+    boringFilter <-+      if includeBoring+        then return (TreeFilter id)+        else restrictBoring Tree.emptyTree+    fmap (map (fromJust . simpleSubPath)) $+      concat `fmap` mapM (expandOne boringFilter . toPath) subpaths+  where+    expandOne boringFilter "" = listFiles boringFilter+    expandOne boringFilter f = do+        isdir <- doesDirectoryReallyExist f+        if not isdir+          then return [f]+          else do+            fs <- withCurrentDirectory f (listFiles boringFilter)+            return $ f: map (f </>) fs+    listFiles boringFilter = do+      working <- applyTreeFilter boringFilter <$> readWorking+      return $ map (anchorPath "" . fst) $ Tree.list working++doesDirectoryReallyExist :: FilePath -> IO Bool+doesDirectoryReallyExist f = maybe False isDirectory `fmap` getFileStatus f++checkUnrelatedRepos :: RepoPatch p+                    => Bool+                    -> PatchSet rt p wStart wX+                    -> PatchSet rt p wStart wY+                    -> IO ()+checkUnrelatedRepos allowUnrelatedRepos us them =+    when ( not allowUnrelatedRepos && areUnrelatedRepos us them ) $+         do confirmed <- promptYorn "Repositories seem to be unrelated. Proceed?"+            unless confirmed $ putStrLn "Cancelled." >> exitSuccess++repoTags :: PatchSet rt p wX wY -> IO [String]+repoTags ps = catMaybes `fmap` patchSetfMap (return . piTag . info) ps
src/Darcs/UI/Commands/Util/Tree.hs view
@@ -30,47 +30,42 @@ import Control.Monad ( forM ) import Control.Monad.State.Strict( gets ) -import qualified Data.ByteString.Char8 as BSC-import Data.Char ( toLower )--import Darcs.Util.Tree.Monad-    ( withDirectory, fileExists, directoryExists-    , virtualTreeMonad, currentDirectory-    , TreeMonad )-import qualified Darcs.Util.Tree.Monad as HS ( exists, tree )+import qualified Darcs.Util.Tree.Monad as TM+    ( TreeMonad, withDirectory, fileExists, directoryExists+    , virtualTreeMonad, currentDirectory, exists, tree ) import Darcs.Util.Tree ( Tree, listImmediate, findTree )  import Darcs.Util.Path-    ( AnchoredPath(..), Name(..), floatPath )+    ( AnchoredPath(..), floatPath, eqAnycase ) -treeHasAnycase :: (Functor m, Monad m)+treeHasAnycase :: Monad m                => Tree m                -> FilePath                -> m Bool treeHasAnycase tree path =-    fst `fmap` virtualTreeMonad (existsAnycase $ floatPath path) tree+    fst `fmap` TM.virtualTreeMonad (existsAnycase $ floatPath path) tree  -existsAnycase :: (Functor m, Monad m)+existsAnycase :: Monad m               => AnchoredPath-              -> TreeMonad m Bool+              -> TM.TreeMonad m Bool existsAnycase (AnchoredPath []) = return True-existsAnycase (AnchoredPath (Name x:xs)) = do-     wd <- currentDirectory-     Just tree <- gets (flip findTree wd . HS.tree)-     let subs = [ AnchoredPath [Name n] | (Name n, _) <- listImmediate tree,-                                          BSC.map toLower n == BSC.map toLower x ]+existsAnycase (AnchoredPath (x:xs)) = do+     wd <- TM.currentDirectory+     Just tree <- gets (flip findTree wd . TM.tree)+     let subs = [ AnchoredPath [n] | (n, _) <- listImmediate tree,+                                          eqAnycase n x ]      or `fmap` forM subs (\path -> do-       file <- fileExists path+       file <- TM.fileExists path        if file then return True-               else withDirectory path (existsAnycase $ AnchoredPath xs))+               else TM.withDirectory path (existsAnycase $ AnchoredPath xs))  -treeHas :: (Functor m, Monad m) => Tree m -> FilePath -> m Bool-treeHas tree path = fst `fmap` virtualTreeMonad (HS.exists $ floatPath path) tree+treeHas :: Monad m => Tree m -> FilePath -> m Bool+treeHas tree path = fst `fmap` TM.virtualTreeMonad (TM.exists $ floatPath path) tree -treeHasDir :: (Functor m, Monad m) => Tree m -> FilePath -> m Bool-treeHasDir tree path = fst `fmap` virtualTreeMonad (directoryExists $ floatPath path) tree+treeHasDir :: Monad m => Tree m -> FilePath -> m Bool+treeHasDir tree path = fst `fmap` TM.virtualTreeMonad (TM.directoryExists $ floatPath path) tree -treeHasFile :: (Functor m, Monad m) => Tree m -> FilePath -> m Bool-treeHasFile tree path = fst `fmap` virtualTreeMonad (fileExists $ floatPath path) tree+treeHasFile :: Monad m => Tree m -> FilePath -> m Bool+treeHasFile tree path = fst `fmap` TM.virtualTreeMonad (TM.fileExists $ floatPath path) tree
src/Darcs/UI/Commands/WhatsNew.hs view
@@ -15,9 +15,6 @@ --  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, --  Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}-- module Darcs.UI.Commands.WhatsNew     (       whatsnew@@ -37,17 +34,16 @@ import Darcs.Patch     ( PrimOf, PrimPatch, RepoPatch     , applyToTree, plainSummaryPrims, primIsHunk-    , listTouchedFiles, IsRepoType     )-import Darcs.Patch.Apply ( ApplyState )-import Darcs.Patch.Choices ( patchChoicesLps, lpPatch )+import Darcs.Patch.Apply ( Apply, ApplyState )+import Darcs.Patch.Choices ( mkPatchChoices, labelPatches, unLabel )+import Darcs.Patch.Commute ( Commute ) import Darcs.Patch.FileHunk ( IsHunk (..) )-import Darcs.Patch.Format ( PatchListFormat (..) )+import Darcs.Patch.Format ( PatchListFormat ) import Darcs.Patch.Inspect ( PatchInspect (..) )-import Darcs.Patch.Patchy ( Patchy ) import Darcs.Patch.Permutations ( partitionRL ) import Darcs.Patch.Prim.Class ( PrimDetails (..) )-import Darcs.Patch.Show ( ShowPatch )+import Darcs.Patch.Show ( ShowPatch, ShowContextPatch ) import Darcs.Patch.Split ( primSplitter ) import Darcs.Patch.TouchesFiles ( choosePreTouching ) import Darcs.Patch.Witnesses.Ordered@@ -58,29 +54,29 @@     ( Sealed (..), Sealed2 (..)     , unFreeLeft     )-import Darcs.Patch.Witnesses.Unsafe ( unsafeCoerceP ) import Darcs.Patch.Witnesses.WZipper ( FZipper (..) ) import Darcs.Repository     ( RepoJob (..), Repository-    , listRegisteredFiles, readRecorded, readRepo-    , unrecordedChangesWithPatches, withRepository+    , readRecorded+    , unrecordedChanges, withRepository     ) import Darcs.Repository.Diff ( treeDiff ) import Darcs.Repository.Prefs ( filetypeFunction )-import Darcs.Repository.State ( getMovesPs, getReplaces ) import Darcs.UI.Commands     ( DarcsCommand(..), withStdOpts, amInRepository     , commandAlias, nodefaults     )-import Darcs.Repository.Resolution ( patchsetConflictResolutions )+import Darcs.UI.Completion ( modifiedFileArgs ) import Darcs.UI.Commands.Util ( announceFiles, filterExistingPaths ) import Darcs.UI.Flags-    ( DarcsFlag (Summary, LookForAdds, LookForMoves), diffAlgorithm, diffingOpts-    , isUnified, useCache, fixSubPaths-    , verbosity, isInteractive, isUnified, lookForAdds, lookForMoves, lookForReplaces, hasSummary-    , scanKnown, useIndex+    ( DarcsFlag, diffAlgorithm+    , withContext, useCache, fixSubPaths+    , verbosity, isInteractive+    , lookForAdds, lookForMoves, lookForReplaces+    , scanKnown, useIndex, diffingOpts     )-import Darcs.UI.Options ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags, parseFlags )+import Darcs.UI.Options+    ( DarcsOption, (^), odesc, ocheck, onormalise, defaultFlags, parseFlags, (?) ) import qualified Darcs.UI.Options.All as O import Darcs.UI.PrintPatch     ( contextualPrintPatch, printPatch@@ -98,73 +94,37 @@     , skipOne, printSummary     ) import qualified Darcs.UI.SelectChanges as S ( PatchSelectionOptions (..) )-import Darcs.Util.Path ( AbsolutePath, SubPath, toFilePath, fp2fn )+import Darcs.Util.Path ( AbsolutePath, SubPath, toFilePath ) import Darcs.Util.Printer-    ( putDocLn, renderString, RenderMode(..)+    ( putDocLn, renderString     , text, vcat     ) import Darcs.Util.Prompt ( PromptConfig (..), promptChar ) --whatsnewBasicOpts :: DarcsOption a-                     (Maybe O.Summary-                      -> O.WithContext-                      -> Bool-                      -> O.LookFor-                      -> O.DiffAlgorithm-                      -> Maybe String-                      -> Maybe Bool-                      -> a)-whatsnewBasicOpts-    = O.summary-    ^ O.withContext-    ^ O.machineReadable-    ^ O.lookfor-    ^ O.diffAlgorithm-    ^ O.workingRepoDir-    ^ O.interactive -- False--whatsnewAdvancedOpts :: DarcsOption a (O.UseIndex -> O.IncludeBoring -> a)-whatsnewAdvancedOpts = O.useIndex ^ O.includeBoring--whatsnewOpts :: DarcsOption a-                (Maybe O.Summary-                 -> O.WithContext-                 -> Bool-                 -> O.LookFor-                 -> O.DiffAlgorithm-                 -> Maybe String-                 -> Maybe Bool-                 -> Maybe O.StdCmdAction-                 -> Bool-                 -> Bool-                 -> O.Verbosity-                 -> Bool-                 -> O.UseIndex-                 -> O.IncludeBoring-                 -> O.UseCache-                 -> Maybe String-                 -> Bool-                 -> Maybe String-                 -> Bool-                 -> a)-whatsnewOpts = whatsnewBasicOpts `withStdOpts` whatsnewAdvancedOpts+commonAdvancedOpts :: DarcsOption a (O.UseIndex -> O.IncludeBoring -> a)+commonAdvancedOpts = O.useIndex ^ O.includeBoring  patchSelOpts :: [DarcsFlag] -> S.PatchSelectionOptions patchSelOpts flags = S.PatchSelectionOptions-    { S.verbosity = verbosity flags+    { S.verbosity = verbosity ? flags     , S.matchFlags = []     , S.interactive = isInteractive True flags     , S.selectDeps = O.PromptDeps -- option not supported, use default-    , S.summary = hasSummary (defaultSummary flags) flags-    , S.withContext = isUnified flags+    , S.summary = getSummary flags+    , S.withContext = withContext ? flags     } -defaultSummary :: [DarcsFlag] -> O.Summary-defaultSummary flags-  | lookForAdds flags == O.YesLookForAdds = O.YesSummary-  | parseFlags O.machineReadable flags    = O.YesSummary-  | otherwise = O.NoSummary+-- lookForAdds and machineReadable set YesSummary+-- unless NoSummary was given expressly+-- (or by default e.g. status)+getSummary :: [DarcsFlag] -> O.Summary+getSummary flags = case O.maybeSummary Nothing ? flags of+  Just O.NoSummary -> O.NoSummary+  Just O.YesSummary -> O.YesSummary+  Nothing+    | O.yes (lookForAdds flags) -> O.YesSummary+    | O.machineReadable ? flags -> O.YesSummary+    | otherwise -> O.NoSummary  whatsnew :: DarcsCommand [DarcsFlag] whatsnew = DarcsCommand@@ -176,14 +136,24 @@     , commandExtraArgHelp = ["[FILE or DIRECTORY]..."]     , commandCommand = whatsnewCmd     , commandPrereq = amInRepository-    , commandGetArgPossibilities = listRegisteredFiles+    , commandCompleteArgs = modifiedFileArgs     , commandArgdefaults = nodefaults-    , commandAdvancedOptions = odesc whatsnewAdvancedOpts+    , commandAdvancedOptions = odesc commonAdvancedOpts     , commandBasicOptions = odesc whatsnewBasicOpts     , commandDefaults = defaultFlags whatsnewOpts     , commandCheckOptions = ocheck whatsnewOpts     , commandParseOptions = onormalise whatsnewOpts     }+  where+    whatsnewBasicOpts+      = O.maybeSummary Nothing+      ^ O.withContext+      ^ O.machineReadable+      ^ O.lookfor+      ^ O.diffAlgorithm+      ^ O.repoDir+      ^ O.interactive -- False+    whatsnewOpts = whatsnewBasicOpts `withStdOpts` commonAdvancedOpts  whatsnewDescription :: String whatsnewDescription = "List unrecorded changes in the working tree."@@ -207,9 +177,9 @@  "* `a f` and `a d/` respectively mean a new, but unadded, file or\n" ++  "  directory, when using `--look-for-adds`.\n" ++  "\n" ++- "  An exclamation mark (!) as in `R! foo.c`, means the hunk is known to\n" ++- "  conflict with a hunk in another patch.  The phrase `duplicated`\n" ++- "  means the hunk is known to be identical to a hunk in another patch.\n" +++ "  An exclamation mark (!) as in `R! foo.c`, means the change is known to\n" +++ "  conflict with a change in another patch.  The phrase `duplicated`\n" +++ "  means the change is known to be identical to a change in another patch.\n" ++  "\n" ++  "The `--machine-readable` option implies `--summary` while making it more\n" ++  "parsable. Modified files are only shown as `M f`, and moves are shown in\n" ++@@ -225,70 +195,96 @@  whatsnewCmd :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO () whatsnewCmd fps opts args =-   withRepository (useCache opts) $ RepoJob $ \(repo :: Repository rt p wR wU wR) -> do-    let scan = scanKnown (O.adds (parseFlags O.lookfor opts)) (parseFlags O.includeBoring opts)+   withRepository (useCache ? opts) $ RepoJob $ \(repo :: Repository rt p wR wU wR) -> do+    let scan = scanKnown (lookForAdds opts) (O.includeBoring ? opts)     existing_files <- do       files <- if null args then return Nothing                else Just . nubSort <$> fixSubPaths fps args       when (files == Just []) $ fail "No valid arguments were given."-      files' <- traverse (filterExistingPaths repo (verbosity opts) (useIndex opts) scan) files+      files' <- traverse+        (filterExistingPaths+          repo (verbosity ? opts) (useIndex ? opts) scan (lookForMoves opts))+        files       let files'' = fmap snd files'       when (files'' == Just []) $         fail "None of the files you specified exist."       return files''-    let isLookForMoves = lookForMoves opts == O.YesLookForMoves && parseFlags O.summary opts /= Just O.NoSummary-        isLookForAdds = lookForAdds opts == O.YesLookForAdds && parseFlags O.summary opts /= Just O.NoSummary-        isLookForReplaces = lookForReplaces opts == O.YesLookForReplaces-        isMachineReadable = parseFlags O.machineReadable opts-        -- LookForAdds and LookForMoves implies Summary, unless it's explcitly disabled.-        opts' | isLookForAdds     = (Summary : filter (\o -> LookForAdds /= o &&-                                                             LookForMoves /= o ) opts)-              | isMachineReadable = (Summary:opts)-              | otherwise         = opts-    movesPs <- if isLookForMoves-        then getMovesPs repo existing_files-        else return NilFL-    Sealed replacePs <- if isLookForReplaces-        then getReplaces (diffingOpts opts) repo existing_files-        else return (Sealed NilFL)-    Sealed noLookChanges <- filteredUnrecordedChanges opts' repo existing_files movesPs-                                                                       (unsafeCoerceP replacePs :: FL (PrimOf p) wR wR)++    -- get all unrecorded changes, possibly including unadded or even boring+    -- files if the appropriate options were supplied+    Sealed allInterestingChanges <-+      filteredUnrecordedChanges (diffingOpts opts)+        (lookForMoves opts) (lookForReplaces opts)+        repo existing_files++    -- get the recorded state     pristine <- readRecorded repo-    -- If we are looking for moves, return the corresponding FL of changes.-    -- If we are looking for adds, return the corresponding FL of changes.-    Sealed unaddedNewPathsPs <- if isLookForAdds++    -- the case --look-for-adds and --summary must be handled specially+    -- in order to distinguish added and unadded files++    -- TODO: it would be nice if we could return the pair+    -- (noLookChanges,unaddedNewPathsPs) in one go and also+    -- with proper witnesses (e.g. as noLookChanges +>+ unaddedNewPathsPs)+    -- This would also obviate the need for samePatchType.+    Sealed noLookChanges <-+      if haveLookForAddsAndSummary+        then+          -- do *not* look for adds here:+          filteredUnrecordedChanges (O.useIndex ? opts, O.ScanKnown, O.diffAlgorithm ? opts)+            (lookForMoves opts) (lookForReplaces opts)+            repo existing_files+        else return (Sealed NilFL)+    Sealed unaddedNewPathsPs <-+      if haveLookForAddsAndSummary         then do-            -- Use opts not opts', here, since we *do* want to look for adds.-            Sealed lookChanges <- filteredUnrecordedChanges opts repo existing_files movesPs (unsafeCoerceP replacePs :: FL (PrimOf p) wR wR)-            noLookAddsTree <- applyAddPatchesToPristine noLookChanges pristine-            lookAddsTree <- applyAddPatchesToPristine lookChanges pristine-            ftf <- filetypeFunction-            -- Return the patches that create files/dirs that aren't yet added.-            unFreeLeft <$> treeDiff (diffAlgorithm opts) ftf noLookAddsTree lookAddsTree+          noLookAddsTree <- applyAddPatchesToPristine noLookChanges pristine+          lookAddsTree <- applyAddPatchesToPristine allInterestingChanges pristine+          ftf <- filetypeFunction+          -- Return the patches that create files/dirs that aren't yet added.+          unFreeLeft <$> treeDiff (diffAlgorithm ? opts) ftf noLookAddsTree lookAddsTree         else return (Sealed NilFL)-    announceFiles (verbosity opts) existing_files "What's new in"-    exitOnNoChanges (unaddedNewPathsPs, noLookChanges)+    -- avoid ambiguous typing for unaddedNewPathsPs:+    samePatchType noLookChanges unaddedNewPathsPs++    exitOnNoChanges allInterestingChanges+    announceFiles (verbosity ? opts) existing_files "What's new in"     if maybeIsInteractive opts-      then runInteractive (interactiveHunks pristine) opts' pristine noLookChanges-      else do-        printChanges repo opts' pristine noLookChanges-        printUnaddedPaths unaddedNewPathsPs+      then+        runInteractive (interactiveHunks pristine) (patchSelOpts opts)+          (diffAlgorithm ? opts) pristine allInterestingChanges+      else+        if haveLookForAddsAndSummary+          then do+            printChanges pristine noLookChanges+            printUnaddedPaths unaddedNewPathsPs+          else do+            printChanges pristine allInterestingChanges   where-    -- |Filter out hunk patches (leaving add patches) and return the tree+    haveSummary = O.yes (getSummary opts)+    haveLookForAddsAndSummary = haveSummary && O.yes (lookForAdds opts)++    -- Filter out hunk patches (leaving add patches) and return the tree     -- resulting from applying the filtered patches to the pristine tree.     applyAddPatchesToPristine ps pristine = do         adds :> _ <- return $ partitionRL primIsHunk $ reverseFL ps         applyToTree (reverseRL adds) pristine -    exitOnNoChanges :: (FL p wX wY, FL p wU wV) -> IO ()-    exitOnNoChanges (NilFL, NilFL) = do putStrLn "No changes!"-                                        exitWith $ ExitFailure 1+    exitOnNoChanges :: FL p wX wY -> IO ()+    exitOnNoChanges NilFL = do putStrLn "No changes!"+                               exitWith $ ExitFailure 1     exitOnNoChanges _ = return () +    -- This function does nothing. Its purpose is to enforce the+    -- same patch type for the two passed FLs. This is necessary+    -- in order to avoid ambiguous typing for unaddedNewPathsPs.+    samePatchType :: FL p wX wY -> FL p wU wV -> IO ()+    samePatchType _ _ = return ()+     printUnaddedPaths :: PrimPatch p => FL p wX wY -> IO ()     printUnaddedPaths NilFL = return ()     printUnaddedPaths ps =-        putDocLn . lowercaseAs . renderString Encode . (plainSummaryPrims False []) $ ps+        putDocLn . lowercaseAs . renderString . (plainSummaryPrims False) $ ps      -- Make any add markers lowercase, to distinguish new-but-unadded files     -- from those that are unrecorded, but added.@@ -296,56 +292,55 @@     lowercaseA ('A' : x) = 'a' : x     lowercaseA x = x -    -- |Appropriately print changes, according to the passed flags.-    printChanges :: forall rt p wR wU wX wY. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree, ApplyState (PrimOf p) ~ Tree)-                 => Repository rt p wR wU wR -> [DarcsFlag] -> Tree IO -> FL (PrimOf p) wX wY+    -- Appropriately print changes, according to the passed flags.+    -- Note this cannot make distinction between unadded and added files.+    printChanges :: ( IsHunk p, ShowPatch p, ShowContextPatch p+                    , PatchListFormat p, Apply p+                    , PrimDetails p, ApplyState p ~ Tree)+                 => Tree IO -> FL p wX wY                  -> IO ()-    printChanges repo opts' pristine changes-        | Summary `elem` opts' = do-             r <- readRepo repo-             Sealed res <- return $ patchsetConflictResolutions r-             let conflictFns = map fp2fn $ nubSort $ listTouchedFiles res-             putDocLn $ plainSummaryPrims machineReadable conflictFns changes-        | isUnified opts' == O.YesContext = contextualPrintPatch pristine changes+    printChanges pristine changes+        | haveSummary = putDocLn $ plainSummaryPrims machineReadable changes+        | O.yes (withContext ? opts) = contextualPrintPatch pristine changes         | otherwise = printPatch changes      where machineReadable = parseFlags O.machineReadable opts -    -- |return the unrecorded changes that affect an optional list of paths.-    filteredUnrecordedChanges :: forall rt p wR wU wT. (RepoPatch p, ApplyState p ~ Tree,-                                                        ApplyState (PrimOf p) ~ Tree)-                              => [DarcsFlag]+    -- return the unrecorded changes that affect an optional list of paths.+    filteredUnrecordedChanges :: forall rt p wR wU wT. (RepoPatch p, ApplyState p ~ Tree)+                              => (O.UseIndex, O.ScanKnown, O.DiffAlgorithm)+                              -> O.LookForMoves+                              -> O.LookForReplaces                               -> Repository rt p wR wU wT -> Maybe [SubPath]-                              -> FL (PrimOf p) wR wT -- look-for-moves patches-                              -> FL (PrimOf p) wT wT -- look-for-replaces patches                               -> IO (Sealed (FL (PrimOf p) wT))-    filteredUnrecordedChanges  opts' repo files movesPs replacesPs =+    filteredUnrecordedChanges diffing lfm lfr repo files =         let filePaths = map toFilePath <$> files in-        choosePreTouching filePaths <$> unrecordedChangesWithPatches movesPs replacesPs (diffingOpts opts') repo files+        choosePreTouching filePaths <$>+          unrecordedChanges diffing lfm lfr repo files  -- | Runs the 'InteractiveSelectionM' code-runInteractive :: (PatchListFormat p, IsHunk p, Patchy p, ShowPatch p,-                     PrimPatch p, PatchInspect p, PrimDetails p,-                     ApplyState p ~ Tree)+runInteractive :: PrimPatch p                => InteractiveSelectionM p wX wY () -- Selection to run-               -> [DarcsFlag]     -- Command-line options+               -> S.PatchSelectionOptions+               -> O.DiffAlgorithm                -> Tree IO         -- Pristine                -> FL p wX wY      -- A list of patches                -> IO ()-runInteractive i opts pristine ps' = do-    let (choices',lps') = patchChoicesLps ps'-    let ps = evalStateT i $+runInteractive i patchsel diffalg pristine ps' = do+    let lps' = labelPatches Nothing ps'+        choices' = mkPatchChoices lps'+        ps = evalStateT i $              ISC { total   = lengthFL lps'                  , current = 0                  , lps     = FZipper NilRL lps'                  , choices = choices'                  }     void $ runReaderT ps $-           selectionContextPrim First "view" (patchSelOpts opts)-             (Just (primSplitter (diffAlgorithm opts)))+           selectionContextPrim First "view" patchsel+             (Just (primSplitter diffalg))              Nothing (Just pristine)  -- | The interactive part of @darcs whatsnew@-interactiveHunks :: (PatchListFormat p, IsHunk p, Patchy p, ShowPatch p,+interactiveHunks :: (IsHunk p, ShowPatch p, ShowContextPatch p, Commute p,                      PatchInspect p, PrimDetails p, ApplyState p ~ Tree)                  => Tree IO -> InteractiveSelectionM p wX wY () interactiveHunks pristine = do@@ -353,7 +348,7 @@     case c of         Nothing -> liftIO $ putStrLn "No more changes!"         Just (Sealed2 lp) -> do-            liftIO $ printPatch (lpPatch lp)+            liftIO $ printPatch (unLabel lp)             repeatThis lp   where     repeatThis lp = do@@ -362,14 +357,14 @@                 (PromptConfig thePrompt (keysFor basic_options) (keysFor adv_options)                  (Just 'n') "?h")         case yorn of-            -- View hunk in context-            'v' -> liftIO (contextualPrintPatch pristine (lpPatch lp))+            -- View change in context+            'v' -> liftIO (contextualPrintPatch pristine (unLabel lp))                    >> repeatThis lp             -- View summary of the change-            'x' -> liftIO (printSummary (lpPatch lp))+            'x' -> liftIO (printSummary (unLabel lp))                    >> repeatThis lp-            -- View hunk and move on-            'y' -> liftIO (contextualPrintPatch pristine (lpPatch lp))+            -- View change and move on+            'y' -> liftIO (contextualPrintPatch pristine (unLabel lp))                    >> decide True lp >> next_hunk             -- Go to the next patch             'n' -> decide False lp >> next_hunk@@ -379,12 +374,12 @@                     (return ())                     (\f -> decideWholeFile f False)                 next_hunk-            -- View hunk in a pager-            'p' -> liftIO (printPatchPager $ lpPatch lp)+            -- View change in a pager+            'p' -> liftIO (printPatchPager $ unLabel lp)                    >> repeatThis lp-            -- Next hunk+            -- Next change             'j' -> next_hunk-            -- Previous hunk+            -- Previous change             'k' -> prev_hunk             -- Start from the first change             'g' -> start_over@@ -397,34 +392,49 @@     next_hunk  = skipOne >> skipMundane >> interactiveHunks pristine     prev_hunk  = backOne >> interactiveHunks pristine     options_yn =-        [ KeyPress 'v' "view this hunk in a context"-        , KeyPress 'y'-          "view this hunk in a context and go to the next one"-        , KeyPress 'n' "go to the next hunk" ]+        [ KeyPress 'v' "view this change in a context"+        , KeyPress 'y' "view this change in a context and go to the next one"+        , KeyPress 'n' "skip this change and its dependencies" ]     optionsView =-        [ KeyPress 'p' "view this hunk in context wih pager "-        , KeyPress 'x' "view a summary of this patch"+        [ KeyPress 'p' "view this change in context wih pager "+        , KeyPress 'x' "view a summary of this change"         ]     optionsNav =         [ KeyPress 'q' "quit whatsnew"         , KeyPress 's' "skip the rest of the changes to this file"-        , KeyPress 'j' "skip to the next hunk"-        , KeyPress 'k' "back up to previous hunk"-        , KeyPress 'g' "start over from the first hunk"+        , KeyPress 'j' "go to the next change"+        , KeyPress 'k' "back up to previous change"+        , KeyPress 'g' "start over from the first change"         ]     basic_options = [ options_yn ]     adv_options = [ optionsView, optionsNav ] --- |status is an alias for whatsnew, with implicit Summary and LookForAdds++-- | status is an alias for whatsnew, with implicit Summary and LookForAdds -- flags. We override the default description, to include the implicit flags. status :: DarcsCommand [DarcsFlag]-status = statusAlias { commandCommand = statusCmd-                     , commandDescription = statusDesc-                     }+status = statusAlias+    { commandDescription = statusDesc+    , commandAdvancedOptions = odesc commonAdvancedOpts+    , commandBasicOptions = odesc statusBasicOpts+    , commandDefaults = defaultFlags statusOpts+    , commandCheckOptions = ocheck statusOpts+    , commandParseOptions = onormalise statusOpts+    }   where     statusAlias = commandAlias "status" Nothing whatsnew-    statusCmd fps fs = commandCommand whatsnew fps (Summary : LookForAdds : fs)     statusDesc = "Alias for `darcs " ++ commandName whatsnew ++ " -ls '."+    statusBasicOpts+      = O.maybeSummary (Just O.YesSummary)+      ^ O.withContext+      ^ O.machineReadable+      ^ O.lookforadds O.YesLookForAdds+      ^ O.lookforreplaces+      ^ O.lookformoves+      ^ O.diffAlgorithm+      ^ O.repoDir+      ^ O.interactive+    statusOpts = statusBasicOpts `withStdOpts` commonAdvancedOpts  maybeIsInteractive :: [DarcsFlag] -> Bool maybeIsInteractive = maybe False id . parseFlags O.interactive
src/Darcs/UI/CommandsAux.hs view
@@ -15,9 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}-- module Darcs.UI.CommandsAux     ( checkPaths     , maliciousPatches
+ src/Darcs/UI/Completion.hs view
@@ -0,0 +1,185 @@+-- | How to complete arguments+{-# LANGUAGE RecordWildCards, NamedFieldPuns #-}+module Darcs.UI.Completion+    ( fileArgs, knownFileArgs, unknownFileArgs, modifiedFileArgs+    , noArgs, prefArgs+    ) where++import Prelude ()+import Darcs.Prelude++import Data.List ( (\\), stripPrefix )+import Data.List.Ordered ( nubSort, minus )+import Data.Maybe ( mapMaybe )++import Darcs.Patch ( listTouchedFiles )++import Darcs.Repository.Flags+    ( UseCache(..)+    )+import Darcs.Repository.Prefs+    ( getPreflist+    )+import Darcs.Repository.Job+    ( RepoJob(..)+    , withRepository+    )+import Darcs.Repository.State+    ( readRecordedAndPending+    , readUnrecordedFiltered+    , unrecordedChanges+    , restrictDarcsdir+    , applyTreeFilter+    , TreeFilter(..)+    )++import Darcs.UI.Flags ( DarcsFlag )+import qualified Darcs.UI.Flags as Flags+import qualified Darcs.UI.Options.All as O++import Darcs.Util.File+    ( doesDirectoryReallyExist+    )+import Darcs.Util.Global+    ( darcsdir+    )+import Darcs.Util.Path+    ( AnchoredPath, anchorPath+    , AbsolutePath, toPath, floatSubPath, makeSubPathOf+    )+import Darcs.Util.Tree as Tree+    ( Tree, ItemType(..)+    , expand, expandPath, list, findTree, itemType, emptyTree+    )+import Darcs.Util.Tree.Plain ( readPlainTree )++-- | Return all files available under the original working+-- directory regardless of their repo state.+-- Subdirectories get a separator (slash) appended.+fileArgs :: (AbsolutePath, AbsolutePath)+         -> [DarcsFlag]+         -> [String]+         -> IO [FilePath]+fileArgs (_, orig) _flags args =+  notYetListed args $+  fmap (map anchoredToFilePath . listItems) $+  Tree.expand . applyTreeFilter restrictDarcsdir =<< readPlainTree (toPath orig)++-- | Return all files available under the original working directory that+-- are unknown to darcs but could be added.+-- Subdirectories get a separator (slash) appended.+unknownFileArgs :: (AbsolutePath, AbsolutePath)+                -> [DarcsFlag]+                -> [String]+                -> IO [FilePath]+unknownFileArgs fps flags args = notYetListed args $ do+  let sk = if Flags.includeBoring flags then O.ScanBoring else O.ScanAll+      lfm = Flags.lookForMoves flags+      lfr = Flags.lookForReplaces flags+  RepoTrees {have, known} <- repoTrees O.UseIndex sk lfm lfr+  known_paths <- listHere known fps+  have_paths <- listHere have fps+  return $ map anchoredToFilePath $ nubSort have_paths `minus` nubSort known_paths++-- | Return all files available under the original working directory that+-- are known to darcs (either recorded or pending).+-- Subdirectories get a separator (slash) appended.+knownFileArgs :: (AbsolutePath, AbsolutePath)+              -> [DarcsFlag]+              -> [String]+              -> IO [FilePath]+knownFileArgs fps flags args = notYetListed args $ do+  let (ui, sk, _) = Flags.diffingOpts flags+      lfm = Flags.lookForMoves flags+      lfr = Flags.lookForReplaces flags+  RepoTrees {known} <- repoTrees ui sk lfm lfr+  map anchoredToFilePath <$> listHere known fps++-- | Return all files available under the original working directory that+-- are modified (relative to the recorded state).+-- Subdirectories get a separator (slash) appended.+modifiedFileArgs :: (AbsolutePath, AbsolutePath)+                 -> [DarcsFlag]+                 -> [String]+                 -> IO [FilePath]+modifiedFileArgs fps flags args = notYetListed args $ do+  let (ui, sk, _) = Flags.diffingOpts flags+      lfm = Flags.lookForMoves flags+      lfr = Flags.lookForReplaces flags+  RepoTrees {new} <- repoTrees ui sk lfm lfr+  case uncurry makeSubPathOf fps of+    Nothing -> return []+    Just here ->+      return $ mapMaybe (stripPathPrefix (toPath here) . drop 2) new++-- | Return the available prefs of the given kind.+prefArgs :: String+         -> (AbsolutePath, AbsolutePath)+         -> [DarcsFlag]+         -> [String]+         -> IO [String]+prefArgs name _ _ _ = getPreflist name++-- | Return an empty list.+noArgs :: (AbsolutePath, AbsolutePath) -> [DarcsFlag] -> [String] -> IO [String]+noArgs _ _ _ = return []++-- * unexported helper functions++data RepoTrees m = RepoTrees+  { have  :: Tree m -- ^ working tree+  , known :: Tree m -- ^ recorded and pending+  , new :: [FilePath] -- ^ unrecorded paths+  }++repoTrees :: O.UseIndex -> O.ScanKnown -> O.LookForMoves -> O.LookForReplaces+          -> IO (RepoTrees IO)+repoTrees ui sk lfm lfr = do+  inDarcsRepo <- doesDirectoryReallyExist darcsdir+  if inDarcsRepo then+    withRepository NoUseCache $ RepoJob $ \r -> do+      known <- readRecordedAndPending r+      have <- readUnrecordedFiltered r ui sk lfm Nothing+      -- we are only interested in the affected paths so the diff+      -- algorithm is irrelevant+      new <- listTouchedFiles <$> unrecordedChanges (ui, sk, O.MyersDiff) lfm lfr r Nothing+      return $ RepoTrees {..}+  else+    return RepoTrees {have = emptyTree, known = emptyTree, new = []}++-- this is for completion which should give us everything under the original wd+subtreeHere :: Tree IO -> (AbsolutePath, AbsolutePath) -> IO (Maybe (Tree IO))+subtreeHere tree fps =+  case floatSubPath <$> uncurry makeSubPathOf fps of+    Nothing -> do+      return Nothing -- here is no subtree of the repo+    Just here -> do+      flip findTree here <$> expandPath tree here++listHere :: Tree IO+         -> (AbsolutePath, AbsolutePath)+         -> IO [(AnchoredPath, ItemType)]+listHere tree fps = do+  msubtree <- subtreeHere tree fps+  case msubtree of+    Nothing -> return []+    Just subtree -> listItems <$> expand subtree++listItems :: Tree m -> [(AnchoredPath, ItemType)]+listItems = map (\(p, i) -> (p, itemType i)) . Tree.list++anchoredToFilePath :: (AnchoredPath, ItemType) -> [Char]+anchoredToFilePath (path, TreeType) = anchorPath "" path -- ++ "/"+anchoredToFilePath (path, BlobType) = anchorPath "" path++stripPathPrefix :: FilePath -> FilePath -> Maybe FilePath+stripPathPrefix = stripPrefix . addSlash where+  addSlash [] = []+  addSlash xs = xs ++ "/"++-- | Turn an action that creates all possible completions into one+-- that removes already given arguments.+notYetListed :: [String] -> IO [String] -> IO [String]+notYetListed already complete = do+  possible <- complete+  return $ possible \\ already
src/Darcs/UI/Defaults.hs view
@@ -6,7 +6,7 @@ import Control.Monad.Writer import Data.Char ( isSpace ) import Data.Functor.Compose ( Compose(..) )-import Data.List ( nub, intercalate )+import Data.List ( nub ) import Data.Maybe ( catMaybes ) import qualified Data.Map as M import System.Console.GetOpt@@ -85,11 +85,9 @@ showCmdName (NormalCmd name) = name  runChecks :: String -> ([DarcsFlag] -> [String]) -> [DarcsFlag] -> Writer [String] [DarcsFlag]-runChecks source check fs = case check fs of-  [] -> return fs-  es -> do-    tell [intercalate "\n" $ map ((source++": ")++) es]-    return fs+runChecks source check fs = do+  tell $ map ((source++": ")++) $ check fs+  return fs  -- | Parse a list of lines from a defaults file, returning a list of 'DarcsFlag', -- given the current working directory, the command name, and a list of 'DarcsOption'
src/Darcs/UI/Email.hs view
@@ -1,8 +1,9 @@-{-# LANGUAGE CPP #-} module Darcs.UI.Email     ( makeEmail     , readEmail     , formatHeader+    -- just for testing+    , prop_qp_roundtrip     ) where  import Prelude ()@@ -11,14 +12,12 @@ import Data.Char ( digitToInt, isHexDigit, ord, intToDigit, isPrint, toUpper ) import Data.List ( isInfixOf ) import Darcs.Util.Printer-    ( Doc, ($$), (<+>), (<>), text, empty, packedString, renderPS-    , RenderMode(..)-    )+    ( Doc, ($$), (<+>), (<>), text, empty, packedString, renderPS )  import Darcs.Util.ByteString ( packStringToUTF8, dropSpace, linesPS, betweenLinesPS ) import qualified Data.ByteString          as B  (ByteString, length, null, tail                                                 ,drop, head, concat, singleton-                                                ,pack, append, empty, unpack+                                                ,pack, append, empty, unpack, snoc                                                 ) import qualified Data.ByteString.Char8    as BC (index, head, pack) import Data.ByteString.Internal as B (c2w, createAndTrim)@@ -131,7 +130,8 @@         word8ToUDigit :: Word8 -> Char         word8ToUDigit = toUpper . intToDigit . fromIntegral --- TODO is this doing mime encoding??+-- Encode a ByteString according to "Quoted Printable" defined by MIME+-- (https://tools.ietf.org/html/rfc2045#section-6.7) qpencode :: B.ByteString -> B.ByteString qpencode s = unsafePerformIO            -- Really only (3 + 2/75) * length or something in the worst case@@ -143,7 +143,7 @@   c | c == newline ->         do poke (buf `plusPtr` bufi) newline            encode ps' qlineMax buf (bufi+1)-    | n == 0 && B.length ps > 1 ->+    | n == 0 && B.length ps >= 1 ->         do poke (buf `plusPtr` bufi) equals            poke (buf `plusPtr` (bufi+1)) newline            encode ps qlineMax buf (bufi + 2)@@ -220,7 +220,7 @@               fromMaybe "x-unknown" mcharset ++ "\"")          $$ text "Content-Transfer-Encoding: quoted-printable"          $$ text ""-         $$ packedString (qpencode (renderPS Standard contents))+         $$ packedString (qpencode (renderPS contents))          $$ text ""          $$ text "--=_"        Nothing -> empty)@@ -229,10 +229,10 @@  $$ text "Content-Transfer-Encoding: quoted-printable"  $$ text "Content-Description: Patch preview"  $$ text ""- $$ (case betweenLinesPS (BC.pack "New patches:") (BC.pack "Context:") (renderPS Standard bundle) of+ $$ (case betweenLinesPS (BC.pack "New patches:") (BC.pack "Context:") (renderPS bundle) of      Just s -> packedString $ qpencode s      -- this should not happen, but in case it does, keep everything-     Nothing -> packedString $ qpencode $ renderPS Standard bundle)+     Nothing -> packedString $ qpencode $ renderPS bundle)  $$ text "--=_"  $$ text "Content-Type: application/x-darcs-patch" <>       (case mfilename of@@ -242,7 +242,7 @@  $$ text "Content-Disposition: attachment"  $$ text "Content-Description: A darcs patch for your repository!"  $$ text ""- $$ packedString (qpencode (renderPS Standard bundle))+ $$ packedString (qpencode (renderPS bundle))  $$ text "--=_--"  $$ text ""  $$ text "."@@ -257,3 +257,6 @@     Nothing -> s -- if it wasn't an email in the first place, just pass along.     Just s' -> qpdecode s' +-- note: qpdecode appends an extra '\n'+prop_qp_roundtrip :: B.ByteString -> Bool+prop_qp_roundtrip s = B.snoc s 10 == (qpdecode . qpencode) s
src/Darcs/UI/External.hs view
@@ -28,6 +28,7 @@  import Prelude () import Darcs.Prelude+import Darcs.Util.Text ( showCommandLine )  import Data.Maybe ( isJust, isNothing, maybeToList ) import Control.Monad ( unless, when, filterM, liftM2, void )@@ -35,11 +36,7 @@ import System.Exit ( ExitCode(..) ) import System.Environment     ( getEnv-#if __GLASGOW_HASKELL__ >= 706     , getExecutablePath-#else-    , getProgName-#endif     ) import System.IO ( hPutStr, hPutStrLn, hClose,                    hIsTerminalDevice, stdout, stderr, Handle )@@ -49,7 +46,10 @@ import System.Process ( createProcess, proc, CreateProcess(..), runInteractiveProcess, waitForProcess, StdStream(..) ) import System.Process.Internals ( ProcessHandle ) -import GHC.IO.Encoding ( setFileSystemEncoding, setForeignEncoding, char8 )+import GHC.IO.Encoding+    ( getFileSystemEncoding+    , setForeignEncoding+    , setLocaleEncoding )  import Foreign.C.String ( CString, peekCString ) @@ -95,7 +95,7 @@ import Darcs.Util.Printer ( Doc, Printers, hPutDocLnWith, hPutDoc, hPutDocLn, hPutDocWith, ($$), renderPS,                  simplePrinters,                  hPutDocCompr,-                 text, empty, packedString, vcat, renderString, RenderMode(..) )+                 text, empty, packedString, vcat, renderString ) import qualified Darcs.Util.Ratified as Ratified import Darcs.UI.Email ( formatHeader ) @@ -116,28 +116,24 @@  -- |Get the name of the darcs executable (as supplied by @getExecutablePath@) darcsProgram :: IO String-#if __GLASGOW_HASKELL__ >= 706 darcsProgram = getExecutablePath-#else-darcsProgram = getProgName-#endif -pipeDoc :: RenderMode -> String -> [String] -> Doc -> IO ExitCode+pipeDoc :: String -> [String] -> Doc -> IO ExitCode pipeDoc = pipeDocInternal (PipeToOther simplePrinters)  data WhereToPipe = PipeToSsh Compression -- ^ if pipe to ssh, can choose to compress or not                  | PipeToOther Printers  -- ^ otherwise, can specify printers -pipeDocInternal :: WhereToPipe -> RenderMode -> String -> [String] -> Doc -> IO ExitCode-pipeDocInternal whereToPipe target c args inp = withoutNonBlock $ withoutProgress $-    do debugMessage $ unwords (c:args)+pipeDocInternal :: WhereToPipe -> String -> [String] -> Doc -> IO ExitCode+pipeDocInternal whereToPipe c args inp = withoutNonBlock $ withoutProgress $+    do debugMessage $ "Exec: " ++ showCommandLine (c:args)        (Just i,_,_,pid) <- createProcess (proc c args){ std_in = CreatePipe-                                                   {- , delegate_ctlc = True -- requires process 1.2.2.0 -} }+                                                      , delegate_ctlc = True}        debugMessage "Start transferring data"        case whereToPipe of-          PipeToSsh GzipCompression -> hPutDocCompr target i inp-          PipeToSsh NoCompression   -> hPutDoc target i inp-          PipeToOther printers      -> hPutDocWith printers target i inp+          PipeToSsh GzipCompression -> hPutDocCompr i inp+          PipeToSsh NoCompression   -> hPutDoc i inp+          PipeToOther printers      -> hPutDocWith printers i inp        hClose i        rval <- waitForProcess pid        debugMessage "Finished transferring data"@@ -145,10 +141,10 @@             putStrLn $ "Command not found:\n   "++ show (c:args)        return rval -pipeDocSSH :: Compression -> RenderMode -> SshFilePath -> [String] -> Doc -> IO ExitCode-pipeDocSSH compress target remoteAddr args input = do+pipeDocSSH :: Compression -> SshFilePath -> [String] -> Doc -> IO ExitCode+pipeDocSSH compress remoteAddr args input = do     (ssh, ssh_args) <- getSSH SSH-    pipeDocInternal (PipeToSsh compress) target ssh (ssh_args++ (sshUhost remoteAddr:args)) input+    pipeDocInternal (PipeToSsh compress) ssh (ssh_args ++ ("--":sshUhost remoteAddr:args)) input  sendEmail :: String -> String -> String -> String -> String -> String -> IO () sendEmail f t s cc scmd body =@@ -169,7 +165,7 @@      putHeader "Subject" s      unless (null cc) $ putHeader "Cc" cc      putHeader "X-Mail-Originator" "Darcs Version Control System"-     hPutDocLn Standard h body+     hPutDocLn h body   where putHeader field value             = B.hPut h (B.append (formatHeader field value) newline)         newline = B.singleton 10@@ -200,10 +196,10 @@       withOpenTemp $ \(hat,at) -> do         ftable' <- case mbundle of                    Just (content,bundle) -> do-                       hPutDocLn Standard hat bundle-                       return [ ('b', renderString Standard content) , ('a', at) ]+                       hPutDocLn hat bundle+                       return [ ('b', renderString content) , ('a', at) ]                    Nothing ->-                       return [ ('b', renderString Standard body) ]+                       return [ ('b', renderString body) ]         hClose hat         let ftable = [ ('t',addressOnly t),('c',cc),('f',f),('s',s) ] ++ ftable'         r <- execSendmail ftable scmd fn@@ -217,7 +213,7 @@             withCString cc $ \ccp ->              withCString s $ \sp ->               withOpenTemp $ \(h,fn) -> do-               hPutDoc Standard h body+               hPutDoc h body                hClose h                writeDocBinFile "mailed_patch" body                cfn <- canonFilename fn@@ -245,7 +241,7 @@      hPutStrLn h $ "To: "++ t      hPutStrLn h $ find_from (linesPS body)      hPutStrLn h $ find_subject (linesPS body)-     hPutDocLn Standard h $ fixit $ linesPS body+     hPutDocLn h $ fixit $ linesPS body      hClose h      let ftable = [('t',t)]      r <-  execSendmail ftable scmd fn@@ -299,15 +295,15 @@ #endif  execPSPipe :: String -> [String] -> B.ByteString -> IO B.ByteString-execPSPipe c args ps = fmap (renderPS Standard)-                     $ execDocPipe Standard c args+execPSPipe c args ps = fmap renderPS+                     $ execDocPipe c args                      $ packedString ps -execAndGetOutput :: RenderMode -> FilePath -> [String] -> Doc+execAndGetOutput :: FilePath -> [String] -> Doc                  -> IO (ProcessHandle, MVar (), B.ByteString)-execAndGetOutput target c args instr = do+execAndGetOutput c args instr = do        (i,o,e,pid) <- runInteractiveProcess c args Nothing Nothing-       _ <- forkIO $ hPutDoc target i instr >> hClose i+       _ <- forkIO $ hPutDoc i instr >> hClose i        mvare <- newEmptyMVar        _ <- forkIO ((Ratified.hGetContents e >>= -- ratify: immediately consumed                 hPutStr stderr)@@ -315,9 +311,9 @@        out <- B.hGetContents o        return (pid, mvare, out) -execDocPipe :: RenderMode -> String -> [String] -> Doc -> IO Doc-execDocPipe target c args instr = withoutProgress $ do-       (pid, mvare, out) <- execAndGetOutput target c args instr+execDocPipe :: String -> [String] -> Doc -> IO Doc+execDocPipe c args instr = withoutProgress $ do+       (pid, mvare, out) <- execAndGetOutput c args instr        rval <- waitForProcess pid        takeMVar mvare        case rval of@@ -327,9 +323,9 @@  -- The following is needed for diff, which returns non-zero whenever -- the files differ.-execPipeIgnoreError :: RenderMode -> String -> [String] -> Doc -> IO Doc-execPipeIgnoreError target c args instr = withoutProgress $ do-       (pid, mvare, out) <- execAndGetOutput target c args instr+execPipeIgnoreError :: String -> [String] -> Doc -> IO Doc+execPipeIgnoreError c args instr = withoutProgress $ do+       (pid, mvare, out) <- execAndGetOutput c args instr        _ <- waitForProcess pid        takeMVar mvare        return $ if B.null out then empty else packedString out@@ -341,7 +337,7 @@ signString (SignSSL idf) d = signSSL idf d  signPGP :: [String] -> Doc -> IO Doc-signPGP args = execDocPipe Standard "gpg" ("--clearsign":args)+signPGP args = execDocPipe "gpg" ("--clearsign":args)  signSSL :: String -> Doc -> IO Doc signSSL idfile t =@@ -356,7 +352,7 @@                 >>= B.writeFile cert     opensslDoc ["smime", "-sign", "-signer", cert,                 "-inkey", idfile, "-noattr", "-text"] t-    where opensslDoc = execDocPipe Standard "openssl"+    where opensslDoc = execDocPipe "openssl"           opensslPS = execPSPipe "openssl"  @@ -418,27 +414,27 @@     where opensslPS = execPSPipe "openssl"  viewDoc :: Doc -> IO ()-viewDoc = viewDocWith simplePrinters Encode+viewDoc = viewDocWith simplePrinters -viewDocWith :: Printers -> RenderMode -> Doc -> IO ()-viewDocWith pr mode msg = do+viewDocWith :: Printers -> Doc -> IO ()+viewDocWith pr msg = do   isTerminal <- hIsTerminalDevice stdout-  void $ if isTerminal && lengthGreaterThan (20 :: Int) (lines $ renderString mode msg)+  void $ if isTerminal && lengthGreaterThan (20 :: Int) (lines $ renderString msg)      then do mbViewerPlusArgs <- getViewer              case mbViewerPlusArgs of                   Just viewerPlusArgs -> do                     let (viewer : args) = words viewerPlusArgs-                    pipeDocToPager viewer args pr mode msg+                    pipeDocToPager viewer args pr msg                   Nothing -> return $ ExitFailure 127 -- No such command                -- TEMPORARY passing the -K option should be removed as soon as                -- we can use the delegate_ctrl_c feature in process-               `ortryrunning` pipeDocToPager  "less" ["-RK"] pr mode msg-               `ortryrunning` pipeDocToPager  "more" [] pr mode msg+               `ortryrunning` pipeDocToPager  "less" ["-RK"] pr msg+               `ortryrunning` pipeDocToPager  "more" [] pr msg #ifdef WIN32-               `ortryrunning` pipeDocToPager  "more.com" [] pr mode msg+               `ortryrunning` pipeDocToPager  "more.com" [] pr msg #endif-               `ortryrunning` pipeDocToPager "" [] pr mode msg-     else pipeDocToPager "" [] pr mode msg+               `ortryrunning` pipeDocToPager "" [] pr msg+     else pipeDocToPager "" [] pr msg               where lengthGreaterThan n _ | n <= 0 = True                     lengthGreaterThan _ [] = False                     lengthGreaterThan n (_:xs) = lengthGreaterThan (n-1) xs@@ -448,13 +444,13 @@             `catchall`             return Nothing -pipeDocToPager :: String -> [String] -> Printers -> RenderMode -> Doc -> IO ExitCode+pipeDocToPager :: String -> [String] -> Printers -> Doc -> IO ExitCode -pipeDocToPager "" _ pr mode inp = do-  hPutDocLnWith pr mode stdout inp+pipeDocToPager "" _ pr inp = do+  hPutDocLnWith pr stdout inp   return ExitSuccess -pipeDocToPager c args pr mode inp = pipeDocInternal (PipeToOther pr) mode c args inp+pipeDocToPager c args pr inp = pipeDocInternal (PipeToOther pr) c args inp  -- | Given two shell commands as arguments, execute the former.  The -- latter is then executed if the former failed because the executable@@ -522,7 +518,6 @@  getEditor :: IO String getEditor = getEnv "DARCS_EDITOR" `catchall`-             getEnv "DARCSEDITOR" `catchall`              getEnv "VISUAL" `catchall`              getEnv "EDITOR" `catchall` return "nano" @@ -532,37 +527,45 @@ a `catchall` b = a `catchNonSignal` (\_ -> b)  --- | In some environments, darcs requires that certain global GHC library variables that--- control the encoding used in internal translations are set to specific values.+-- | On Posix systems, GHC by default uses the user's locale encoding to+-- determine how to decode/encode the raw byte sequences in the Posix API+-- to/from 'String'. It also uses certain special variants of this+-- encoding to determine how to handle encoding errors. ----- @setDarcsEncoding@ enforces those settings, and should be called before the--- first time any darcs operation is run, and again if anything else might have--- set those encodings to different values.+-- See "GHC.IO.Encoding" for details. ----- Note that it isn't thread-safe and has a global effect on your program.+-- In particular, the default variant used for command line arguments and+-- environment variables is //ROUNDTRIP, which means that /any/ byte sequence+-- can be decoded and re-encoded w/o failure or loss of information. To+-- enable this, GHC uses code points that are outside the range of the regular+-- unicode set. This is what you get with 'getFileSystemEncoding'. ----- The current behaviour of this function is as follows, though this may--- change in future:+-- We need to preserve the raw bytes e.g. for file names passed in by the+-- user and also when reading file names from disk; also when re-generating+-- files from patches, and when we display them to the user. ----- Encodings are only set on GHC 7.4 and up, on any non-Windows platform.+-- So we want to use this encoding variant for *all* IO and for (almost) all+-- conversions between raw bytes and 'String's. The encoding used for IO from+-- and to handles is controlled by 'setLocaleEncoding' which we use here to+-- make it equal to the //ROUNDTRIP variant. ----- Two encodings are set, both to @GHC.IO.Encoding.char8@:--- @GHC.IO.Encoding.setFileSystemEncoding@ and @GHC.IO.Encoding.setForeignEncoding@.+-- @setDarcsEncoding@ should be called before the+-- first time any darcs operation is run, and again if anything else might have+-- set those encodings to different values. ----- Prevent HLint from warning us about a redundant do if the macro isn't--- defined:+-- Note that it isn't thread-safe and has a global effect on your program.+--+-- On Windows, this function does (and should) not do anything. setDarcsEncodings :: IO ()+#ifdef WIN32+setDarcsEncodings = return ()+#else setDarcsEncodings = do---- This is needed for appropriate behaviour from getArgs and from general--- filesystem calls (e.g. getDirectoryContents, readFile, ...)-    setFileSystemEncoding char8---- This ensures that foreign calls made by hashed-storage to stat--- filenames returned from getDirectoryContents are translated appropriately-    setForeignEncoding char8--    return ()+    e <- getFileSystemEncoding+    -- TODO check if we have to set this, too.+    setForeignEncoding e+    setLocaleEncoding e+#endif  -- The following functions are copied from the encoding package (BSD3 -- licence, by Henning Günther).
src/Darcs/UI/Flags.hs view
@@ -17,59 +17,35 @@  {-# LANGUAGE OverloadedStrings #-} module Darcs.UI.Flags-    ( -- TODO we want to stop exporting the constructors of DarcsFlag-      -- from here. First need to change all the relevant code over to the-      -- using helpers from this module instead.-      F.DarcsFlag( .. )-    , compression+    ( F.DarcsFlag+        -- FIXME these are temporary exceptions+        ( WorkRepoDir -- init+        , NewRepo     -- convert, clone+        , UpToPattern -- clone --to-xxx -> -xxx hack+        , UpToPatch   -- same+        , UpToHash    -- same+        , OnePattern  -- same+        , OnePatch    -- same+        , OneHash     -- same+        )     , remoteDarcs-    , reorder-    , minimize-    , editDescription     , diffingOpts     , diffOpts     , scanKnown-    , externalMerge     , wantGuiPause     , isInteractive-    , maxCount     , willRemoveLogFile-    , isUnified-    , doHappyForwarding     , includeBoring-    , doAllowCaseOnly-    , doAllowWindowsReserved-    , doReverse-    , usePacks-    , showChangesOnlyToFiles-    , removeFromAmended-    , toMatchFlags-    , verbosity-    , useCache-    , umask-    , dryRun     , lookForAdds     , lookForMoves     , lookForReplaces-    , diffAlgorithm-    , runTest-    , testChanges-    , setScriptsExecutable-    , withWorkingDir-    , leaveTestDir-    , remoteRepos     , setDefault-    , cloneKind-    , workRepo     , allowConflicts-    , runPatchIndex-    , useIndex-    , hasSummary     , hasXmlOutput-    , selectDeps-    , hasAuthor     , hasLogfile-    , patchFormat+    , quiet+    , verbose+    , enumeratePatches      , fixRemoteRepos     , fixUrl@@ -83,15 +59,53 @@     , fileHelpAuthor     , environmentHelpEmail     , getSubject-    , getCharset     , getInReplyTo     , getCc     , environmentHelpSendmail-    , siblings     , getOutput     , getDate-    , getReply-    , applyAs++    -- * Re-exports+    , O.compress+    , O.diffAlgorithm+    , O.reorder+    , O.minimize+    , O.editDescription+    , O.externalMerge+    , O.maxCount+    , O.matchAny+    , O.withContext+    , O.happyForwarding+    , O.allowCaseDifferingFilenames+    , O.allowWindowsReservedFilenames+    , O.changesReverse+    , O.usePacks+    , O.onlyToFiles+    , O.amendUnrecord+    , O.verbosity+    , O.useCache+    , O.useIndex+    , O.umask+    , O.dryRun+    , O.runTest+    , O.testChanges+    , O.setScriptsExecutable+    , O.withWorkingDir+    , O.leaveTestDir+    , O.remoteRepos+    , O.cloneKind+    , O.workRepo+    , O.patchIndexNo+    , O.patchIndexYes+    , O.xmlOutput+    , O.selectDeps+    , O.author+    , O.reply+    , O.patchFormat+    , O.charset+    , O.siblings+    , O.applyAs+    , O.enumPatches     ) where  import Prelude ()@@ -107,28 +121,25 @@ import Control.Monad ( unless ) import System.Directory ( doesDirectoryExist, createDirectory ) import System.FilePath.Posix ( (</>) )+import System.Environment ( lookupEnv ) -import qualified Darcs.Patch.Match as MF ( MatchFlag(..) ) import Darcs.UI.External     ( catchall ) import qualified Darcs.UI.Options.Flags as F ( DarcsFlag( .. ) ) import Darcs.UI.Options.Core import qualified Darcs.UI.Options.All as O-import Darcs.Util.Environment ( maybeGetEnv )-import Darcs.Util.Exception ( firstJustIO ) import Darcs.Util.File ( withCurrentDirectory ) import Darcs.Util.Prompt     ( askUser     , askUserListItem     )-import Darcs.Util.Lock ( writeLocaleFile )+import Darcs.Util.Lock ( writeTextFile ) import Darcs.Repository.Prefs     ( getPreflist     , getGlobal     , globalPrefsDirDoc     , globalPrefsDir     )-import Darcs.Util.ByteString ( decodeString ) import Darcs.Util.Global ( darcsdir ) import Darcs.Util.IsoDate ( getIsoDateTime, cleanLocalDate ) import Darcs.Util.Path@@ -146,20 +157,17 @@  type Config = [F.DarcsFlag] -compression :: Config -> O.Compression-compression = parseFlags O.compress+verbose :: Config -> Bool+verbose = (== O.Verbose) . parseFlags O.verbosity +quiet :: Config -> Bool+quiet = (== O.Quiet) . parseFlags O.verbosity+ remoteDarcs :: Config -> O.RemoteDarcs remoteDarcs = O.remoteDarcs . parseFlags O.network -reorder :: Config -> O.Reorder-reorder = parseFlags O.reorder--minimize :: Config -> Bool-minimize = parseFlags O.minimize--editDescription :: Config -> Bool-editDescription = parseFlags O.editDescription+enumeratePatches :: Config -> Bool+enumeratePatches = (== O.YesEnumPatches) . parseFlags O.enumPatches  diffOpts :: O.UseIndex -> O.LookForAdds -> O.IncludeBoring -> O.DiffAlgorithm -> (O.UseIndex, O.ScanKnown, O.DiffAlgorithm) diffOpts use_index look_for_adds include_boring diff_alg =@@ -172,17 +180,15 @@ scanKnown O.YesLookForAdds O.YesIncludeBoring = O.ScanBoring  diffingOpts :: Config -> (O.UseIndex, O.ScanKnown, O.DiffAlgorithm)-diffingOpts flags = diffOpts (useIndex flags) (lookForAdds flags) O.NoIncludeBoring (diffAlgorithm flags)--externalMerge :: Config -> O.ExternalMerge-externalMerge = parseFlags O.useExternalMerge+diffingOpts flags = diffOpts (O.useIndex ? flags) (lookForAdds flags)+    (parseFlags O.includeBoring flags) (O.diffAlgorithm ? flags)  -- | This will become dis-entangled as soon as we inline these functions. wantGuiPause :: Config -> O.WantGuiPause wantGuiPause fs = if (hasDiffCmd fs || hasExternalMerge fs) && hasPause fs then O.YesWantGuiPause else O.NoWantGuiPause   where-    hasDiffCmd = isJust . O._diffCmd . parseFlags O.extDiff-    hasExternalMerge = (/= O.NoExternalMerge) . parseFlags O.useExternalMerge+    hasDiffCmd = isJust . O.diffCmd . parseFlags O.extDiff+    hasExternalMerge = (/= O.NoExternalMerge) . parseFlags O.externalMerge     hasPause = (== O.YesWantGuiPause) . parseFlags O.pauseForGui  -- | Non-trivial interaction between options. Explicit @-i@ or @-a@ dominates,@@ -198,102 +204,30 @@     decide O.YesDryRun _        _                     Nothing      = False     decide _           _        _                     Nothing      = def -maxCount :: Config -> Maybe Int-maxCount = parseFlags O.matchMaxcount- willRemoveLogFile :: Config -> Bool willRemoveLogFile = O._rmlogfile . parseFlags O.logfile -isUnified :: Config -> O.WithContext-isUnified = parseFlags O.withContext--doHappyForwarding :: Config -> Bool-doHappyForwarding = parseFlags O.happyForwarding- includeBoring :: Config -> Bool includeBoring cfg = case parseFlags O.includeBoring cfg of   O.NoIncludeBoring -> False   O.YesIncludeBoring -> True -doAllowCaseOnly :: Config -> Bool-doAllowCaseOnly = parseFlags O.allowCaseDifferingFilenames--doAllowWindowsReserved :: Config -> Bool-doAllowWindowsReserved = parseFlags O.allowWindowsReservedFilenames--doReverse :: Config -> Bool-doReverse = parseFlags O.changesReverse--usePacks :: Config -> Bool-usePacks = parseFlags O.usePacks--showChangesOnlyToFiles :: Config -> Bool-showChangesOnlyToFiles = parseFlags O.onlyToFiles--removeFromAmended :: Config -> Bool-removeFromAmended = parseFlags O.amendUnrecord--toMatchFlags :: Config -> [MF.MatchFlag]-toMatchFlags = parseFlags O.matchAny--verbosity :: Config -> O.Verbosity-verbosity = parseFlags O.verbosity--useCache :: Config -> O.UseCache-useCache = parseFlags O.useCache--umask :: Config -> O.UMask-umask = parseFlags O.umask--dryRun :: Config -> O.DryRun-dryRun = parseFlags O.dryRun--runPatchIndex :: Config -> O.WithPatchIndex-runPatchIndex = parseFlags O.patchIndex- lookForAdds :: Config -> O.LookForAdds lookForAdds = O.adds . parseFlags O.lookfor  lookForReplaces :: Config -> O.LookForReplaces lookForReplaces = O.replaces . parseFlags O.lookfor -diffAlgorithm :: Config -> O.DiffAlgorithm-diffAlgorithm = parseFlags O.diffAlgorithm- lookForMoves :: Config -> O.LookForMoves lookForMoves = O.moves . parseFlags O.lookfor -runTest :: Config -> O.RunTest-runTest = parseFlags O.test--testChanges :: Config -> O.TestChanges-testChanges = parseFlags O.testChanges--setScriptsExecutable :: Config -> O.SetScriptsExecutable-setScriptsExecutable = parseFlags O.setScriptsExecutable--withWorkingDir :: Config -> O.WithWorkingDir-withWorkingDir = parseFlags O.useWorkingDir--leaveTestDir :: Config -> O.LeaveTestDir-leaveTestDir = parseFlags O.leaveTestDir--remoteRepos :: Config -> O.RemoteRepos-remoteRepos = parseFlags O.remoteRepos- setDefault :: Bool -> Config -> O.SetDefault setDefault defYes = maybe def noDef . parseFlags O.setDefault where   def = if defYes then O.YesSetDefault False else O.NoSetDefault False   noDef yes = if yes then O.YesSetDefault True else O.NoSetDefault True -cloneKind :: Config -> O.CloneKind-cloneKind = parseFlags O.partial--workRepo :: Config -> O.WorkRepo-workRepo = parseFlags O.workRepo- allowConflicts :: Config -> O.AllowConflicts-allowConflicts = maybe O.NoAllowConflicts id . parseFlags (O.conflicts O.NoAllowConflicts)+allowConflicts = maybe O.NoAllowConflicts id . parseFlags O.conflictsNo  -- | Ugly. The alternative is to put the remoteRepos accessor into the IO monad, -- which is hardly better.@@ -394,10 +328,10 @@   as <- getEasyAuthor   case as of     [a] -> if alwaysAsk then-             askForAuthor (fancyPrompt as) (fancyPrompt as)+             askForAuthor False (fancyPrompt as) (fancyPrompt as)            else return a-    []  -> askForAuthor shortPrompt longPrompt-    _   -> askForAuthor (fancyPrompt as) (fancyPrompt as)+    []  -> askForAuthor True shortPrompt longPrompt+    _   -> askForAuthor False (fancyPrompt as) (fancyPrompt as)  where   shortPrompt = askUser "What is your email address? "   longPrompt  = askUser "What is your email address (e.g. Fred Bloggs <fred@example.net>)? "@@ -408,31 +342,42 @@        if str == "Other"           then longPrompt           else return str-  askForAuthor askfn1 askfn2 = do-      aminrepo <- doesDirectoryExist (darcsdir++"/prefs")+  askForAuthor storeGlobal askfn1 askfn2 = do+      aminrepo <- doesDirectoryExist (darcsdir </> "prefs")       if aminrepo && store then do+          prefsdir <- if storeGlobal+                         then tryGlobalPrefsDir+                         else return $ darcsdir </> "prefs"           putDocLn $             text "Each patch is attributed to its author, usually by email address (for" $$             text "example, `Fred Bloggs <fred@example.net>').  Darcs could not determine" $$             text "your email address, so you will be prompted for it." $$             text "" $$-            text ("Your address will be stored in " ++ globalPrefsDirDoc ++ "author") $$-            text "It will be used for all patches you record in ALL repositories." $$-            text ("If you move that file to " ++ darcsdir </> "prefs" </> "author, it will") $$-            text "be used for patches recorded in this repository only."+            text ("Your address will be stored in " ++ prefsdir)+          if prefsdir /= darcsdir </> "prefs" then+            putDocLn $+              text "It will be used for all patches you record in ALL repositories." $$+              text ("If you move that file to " ++ darcsdir </> "prefs" </> "author" ++ ", it will") $$+              text "be used for patches recorded in this repository only."+          else+            putDocLn $+              text "It will be used for all patches you record in this repository only." $$+              text ("If you move that file to " ++ globalPrefsDirDoc ++ "author, it will") $$+              text "be used for all patches recorded in ALL repositories."           add <- askfn1-          maybeprefsdir <- globalPrefsDir-          prefsdir <- case maybeprefsdir of-            Nothing -> do-                    putStrLn "WARNING: Global preference directory could not be found."-                    return $ darcsdir </> "prefs"-            Just dir -> do exists <- doesDirectoryExist dir-                           unless exists $ createDirectory dir-                           return dir-          writeLocaleFile (prefsdir </> "author") $+          writeTextFile (prefsdir </> "author") $                           unlines ["# " ++ line | line <- fileHelpAuthor] ++ "\n" ++ add           return add         else askfn2+  tryGlobalPrefsDir = do+    maybeprefsdir <- globalPrefsDir+    case maybeprefsdir of+      Nothing -> do+        putStrLn "WARNING: Global preference directory could not be found."+        return $ darcsdir </> "prefs"+      Just dir -> do exists <- doesDirectoryExist dir+                     unless exists $ createDirectory dir+                     return dir  -- | 'getEasyAuthor' tries to get the author name first from the repository preferences, -- then from global preferences, then from environment variables.  Returns @[]@@@ -442,9 +387,9 @@ getEasyAuthor =   firstNotNullIO [ (take 1 . nonblank) `fmap` getPreflist "author"                  , nonblank    `fmap` getGlobal "author"-                 , maybeToList `fmap` maybeGetEnv "DARCS_EMAIL"-                 , maybeToList `fmap` maybeGetEnv "EMAIL"-                 ] >>= mapM decodeString+                 , maybeToList `fmap` lookupEnv "DARCS_EMAIL"+                 , maybeToList `fmap` lookupEnv "EMAIL"+                 ]  where   nonblank = filter (not . null)   -- this could perhaps be simplified with Control.Monad@@ -481,7 +426,7 @@ getSendmailCmd :: Config -> IO String getSendmailCmd fs = case parseFlags O.sendmailCmd fs of   Just cmd -> return cmd-  Nothing -> fmap (maybe "" id) $ firstJustIO [ maybeGetEnv "SENDMAIL" ]+  Nothing -> fmap (maybe "" id) $ lookupEnv "SENDMAIL"  -- | Accessor for output option getOutput :: Config -> FilePath -> Maybe AbsolutePathOrStd@@ -489,9 +434,6 @@   go (O.Output ap)         = ap   go (O.OutputAutoName ap) = makeAbsoluteOrStd ap fp -getCharset :: Config -> Maybe String-getCharset = parseFlags O.charset- -- |'getSubject' takes a list of flags and returns the subject of the mail -- to be sent by @darcs send@. Looks for a subject specified by -- @Subject \"subject\"@ in that list of flags, if any.@@ -509,33 +451,8 @@ getInReplyTo :: Config -> Maybe String getInReplyTo = O._inReplyTo . parseFlags O.headerFields -getReply :: Config -> Maybe String-getReply = parseFlags O.reply---- | 'flagsToSiblings' collects the contents of all @Sibling@ flags in a list of flags.-siblings :: Config -> [AbsolutePath]-siblings = parseFlags O.siblings--useIndex :: Config -> O.UseIndex-useIndex = parseFlags O.useIndex--hasSummary :: O.Summary -> Config -> O.Summary-hasSummary def = maybe def id . parseFlags O.summary--hasXmlOutput :: Config -> O.XmlOutput-hasXmlOutput = parseFlags O.xmloutput--selectDeps :: Config -> O.SelectDeps-selectDeps = parseFlags O.selectDeps+hasXmlOutput :: Config -> Bool+hasXmlOutput = (== O.YesXml) . parseFlags O.xmlOutput  hasLogfile :: Config -> Maybe AbsolutePath hasLogfile = O._logfile . parseFlags O.logfile--hasAuthor :: Config -> Maybe String-hasAuthor = parseFlags O.author--patchFormat :: Config -> O.PatchFormat-patchFormat = parseFlags O.patchFormat--applyAs :: Config -> Maybe String-applyAs = parseFlags O.applyAs
− src/Darcs/UI/Message/Send.hs
@@ -1,186 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}---  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.--{-# LANGUAGE CPP, TypeOperators #-}---- | Help text and UI messages for @darcs send@-module Darcs.UI.Message.Send where--import Prelude ()-import Darcs.Prelude--import Darcs.Util.Path ( FilePathLike(..), toFilePath )-import Darcs.Repository.Flags ( DryRun(..) )-import Darcs.Util.Text ( sentence, quote )-import Darcs.Util.Printer--cmdDescription :: String-cmdDescription =-    "Prepare a bundle of patches to be applied to some target repository."--cmdHelp :: String-cmdHelp = unlines-    [ "Send is used to prepare a bundle of patches that can be applied to a target"-    , "repository.  Send accepts the URL of the repository as an argument.  When"-    , "called without an argument, send will use the most recent repository that"-    , "was either pushed to, pulled from or sent to.  By default, the patch bundle"-    , "is saved to a file, although you may directly send it by mail."-    , ""-    , "The `--output`, `--output-auto-name`, and `--to` flags determine"-    , "what darcs does with the patch bundle after creating it.  If you provide an"-    , "`--output` argument, the patch bundle is saved to that file.  If you"-    , "specify `--output-auto-name`, the patch bundle is saved to a file with an"-    , "automatically generated name.  If you give one or more `--to` arguments,"-    , "the bundle of patches is sent to those locations. The locations may either"-    , "be email addresses or urls that the patch should be submitted to via HTTP."-    , ""-    , "If you provide the `--mail` flag, darcs will look at the contents"-    , "of the `_darcs/prefs/email` file in the target repository (if it exists),"-    , "and send the patch by email to that address.  In this case, you may use"-    , "the `--cc` option to specify additional recipients without overriding the"-    , "default repository email address."-    , ""-    , "If `_darcs/prefs/post` exists in the target repository, darcs will"-    , "upload to the URL contained in that file, which may either be a"-    , "`mailto:` URL, or an `http://` URL.  In the latter case, the"-    , "patch is posted to that URL."-    , ""-    , "If there is no email address associated with the repository, darcs will"-    , "prompt you for an email address."-    , ""-    , "Use the `--subject` flag to set the subject of the e-mail to be sent."-    , "If you don't provide a subject on the command line, darcs will make one up"-    , "based on names of the patches in the patch bundle."-    , ""-    , "Use the `--in-reply-to` flag to set the In-Reply-To and References headers"-    , "of the e-mail to be sent. By default no additional headers are included so"-    , "e-mail will not be treated as reply by mail readers."-    , ""-    , "If you want to include a description or explanation along with the bundle"-    , "of patches, you need to specify the `--edit-description` flag, which"-    , "will cause darcs to open up an editor with which you can compose a message"-    , "to go along with your patches."-    , ""-    , "If you want to use a command different from the default one for sending"-    , "email, you need to specify a command line with the `--sendmail-command`"-    , "option. The command line can contain some format specifiers which are"-    , "replaced by the actual values. Accepted format specifiers are `%s` for"-    , "subject, `%t` for to, `%c` for cc, `%b` for the body of the mail, `%f` for"-    , "from, `%a` for the patch bundle and the same specifiers in uppercase for the"-    , "URL-encoded values."-    , "Additionally you can add `%<` to the end of the command line if the command"-    , "expects the complete email message on standard input. E.g. the command lines"-    , "for evolution and msmtp look like this:"-    , ""-    , "    evolution \"mailto:%T?subject=%S&attach=%A&cc=%C&body=%B\""-    , "    msmtp -t %<"-    , ""-    , "Do not confuse the `--author` options with the return address"-    , "that `darcs send` will set for your patch bundle."-    , ""-    , "For example, if you have two email addresses A and B:"-    , ""-    , "* If you use `--author A` but your machine is configured to send mail from"-    , "  address B by default, then the return address on your message will be B."-    , "* If you use `--from A` and your mail client supports setting the"-    , "  From: address arbitrarily (some non-Unix-like mail clients, especially,"-    , "  may not support this), then the return address will be A; if it does"-    , "  not support this, then the return address will be B."-    , "* If you supply neither `--from` nor `--author` then the return"-    , "  address will be B."-    , ""-    , "In addition, unless you specify the sendmail command with"-    , "`--sendmail-command`, darcs sends email using the default email"-    , "command on your computer. This default command is determined by the"-    , "`configure` script. Thus, on some non-Unix-like OSes,"-    , "`--from` is likely to not work at all."-    ]--cannotSendToSelf :: String-cannotSendToSelf = "Can't send to current repository! Did you mean send --context?"--creatingPatch :: String -> Doc-creatingPatch repodir = "Creating patch to" <+> text (quote repodir) <> "..."--noWorkingSendmail :: Doc-noWorkingSendmail = "No working sendmail instance on your machine!"--nothingSendable :: Doc-nothingSendable = "No recorded local changes to send!"--selectionIs :: [Doc] -> Doc-selectionIs descs = text "We have the following patches to send:" $$ vcat descs--selectionIsNull :: Doc-selectionIsNull = text "You don't want to send any patches, and that's fine with me!"--emailBackedUp :: String -> Doc-emailBackedUp mf = sentence $ "Email body left in" <+> text mf--promptCharSetWarning :: String -> String-promptCharSetWarning msg = "Warning: " ++ msg ++ "  Send anyway?"--charsetAborted :: Doc-charsetAborted = "Aborted.  You can specify charset with the --charset option."--charsetCouldNotGuess :: String-charsetCouldNotGuess = "darcs could not guess the charset of your mail."--currentEncodingIs :: String -> String-currentEncodingIs e = "Current locale encoding: " ++ e--charsetUtf8MailDiffLocale :: String-charsetUtf8MailDiffLocale = "your mail is valid UTF-8 but your locale differs."--aborted :: Doc-aborted = "Aborted."--success :: String -> String -> Doc-success to cc = sentence $-    "Successfully sent patch bundle to:" <+> text to <+> copies cc-  where-    copies "" = ""-    copies x  = "and cc'ed" <+> text x--postingPatch :: String -> Doc-postingPatch url = "Posting patch to" <+> text url--wroteBundle :: FilePathLike a => a -> Doc-wroteBundle a = sentence $ "Wrote patch to" <+> text (toFilePath a)--savedButNotSent :: String -> Doc-savedButNotSent to =-        text ("The usual recipent for this bundle is: " ++ to)-    $$  text "To send it automatically, make sure sendmail is working,"-    <+> text "and add 'send mail' to _darcs/prefs/defaults or"-    <+> text " ~/.darcs/defaults"--willSendTo :: DryRun -> [String] -> Doc-willSendTo dr addresses =-    "Patch bundle" <+> will <+> " be sent to:" <+> text (unwords addresses)-  where-    will = case dr of { YesDryRun -> "would"; NoDryRun  -> "will" }--promptTarget :: String-promptTarget = "What is the target email address? "--aboutToEdit :: FilePath -> String-aboutToEdit file = "About to edit file " ++ file--promptNoDescriptionChange :: String-promptNoDescriptionChange = "File content did not change. Continue anyway?"
src/Darcs/UI/Options.hs view
@@ -1,6 +1,5 @@ module Darcs.UI.Options     ( module Darcs.UI.Options.Core-    , module Darcs.UI.Options.Markdown     , DarcsOption     , PrimDarcsOption     , DarcsOptDescr@@ -10,22 +9,14 @@ import Prelude () import Darcs.Prelude -import Data.Functor.Compose-import System.Console.GetOpt+import Data.Functor.Compose ( getCompose )+import System.Console.GetOpt ( OptDescr ) -import Darcs.UI.Options.All+import Darcs.UI.Options.All ( DarcsOption ) import Darcs.UI.Options.Core-import Darcs.UI.Options.Markdown import Darcs.UI.Options.Util ( DarcsOptDescr, PrimDarcsOption ) import Darcs.Util.Path ( AbsolutePath ) --- * Type instantiations---- | The @instance Functor OptDescr@ was introduced only in base-4.7.0.0, which is--- why we implement it here manually.+-- | Instantiate a 'DarcsOptDescr' with an 'AbsolutePath' optDescr :: AbsolutePath -> DarcsOptDescr f -> OptDescr f-optDescr path = omap ($path) . getCompose where-  omap f (Option s l a h) = Option s l (amap f a) h-  amap f (NoArg a) = NoArg (f a)-  amap f (ReqArg mkF n) = ReqArg (fmap f mkF) n-  amap f (OptArg mkF n) = OptArg (fmap f mkF) n+optDescr path = fmap ($ path) . getCompose
src/Darcs/UI/Options/All.hs view
@@ -28,6 +28,9 @@ module Darcs.UI.Options.All     ( DarcsOption +    -- conversion to 'Bool'+    , YesNo (..)+     -- root     , RootAction (..)     , rootActions@@ -40,6 +43,8 @@     , verbosity     , timings     , anyVerbosity+    , HooksConfig (..) -- re-export+    , HookConfig (..) -- re-export     , preHook     , postHook     , hooks@@ -48,7 +53,7 @@      -- interactivity     , XmlOutput (..)-    , xmloutput+    , xmlOutput     , DryRun (..) -- re-export     , dryRun     , dryRunXml@@ -56,23 +61,24 @@     , pipe     , WantGuiPause (..) -- re-export     , pauseForGui-    , askdeps+    , askDeps      -- patch selection     , module Darcs.UI.Options.Matching -- re-export     , SelectDeps (..)     , selectDeps     , changesReverse-    , matchMaxcount+    , maxCount      -- local or remote repo(s)     , WorkRepo (..) -- re-export     , workRepo-    , workingRepoDir+    , repoDir     , RemoteRepos (..) -- re-export     , remoteRepos     , possiblyRemoteRepo     , reponame+    , NotInRemote (..)     , notInRemote     , notInRemoteFlagName     , RepoCombinator (..)@@ -80,7 +86,7 @@     , allowUnrelatedRepos     , justThisRepo     , WithWorkingDir (..) -- re-export-    , useWorkingDir+    , withWorkingDir     , SetDefault (..) -- re-export     , setDefault @@ -99,11 +105,13 @@     , LookForMoves (..) -- re-export     , LookForReplaces (..) -- re-export     , lookfor+    , lookforadds+    , lookforreplaces+    , lookformoves      -- files to consider     , UseIndex (..) -- re-export     , ScanKnown (..) -- re-export-    , diffing     , IncludeBoring (..)     , includeBoring     , allowProblematicFilenames@@ -118,7 +126,6 @@     , diffAlgorithm     , WithContext (..)     , withContext-    , unidiff     , ExternalDiff (..)     , extDiff @@ -126,7 +133,7 @@     , TestChanges (..)     , testChanges     , RunTest (..) -- re-export-    , test+    , runTest     , LeaveTestDir (..) -- re-export     , leaveTestDir @@ -151,16 +158,17 @@      -- merging patches     , AllowConflicts (..) -- re-export-    , conflicts+    , conflictsNo+    , conflictsYes     , ExternalMerge (..) -- re-export-    , useExternalMerge+    , externalMerge      -- optimizations     , Compression (..) -- re-export     , compress     , usePacks     , WithPatchIndex (..) -- re-export-    , patchIndex+    , patchIndexNo     , patchIndexYes     , Reorder (..) -- re-export     , reorder@@ -172,6 +180,7 @@     , output     , Summary (..)     , summary+    , maybeSummary     , RemoteDarcs (..) -- re-export     , NetworkOptions (..)     , network@@ -188,12 +197,11 @@     , selectAuthor      -- annotate-    , humanReadable     , machineReadable      -- clone     , CloneKind (..)-    , partial+    , cloneKind      -- dist     , distname@@ -225,13 +233,16 @@     , pending     , nullFlag +    -- show repo+    , EnumPatches (..)+    , enumPatches+     -- gzcrcs     , GzcrcsAction (..)     , gzcrcsActions      -- optimize     , siblings-    , reorderPatches     , optimizePatchIndex     ) where @@ -241,7 +252,6 @@ import Prelude hiding ( (^) ) import Data.Char ( isDigit ) import Data.List ( intercalate )-import Data.Maybe ( listToMaybe )  import Darcs.Repository.Flags     ( Compression (..)@@ -271,6 +281,8 @@     , WithWorkingDir (..)     , PatchFormat (..)     , IncludeBoring (..)+    , HooksConfig (..)+    , HookConfig (..)     )  import qualified Darcs.UI.Options.Flags as F ( DarcsFlag(..) )@@ -288,6 +300,79 @@  type RawDarcsOption = forall v. v -> RawOptSpec Flag v +-- * Conversion to 'Bool'++class YesNo a where+  yes :: a -> Bool+  no :: a -> Bool+  no = not . yes++instance YesNo Compression where+  yes NoCompression = False+  yes GzipCompression = True++instance YesNo WithPatchIndex where+  yes NoPatchIndex = False+  yes YesPatchIndex = True++instance YesNo Reorder where+  yes NoReorder = False+  yes Reorder = True++instance YesNo UseCache where+  yes NoUseCache = False+  yes YesUseCache = True++instance YesNo DryRun where+  yes NoDryRun = False+  yes YesDryRun = True++instance YesNo LookForAdds where+  yes NoLookForAdds = False+  yes YesLookForAdds = True++instance YesNo LookForReplaces where+  yes NoLookForReplaces = False+  yes YesLookForReplaces = True++instance YesNo LookForMoves where+  yes NoLookForMoves = False+  yes YesLookForMoves = True++instance YesNo IncludeBoring where+  yes NoIncludeBoring = False+  yes YesIncludeBoring = True++instance YesNo RunTest where+  yes NoRunTest = False+  yes YesRunTest = True++instance YesNo SetScriptsExecutable where+  yes NoSetScriptsExecutable = False+  yes YesSetScriptsExecutable = True++instance YesNo LeaveTestDir where+  yes NoLeaveTestDir = False+  yes YesLeaveTestDir = True++instance YesNo UseIndex where+  yes IgnoreIndex = False+  yes UseIndex = True++instance YesNo WantGuiPause where+  yes NoWantGuiPause = False+  yes YesWantGuiPause = True++instance YesNo WithWorkingDir where+  yes NoWorkingDir = False+  yes WithWorkingDir = True++data EnumPatches = NoEnumPatches | YesEnumPatches deriving (Eq, Show)++instance YesNo EnumPatches where+  yes NoEnumPatches = False+  yes YesEnumPatches = True+ -- * Root command  -- | Options for darcs iself that act like sub-commands.@@ -295,13 +380,13 @@  rootActions :: PrimDarcsOption (Maybe RootAction) rootActions = withDefault Nothing-  [ RawNoArg ['h'] ["help", "overview"] F.Help (Just RootHelp)+  [ RawNoArg ['h'] ["help"] F.Help (Just RootHelp)     "show a brief description of all darcs commands and top-level options"-  , RawNoArg ['v'] ["version"] F.Version  (Just Version) "show the darcs version"+  , RawNoArg ['v','V'] ["version"] F.Version  (Just Version) "show the darcs version"   , RawNoArg [] ["exact-version"] F.ExactVersion (Just ExactVersion)     "show the exact darcs version"     -- the switch --commands is here for compatibility only-  , RawNoArg [] ["commands","list-options"] F.ListCommands (Just ListCommands)+  , RawNoArg [] ["commands"] F.ListCommands (Just ListCommands)     "show plain list of available options and commands, for auto-completion"   ] @@ -342,15 +427,22 @@  -- ** Hooks -hooks :: DarcsOption a (Maybe String -> Bool -> Maybe String -> Bool -> a)-hooks = preHook ^ postHook+hooks :: DarcsOption a (HooksConfig -> a)+hooks = imap (Iso fw bw) $ preHook ^ postHook where+  fw k (HooksConfig pr po) = k pr po+  bw k pr po = k (HooksConfig pr po) -preHook :: DarcsOption a (Maybe String -> Bool -> a)-preHook = prehookCmd ^ hookPrompt "prehook" F.AskPrehook F.RunPrehook+hookIso :: Iso (Maybe String -> Bool -> a) (HookConfig -> a)+hookIso = (Iso fw bw) where+    fw k (HookConfig c p) = k c p+    bw k c p = k (HookConfig c p) -postHook :: DarcsOption a (Maybe String -> Bool -> a)-postHook = posthookCmd ^ hookPrompt "posthook" F.AskPosthook F.RunPosthook+preHook :: DarcsOption a (HookConfig -> a)+preHook = imap hookIso $ prehookCmd ^ hookPrompt "prehook" F.AskPrehook F.RunPrehook +postHook :: DarcsOption a (HookConfig -> a)+postHook = imap hookIso $ posthookCmd ^ hookPrompt "posthook" F.AskPosthook F.RunPosthook+ prehookCmd :: PrimDarcsOption (Maybe String) prehookCmd = withDefault Nothing     [ RawStrArg [] ["prehook"] F.PrehookCmd unF Just unV@@ -397,30 +489,27 @@  data XmlOutput = NoXml | YesXml deriving (Eq, Show) -xmloutput :: PrimDarcsOption XmlOutput-xmloutput = withDefault NoXml [__xmloutput YesXml]+instance YesNo XmlOutput where+  yes NoXml = False+  yes YesXml = True +xmlOutput :: PrimDarcsOption XmlOutput+xmlOutput = withDefault NoXml [__xmloutput YesXml]+ __xmloutput :: RawDarcsOption __xmloutput val = RawNoArg [] ["xml-output"] F.XMLOutput val "generate XML formatted output" --- | NOTE: I'd rather work to have no uses of dryRunNoxml, so that any time--- --dry-run is a possibility, automated users can examine the results more--- easily with --xml.------ See also issue2397.+-- | TODO someone wrote here long ago that any time --dry-run is a possibility+-- automated users should be able to examine the results more+-- easily with --xml. See also issue2397.+-- dryRun w/o xml is currently used in add, pull, and repair.+ dryRun :: PrimDarcsOption DryRun-dryRun = (imap . cps) (Iso fw bw) $ singleNoArg [] ["dry-run"] F.DryRun "don't actually take the action"-  where-    fw True = YesDryRun-    fw False = NoDryRun-    bw YesDryRun = True-    bw NoDryRun = False+dryRun = withDefault NoDryRun+  [ RawNoArg [] ["dry-run"] F.DryRun YesDryRun "don't actually take the action" ]  dryRunXml :: DarcsOption a (DryRun -> XmlOutput -> a)-dryRunXml = dryRun ^ xmloutput--__dryrun :: RawDarcsOption-__dryrun val = RawNoArg [] ["dry-run"] F.DryRun val "don't actually take the action"+dryRunXml = dryRun ^ xmlOutput  pipe :: PrimDarcsOption Bool pipe = singleNoArg [] ["pipe"] F.Pipe "ask user interactively for the patch metadata"@@ -437,8 +526,8 @@   , RawNoArg [] ["no-pause-for-gui"] F.NoPauseForGui NoWantGuiPause     "return immediately after external diff or merge command finishes" ] -askdeps :: PrimDarcsOption Bool-askdeps = withDefault False+askDeps :: PrimDarcsOption Bool+askDeps = withDefault False   [ RawNoArg [] ["ask-deps"] F.AskDeps True "manually select dependencies"   , RawNoArg [] ["no-ask-deps"] F.NoAskDeps False "automatically select dependencies" ] @@ -465,22 +554,28 @@ -- should take either a plain 'String' argument (leaving it to a later stage -- to parse the 'String' to an 'Int'), or else a @'Maybe' 'Int'@, taking -- the possibility of a failed parse into account.-matchMaxcount :: PrimDarcsOption (Maybe Int)-matchMaxcount = OptSpec {..} where-  ounparse k (Just n) = k [ F.MaxCount n ]-  ounparse k Nothing = k []-  oparse k fs = k $ listToMaybe [ s | F.MaxCount s <- fs ]-  ocheck fs = case [ "--max-count="++show n | F.MaxCount n <- fs ] of-    cfs@(_:_:_) -> ["conflicting flags: " ++ intercalate ", " cfs]-    _ -> []-  odesc = [ strArg [] ["max-count"] (F.MaxCount . toInt) "NUMBER"-    "return only NUMBER results" ]-  toInt s = if not (null s) && all isDigit s then read s else (-1)+maxCount :: PrimDarcsOption (Maybe Int)+maxCount = (withDefault Nothing+    [ RawStrArg [] ["max-count"] F.MaxCount unF toV unV "NUMBER"+      "return only NUMBER results" ])+    {ocheck=check}+  where+    unF f = [ s | F.MaxCount s <- [f] ]+    unV x = [ show s | Just s <- [x] ]+    toV s = if good s then Just (read s) else Nothing+    check fs =+      [ "invalid argument to --max-count: '"++s++"'" | s <- args, not (good s) ] +++      if length args > 1+        then ["conflicting flags: " ++ intercalate ", " (map ("--max-count="++) args)]+        else []+      where+        args = [ s | F.MaxCount s <- fs ]+    good s = not (null s) && all isDigit s  -- * Local or remote repo  workRepo :: PrimDarcsOption WorkRepo-workRepo = imap (Iso fw bw) $ workingRepoDir ^ possiblyRemoteRepo where+workRepo = imap (Iso fw bw) $ repoDir ^ possiblyRemoteRepo where   fw k (WorkRepoDir s)         = k (Just s) Nothing   fw k (WorkRepoPossibleURL s) = k Nothing  (Just s)   fw k WorkRepoCurrentDir      = k Nothing  Nothing@@ -488,8 +583,8 @@   bw k Nothing  (Just s)       = k (WorkRepoPossibleURL s)   bw k Nothing  Nothing        = k WorkRepoCurrentDir -workingRepoDir :: PrimDarcsOption (Maybe String)-workingRepoDir = singleStrArg [] ["repodir"] F.WorkRepoDir arg "DIRECTORY"+repoDir :: PrimDarcsOption (Maybe String)+repoDir = singleStrArg [] ["repodir"] F.WorkRepoDir arg "DIRECTORY"     "specify the repository directory in which to run"   where arg (F.WorkRepoDir s) = Just s         arg _ = Nothing@@ -518,13 +613,21 @@ notInRemoteFlagName :: String notInRemoteFlagName = "not-in-remote" -notInRemote :: PrimDarcsOption [Maybe String]-notInRemote =+data NotInRemote+  = NotInDefaultRepo+  | NotInRemotePath String++notInRemote :: PrimDarcsOption [NotInRemote]+notInRemote = (imap . cps) (Iso (map fw) (map bw)) $     multiOptStrArg [] [notInRemoteFlagName] F.NotInRemote args "URL/PATH" $         "select all patches not in the default push/pull repository or at "         ++ "location URL/PATH"   where     args fs = [s | F.NotInRemote s <- fs]+    fw (Just s) = NotInRemotePath s+    fw Nothing = NotInDefaultRepo+    bw (NotInRemotePath s) = Just s+    bw NotInDefaultRepo = Nothing  data RepoCombinator = Intersection | Union | Complement deriving (Eq, Show) @@ -546,8 +649,8 @@   "Limit the check or repair to the current repo"  -- | convert, clone, init-useWorkingDir :: PrimDarcsOption WithWorkingDir-useWorkingDir = withDefault WithWorkingDir+withWorkingDir :: PrimDarcsOption WithWorkingDir+withWorkingDir = withDefault WithWorkingDir   [ RawNoArg [] ["with-working-dir"] F.UseWorkingDir WithWorkingDir     "Create a working directory (normal repository)"   , RawNoArg [] ["no-working-dir"] F.UseNoWorkingDir NoWorkingDir@@ -625,12 +728,12 @@   }  lookfor :: PrimDarcsOption LookFor-lookfor = imap (Iso fw bw) (lookforadds ^ lookforreplaces ^ lookformoves) where+lookfor = imap (Iso fw bw) (lookforadds NoLookForAdds ^ lookforreplaces ^ lookformoves) where   fw k (LookFor a r m) = k a r m   bw k a r m = k (LookFor a r m) -lookforadds :: PrimDarcsOption LookForAdds-lookforadds = withDefault NoLookForAdds+lookforadds :: LookForAdds -> PrimDarcsOption LookForAdds+lookforadds def = withDefault def   [ RawNoArg ['l'] ["look-for-adds"] F.LookForAdds YesLookForAdds     "look for (non-boring) files that could be added"   , RawNoArg [] ["dont-look-for-adds","no-look-for-adds"] F.NoLookForAdds NoLookForAdds@@ -654,12 +757,6 @@  -- * Files to consider -diffing :: PrimDarcsOption (UseIndex, ScanKnown, DiffAlgorithm)-diffing = imap (Iso curry3 uncurry3) $ useIndex ^ scanKnown ^ diffAlgorithm-  where-    uncurry3 k x y z = k (x,y,z)-    curry3 k (x,y,z) = k x y z- useIndex :: PrimDarcsOption UseIndex useIndex = (imap . cps) (Iso fw bw) ignoreTimes where   fw False = UseIndex@@ -667,15 +764,6 @@   bw UseIndex = False   bw IgnoreIndex = True -scanKnown :: PrimDarcsOption ScanKnown-scanKnown = imap (Iso fw bw) $ lookforadds ^ includeBoring where-  fw k ScanKnown = k NoLookForAdds NoIncludeBoring-  fw k ScanAll = k YesLookForAdds NoIncludeBoring-  fw k ScanBoring = k YesLookForAdds YesIncludeBoring-  bw k NoLookForAdds _ = k ScanKnown-  bw k YesLookForAdds NoIncludeBoring = k ScanAll-  bw k YesLookForAdds YesIncludeBoring = k ScanBoring- includeBoring :: PrimDarcsOption IncludeBoring includeBoring = withDefault NoIncludeBoring   [ RawNoArg [] ["boring"] F.Boring YesIncludeBoring "don't skip boring files"@@ -729,6 +817,10 @@  data WithContext = NoContext | YesContext deriving (Eq, Show) +instance YesNo WithContext where+  yes NoContext = False+  yes YesContext = True+ withContext :: PrimDarcsOption WithContext withContext = (imap . cps) (Iso fw bw) $ withDefault False   [ RawNoArg ['u'] ["unified"] F.Unified True@@ -740,42 +832,46 @@         bw NoContext = False         bw YesContext = True -unidiff :: PrimDarcsOption Bool-unidiff = withDefault True-  [ RawNoArg ['u'] ["unified"] F.Unified True "pass -u option to diff"-  , RawNoArg  [] ["no-unified"] F.NonUnified False "output patch in diff's dumb format" ]--data ExternalDiff = ExternalDiff { _diffCmd :: Maybe String, _diffOpts :: [String] } deriving (Eq, Show)+data ExternalDiff = ExternalDiff+  { diffCmd :: Maybe String+  , diffOpts :: [String]+  , diffUnified :: Bool+  } deriving (Eq, Show)  extDiff :: PrimDarcsOption ExternalDiff-extDiff = imap (Iso fw bw) $ extDiffCmd ^ extDiffOpts where-  fw k (ExternalDiff cmd opts) = k cmd opts-  bw k cmd opts = k (ExternalDiff cmd opts)+extDiff = imap (Iso fw bw) $ __extDiffCmd ^ __extDiffOpts ^ __unidiff where+  fw k (ExternalDiff cmd opts uni) = k cmd opts uni+  bw k cmd opts uni = k (ExternalDiff cmd opts uni) -extDiffCmd :: PrimDarcsOption (Maybe String)-extDiffCmd = singleStrArg [] ["diff-command"] F.DiffCmd arg "COMMAND"+__extDiffCmd :: PrimDarcsOption (Maybe String)+__extDiffCmd = singleStrArg [] ["diff-command"] F.DiffCmd arg "COMMAND"     "specify diff command (ignores --diff-opts)"   where arg (F.DiffCmd s) = Just s         arg _ = Nothing -extDiffOpts :: PrimDarcsOption [String]-extDiffOpts = multiStrArg [] ["diff-opts"] F.DiffFlags mkV "OPTIONS"+__extDiffOpts :: PrimDarcsOption [String]+__extDiffOpts = multiStrArg [] ["diff-opts"] F.DiffFlags mkV "OPTIONS"     "options to pass to diff"   where mkV fs = [ s | F.DiffFlags s <- fs ] +__unidiff :: PrimDarcsOption Bool+__unidiff = withDefault True+  [ RawNoArg ['u'] ["unified"] F.Unified True "pass -u option to diff"+  , RawNoArg  [] ["no-unified"] F.NonUnified False "output patch in diff's dumb format" ]+ -- * Runnign tests  data TestChanges = NoTestChanges | YesTestChanges LeaveTestDir deriving (Eq)  testChanges :: PrimDarcsOption TestChanges-testChanges = imap (Iso fw bw) $ test ^ leaveTestDir where+testChanges = imap (Iso fw bw) $ runTest ^ leaveTestDir where   fw k NoTestChanges = k NoRunTest {- undefined -} YesLeaveTestDir   fw k (YesTestChanges ltd) = k YesRunTest ltd   bw k NoRunTest _ = k NoTestChanges   bw k YesRunTest ltd = k (YesTestChanges ltd) -test :: PrimDarcsOption RunTest-test = withDefault NoRunTest+runTest :: PrimDarcsOption RunTest+runTest = withDefault NoRunTest   [ RawNoArg [] ["test"] F.Test YesRunTest "run the test script"   , RawNoArg [] ["no-test"] F.NoTest NoRunTest "don't run the test script" ] @@ -805,8 +901,8 @@         arg _ = Nothing  to :: PrimDarcsOption [String]-to = multiStrArg [] ["to"] F.Target mkV "EMAIL" "specify destination email"-  where mkV fs = [ s | F.Target s <- fs ]+to = multiStrArg [] ["to"] F.To mkV "EMAIL" "specify destination email"+  where mkV fs = [ s | F.To s <- fs ]  cc :: PrimDarcsOption [String] cc = multiStrArg [] ["cc"] F.Cc mkV "EMAIL" "mail results to additional EMAIL(s)"@@ -937,25 +1033,28 @@  -- * Merging patches --- applyConflictOptions = conflicts NoAllowConflicts--- pullConflictOptions = conflicts YesAllowConflictsAndMark+-- | push, apply, rebase apply: default to 'NoAllowConflicts'+conflictsNo :: PrimDarcsOption (Maybe AllowConflicts)+conflictsNo = conflicts NoAllowConflicts +-- | pull, rebase pull: default to 'YesAllowConflictsAndMark'+conflictsYes :: PrimDarcsOption (Maybe AllowConflicts)+conflictsYes = conflicts YesAllowConflictsAndMark+ conflicts :: AllowConflicts -> PrimDarcsOption (Maybe AllowConflicts) conflicts def = withDefault (Just def)   [ RawNoArg [] ["mark-conflicts"]       F.MarkConflicts (Just YesAllowConflictsAndMark) "mark conflicts"   , RawNoArg [] ["allow-conflicts"]       F.AllowConflicts (Just YesAllowConflicts) "allow conflicts, but don't mark them"---   , RawNoArg [] ["no-resolve-conflicts"]---       NoAllowConflicts "equivalent to --dont-allow-conflicts, for backwards compatibility"   , RawNoArg [] ["dont-allow-conflicts","no-allow-conflicts","no-resolve-conflicts"]       F.NoAllowConflicts (Just NoAllowConflicts) "fail if there are patches that would create conflicts"   , RawNoArg [] ["skip-conflicts"]       F.SkipConflicts Nothing "filter out any patches that would create conflicts" ]  -- Technically not an isomorphism, see 'sendmailIso'.-useExternalMerge :: PrimDarcsOption ExternalMerge-useExternalMerge = imap (Iso fw bw) $ singleStrArg [] ["external-merge"] F.ExternalMerge arg+externalMerge :: PrimDarcsOption ExternalMerge+externalMerge = imap (Iso fw bw) $ singleStrArg [] ["external-merge"] F.ExternalMerge arg     "COMMAND" "use external tool to merge conflicts"   where     arg (F.ExternalMerge s) = Just s@@ -978,8 +1077,8 @@   , RawNoArg [] ["no-packs"] F.NoPacks False "don't use repository packs" ]  -- for init, clone and convert: patch index disabled by default-patchIndex :: PrimDarcsOption WithPatchIndex-patchIndex = withDefault NoPatchIndex [__patchIndex YesPatchIndex, __noPatchIndex NoPatchIndex]+patchIndexNo :: PrimDarcsOption WithPatchIndex+patchIndexNo = withDefault NoPatchIndex [__patchIndex YesPatchIndex, __noPatchIndex NoPatchIndex]  -- for log and annotate: patch index enabled by default patchIndexYes :: PrimDarcsOption WithPatchIndex@@ -1025,8 +1124,23 @@  data Summary = NoSummary | YesSummary deriving (Eq, Show) -summary :: PrimDarcsOption (Maybe Summary)-summary = withDefault Nothing+instance YesNo Summary where+  yes NoSummary = False+  yes YesSummary = True++-- all commands except whatsnew+summary :: PrimDarcsOption Summary+summary = (imap . cps) (Iso fw bw) $ maybeSummary Nothing+  where+    fw Nothing = NoSummary+    fw (Just NoSummary) = NoSummary+    fw (Just YesSummary) = YesSummary+    bw NoSummary = Nothing+    bw YesSummary = Just YesSummary++-- needed for whatsnew+maybeSummary :: Maybe Summary -> PrimDarcsOption (Maybe Summary)+maybeSummary def = withDefault def   [ RawNoArg ['s'] ["summary"] F.Summary (Just YesSummary) "summarize changes"   , RawNoArg [] ["no-summary"] F.NoSummary (Just NoSummary) "don't summarize changes" ] @@ -1091,24 +1205,21 @@  -- ** annotate --- | TODO: These should be mutually exclusive, but are they? The code is almost inscrutable.-humanReadable :: PrimDarcsOption Bool-humanReadable = withDefault False [__humanReadable True]+machineReadable :: PrimDarcsOption Bool+machineReadable = withDefault False+  [ __humanReadable False+  , __machineReadable True ]  __humanReadable :: RawDarcsOption __humanReadable val = RawNoArg [] ["human-readable"] F.HumanReadable val "give human-readable output" --- | See above.-machineReadable :: PrimDarcsOption Bool-machineReadable = withDefault False [__machineReadable True]- __machineReadable :: RawDarcsOption __machineReadable val = RawNoArg [] ["machine-readable"] F.MachineReadable val "give machine-readable output"  -- ** clone -partial :: PrimDarcsOption CloneKind-partial = withDefault NormalClone+cloneKind :: PrimDarcsOption CloneKind+cloneKind = withDefault NormalClone   [ RawNoArg [] ["lazy"] F.Lazy LazyClone "get patch files only as needed"   , RawNoArg [] ["complete"] F.Complete CompleteClone "get a complete copy of the repository" ] @@ -1155,11 +1266,18 @@  -- ** log -data ChangesFormat = HumanReadable | MachineReadable | GenContext | GenXml | NumberPatches | CountPatches deriving (Eq, Show)+data ChangesFormat+  = HumanReadable+  | MachineReadable+  | GenContext+  | GenXml+  | NumberPatches+  | CountPatches+  deriving (Eq, Show)  changesFormat :: PrimDarcsOption (Maybe ChangesFormat) changesFormat = withDefault Nothing-  [ RawNoArg [] ["context"] F.GenContext (Just GenContext) "give output suitable for get --context"+  [ RawNoArg [] ["context"] F.GenContext (Just GenContext) "give output suitable for clone --context"   , __xmloutput (Just GenXml)   , __humanReadable (Just HumanReadable)   , __machineReadable (Just MachineReadable)@@ -1191,7 +1309,7 @@   , RawNoArg [] ["backoff"] F.Backoff Backoff "exponential backoff search"   , RawNoArg [] ["bisect"] F.Bisect Bisect "binary instead of linear search" ] --- ** show files/index+-- ** show files  files :: PrimDarcsOption Bool files = withDefault True@@ -1206,12 +1324,21 @@ pending :: PrimDarcsOption Bool pending = withDefault True   [ RawNoArg [] ["pending"] F.Pending True "reflect pending patches in output"-  , RawNoArg [] ["no-pending"] F.NoPending False "only included recorded patches in output" ]+  , RawNoArg [] ["no-pending"] F.NoPending False "only include recorded patches in output" ]  -- "null" is already taken nullFlag :: PrimDarcsOption Bool nullFlag = singleNoArg ['0'] ["null"] F.NullFlag "separate file names by NUL characters" +-- ** show repo++enumPatches :: PrimDarcsOption EnumPatches+enumPatches = withDefault YesEnumPatches+  [ RawNoArg [] ["enum-patches"] F.EnumPatches YesEnumPatches+    "include statistics requiring enumeration of patches"+  , RawNoArg [] ["no-enum-patches"] F.NoEnumPatches NoEnumPatches+    "don't include statistics requiring enumeration of patches" ]+ -- ** gzcrcs  data GzcrcsAction = GzcrcsCheck | GzcrcsRepair deriving (Eq, Show)@@ -1224,11 +1351,9 @@ -- ** optimize  siblings :: PrimDarcsOption [AbsolutePath]-siblings = multiAbsPathArg [] ["sibling"] F.Sibling mkV "URL" "specify a sibling directory"+siblings = multiAbsPathArg [] ["sibling"] F.Sibling mkV "DIRECTORY"+    "specify a sibling directory"   where mkV fs = [ s | F.Sibling s <- fs ]--reorderPatches :: PrimDarcsOption Bool-reorderPatches = singleNoArg [] ["reorder-patches"] F.Reorder "reorder the patches in the repository"  reorder :: PrimDarcsOption Reorder reorder = withDefault NoReorder
src/Darcs/UI/Options/Core.hs view
@@ -283,6 +283,9 @@   ocheck _ = []   odesc = [] +instance Semigroup (PrimOptSpec d f a [v]) where+  (<>) = oappend+ -- | See 'oappend' and 'oempty'. instance Monoid (PrimOptSpec d f a [v]) where   mappend = oappend@@ -295,3 +298,13 @@ -- prop> parseFlags o fs = oparse o id fs parseFlags :: (forall a. PrimOptSpec d f a v) -> [f] -> v parseFlags o fs = oparse o id fs++-- no assoiativity, higher precedence than comparisons operators (4)+-- and lower than arithemic operators (6,7,8)+infix 5 ?++-- | Operator version of 'parseFlags'+--+-- prop> opt ? flags = parseFlags opt flags+(?) :: (forall a. PrimOptSpec d f a v) -> [f] -> v+(?) = parseFlags
src/Darcs/UI/Options/Flags.hs view
@@ -16,7 +16,7 @@                | LeaveTestDir | NoLeaveTestDir                | Timings | Debug | DebugHTTP                | Verbose | NormalVerbosity | Quiet-               | Target String | Cc String+               | To String | Cc String                | Output AbsolutePathOrStd | OutputAutoName AbsolutePath | Mail                | Subject String | InReplyTo String | Charset String                | SendmailCmd String | Author String | SelectAuthor | PatchName String@@ -24,7 +24,7 @@                | OneHash String                | AfterPatch String | UpToPatch String                | AfterHash String | UpToHash String-               | TagName String | LastN Int | MaxCount Int | PatchIndexRange Int Int+               | TagName String | LastN Int | MaxCount String | PatchIndexRange Int Int                | NumberPatches                | OneTag String | AfterTag String | UpToTag String                | GenContext | Context AbsolutePath | Count@@ -95,4 +95,5 @@                | NoAmendUnrecord | AmendUnrecord                | PatchIndexFlag                | NoPatchIndexFlag+               | EnumPatches | NoEnumPatches                  deriving ( Eq, Show )
src/Darcs/UI/Options/Matching.hs view
@@ -21,14 +21,17 @@     , matchSeveralOrLast     , matchRange     , matchSeveralOrRange-    , matchAny -- temporary, for toMatchFlags+    -- * exported for for checking+    , context+    , matchLast+    , matchFrom+    , matchAny -- temporary hack     ) where  import Prelude () import Darcs.Prelude hiding ( last )  import Data.Char ( isDigit )-import Data.Monoid ( (<>) )  import Darcs.Patch.Match ( MatchFlag(..) ) import qualified Darcs.UI.Options.Flags as F ( DarcsFlag(..) )@@ -59,10 +62,13 @@ matchOneNontag :: MatchOption matchOneNontag =  match <> patch <> hash --- | Used by: rebase pull, apply, send, push, pull, fetch+-- | Used by: rebase pull/apply, send, push, pull, apply, fetch matchSeveral :: MatchOption matchSeveral = matches <> patches <> tags <> hash +matchLast :: MatchOption+matchLast = last+ -- | Used by: rebase unsuspend/reify matchSeveralOrFirst :: MatchOption matchSeveralOrFirst = mconcat [ matchTo, last, matches, patches, tags, hash ]@@ -89,7 +95,7 @@ matchAny :: MatchOption matchAny = mconcat [ toMatch, toPatch, toHash, toTag,   fromMatch, fromPatch, fromHash, fromTag,-  tag, tags, patch, patches, match, matches, index, indexes, context, last ]+  tag, tags, patch, patches, hash, match, matches, index, indexes, context, last ]  -- * Primitive matching options @@ -220,7 +226,7 @@     "select the last NUMBER patches" ]   toInt s = if not (null s) && all isDigit s then read s else (-1) --- | TODO: see 'Darcs.UI.Options.matchMaxcount'.+-- | TODO: see 'Darcs.UI.Options.maxCount'. index = OptSpec {..} where   ounparse k mfs = k [ F.PatchIndexRange n m | PatchIndexRange n m <- mfs ]   oparse k fs = k [ PatchIndexRange n m | F.PatchIndexRange n m <- fs ]@@ -230,7 +236,7 @@                  then F.PatchIndexRange (read s) (read s)                  else F.PatchIndexRange 0 0 --- | TODO: see 'Darcs.UI.Options.matchMaxcount'.+-- | TODO: see 'Darcs.UI.Options.maxCount'. indexes = OptSpec {..} where   ounparse k mfs = k [ F.PatchIndexRange n m | PatchIndexRange n m <- mfs ]   oparse k fs = k [ PatchIndexRange n m | F.PatchIndexRange n m <- fs ]
src/Darcs/UI/PatchHeader.hs view
@@ -10,7 +10,7 @@ import Darcs.Prelude  import Darcs.Patch-    ( IsRepoType, RepoPatch, Patchy, PrimPatch, PrimOf, fromPrims+    ( IsRepoType, RepoPatch, PrimPatch, PrimOf, fromPrims     , effect     , summaryFL     )@@ -27,9 +27,8 @@  import Darcs.Repository ( Repository ) import Darcs.Util.Lock-    ( readLocaleFile-    , writeLocaleFile-    , appendToFile+    ( readTextFile+    , writeTextFile     )  import Darcs.UI.External ( editFile )@@ -38,13 +37,12 @@ import qualified Darcs.UI.SelectChanges as S ( PatchSelectionOptions(..) ) import Darcs.UI.SelectChanges ( askAboutDepends ) -import Darcs.Util.ByteString ( encodeLocale ) import qualified Darcs.Util.Diff as D ( DiffAlgorithm ) import Darcs.Util.English ( capitalize ) import Darcs.Util.Global ( darcsLastMessage ) import Darcs.Util.Path ( FilePathLike, toFilePath ) import Darcs.Util.Prompt ( PromptConfig(..), askUser, promptChar, promptYorn )-import Darcs.Util.Printer ( hPutDocLn, text, ($$), prefixLines, RenderMode(..) )+import Darcs.Util.Printer ( text, ($$), vcat, prefixLines, renderString ) import qualified Darcs.Util.Ratified as Ratified ( hGetContents )  import Darcs.Util.Tree ( Tree )@@ -53,7 +51,6 @@ import Control.Monad ( when, void ) import Control.Monad.Trans              ( liftIO ) import Control.Monad.Trans.State.Strict ( StateT(..), evalStateT, get, put  )-import qualified Data.ByteString as B ( hPut ) import Data.List ( isPrefixOf ) import System.Exit ( exitSuccess ) import System.IO ( stdin )@@ -83,7 +80,7 @@ -- It ensures the patch name is not empty nor starts with the prefix TAG. -- -- The last result component is a possible path to a temporary file that should be removed later.-getLog :: forall prim wX wY . (Patchy prim, PrimPatch prim)+getLog :: forall prim wX wY . PrimPatch prim        => Maybe String                          -- ^ patchname option        -> Bool                                  -- ^ pipe option        -> O.Logfile                             -- ^ logfile option@@ -102,7 +99,7 @@       thelog <- lines `fmap` Ratified.hGetContents stdin       return (p, thelog, Nothing)   go _ (O.Logfile { O._logfile = Just f }) _ = do-      mlp <- lines `fmap` readLocaleFile f `catch` (\(_ :: IOException) -> return [])+      mlp <- readTextFile f `catch` (\(_ :: IOException) -> return [])       firstname <- case (patchname_specified, mlp) of                      (FlagPatchName  p, []) -> return p                      (_, p:_)               -> if badName p@@ -165,7 +162,7 @@   actually_get_log p = do let logf = darcsLastMessage                           -- TODO: make sure encoding used for logf is the same everywhere                           -- probably should be locale because the editor will assume it-                          writeLocaleFile logf $ unlines $ p : default_log+                          writeTextFile logf $ unlines $ p : default_log                           append_info logf p                           _ <- editFile logf                           (name,long) <- read_long_comment logf p@@ -177,28 +174,25 @@    read_long_comment :: FilePathLike p => p -> String -> IO (String, [String])   read_long_comment f oldname =-      do f' <- readLocaleFile f-         let t = filter (not.("#" `isPrefixOf`)) $ (lines.filter (/='\r')) f'-         case t of []     -> return (oldname, [])-                   (n:ls) -> return (n, ls)+      do t <- readTextFile f+         let filter_out_info = filter (not.("#" `isPrefixOf`))+         case reverse $ dropWhile null $ reverse $ filter_out_info t of+            []     -> return (oldname, [])+            (n:ls) -> return (n, ls) -  append_info f oldname =-      do fc <- readLocaleFile f-         appendToFile f $ \h ->-             do case fc of-                  _ | null (lines fc) -> B.hPut h (encodeLocale (oldname ++ "\n"))-                    | last fc /= '\n' -> B.hPut h (encodeLocale "\n")-                    | otherwise       -> return ()-                hPutDocLn Encode h-                     $ text "# Please enter the patch name in the first line, and"-                    $$ text "# optionally, a long description in the following lines."-                    $$ text "#"-                    $$ text "# Lines starting with '#' will be ignored."-                    $$ text "#"-                    $$ text "#"-                    $$ text "# Summary of selected changes:"-                    $$ text "#"-                    $$ prefixLines (text "#") (summaryFL chs)+  append_info f oldname = do+    fc <- readTextFile f+    writeTextFile f $ renderString+       $ vcat (map text $ if null fc then [oldname] else fc)+      $$ text "# Please enter the patch name in the first line, and"+      $$ text "# optionally, a long description in the following lines."+      $$ text "#"+      $$ text "# Lines starting with '#' will be ignored."+      $$ text "#"+      $$ text "#"+      $$ text "# Summary of selected changes:"+      $$ text "#"+      $$ prefixLines (text "#") (summaryFL chs)  -- |specify whether to ask about dependencies with respect to a particular repository, or not data AskAboutDeps rt p wR wU wT = AskAboutDeps (Repository rt p wR wU wT) | NoAskAboutDeps
src/Darcs/UI/PrintPatch.hs view
@@ -15,8 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.UI.PrintPatch     ( printPatch     , contextualPrintPatch@@ -35,17 +33,16 @@ import Darcs.Patch.Apply ( ApplyState ) import Darcs.Patch ( showContextPatch, showPatch, showNicely, description,                      summary )-import Darcs.Patch.Show ( ShowPatch )+import Darcs.Patch.Show ( ShowPatch, ShowContextPatch, ShowPatchFor(ForDisplay) ) import Darcs.UI.External ( viewDocWith )---import Darcs.UI.Flags ( DarcsFlag(Summary, Verbose), isUnified ) import Darcs.UI.Options.All ( Verbosity(..), Summary(..), WithContext(..) ) -import Darcs.Util.Printer ( Doc, putDocLnWith, RenderMode(..) )+import Darcs.Util.Printer ( Doc, putDocLnWith )  -- | @'printFriendly' opts patch@ prints @patch@ in accordance with the flags -- in opts, ie, whether @--verbose@ or @--summary@ were passed at the -- command-line.-printFriendly :: (ShowPatch p, ApplyState p ~ Tree) => Maybe (Tree IO)+printFriendly :: (ShowPatch p, ShowContextPatch p, ApplyState p ~ Tree) => Maybe (Tree IO)               -> Verbosity -> Summary -> WithContext -> p wX wY -> IO () printFriendly (Just pristine) _ _ YesContext = contextualPrintPatch pristine printFriendly _ v s _ = putDocLnWith fancyPrinters . showFriendly v s@@ -59,16 +56,16 @@  -- | 'printPatch' prints a patch on standard output. printPatch :: ShowPatch p => p wX wY -> IO ()-printPatch p = putDocLnWith fancyPrinters $ showPatch p+printPatch p = putDocLnWith fancyPrinters $ showPatch ForDisplay p  -- | 'printPatchPager' runs '$PAGER' and shows a patch in it. printPatchPager :: ShowPatch p => p wX wY -> IO ()-printPatchPager p = viewDocWith fancyPrinters Standard $ showPatch p+printPatchPager p = viewDocWith fancyPrinters $ showPatch ForDisplay p  -- | 'contextualPrintPatch' prints a patch, together with its context, on -- standard output.-contextualPrintPatch :: (ShowPatch p, ApplyState p ~ Tree) => Tree IO+contextualPrintPatch :: (ShowContextPatch p, ApplyState p ~ Tree) => Tree IO                      -> p wX wY -> IO () contextualPrintPatch s p = do-    (contextedPatch, _) <- virtualTreeIO (showContextPatch p) s+    (contextedPatch, _) <- virtualTreeIO (showContextPatch ForDisplay p) s     putDocLnWith fancyPrinters contextedPatch
src/Darcs/UI/RunCommand.hs view
@@ -15,7 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-} -- | This is the actual heavy lifter code, which is responsible for parsing the -- arguments and then running the command itself. module Darcs.UI.RunCommand ( runTheCommand ) where@@ -30,15 +29,15 @@                               getOpt ) import System.Exit ( ExitCode ( ExitSuccess ), exitWith ) -import Darcs.UI.Options ( DarcsOption, (^), odesc, oparse, parseFlags, optDescr )+import Darcs.UI.Options ( (^), odesc, oparse, parseFlags, optDescr, (?) ) import Darcs.UI.Options.All     ( stdCmdActions, StdCmdAction(..)     , anyVerbosity, verbosity, Verbosity(..), network, NetworkOptions(..)-    , preHook, postHook )+    , HooksConfig(..), hooks )  import Darcs.UI.Defaults ( applyDefaults ) import Darcs.UI.External ( viewDoc )-import Darcs.UI.Flags ( DarcsFlag (NewRepo), toMatchFlags, fixRemoteRepos )+import Darcs.UI.Flags ( DarcsFlag (NewRepo), matchAny, fixRemoteRepos ) import Darcs.UI.Commands     ( CommandArgs( CommandOnly, SuperCommandOnly, SuperCommandSub )     , CommandControl@@ -49,20 +48,22 @@     , commandExtraArgHelp     , commandExtraArgs     , commandArgdefaults-    , commandGetArgPossibilities+    , commandCompleteArgs     , commandOptions     , commandParseOptions     , wrappedCommandName     , disambiguateCommands-    , getCommandHelp-    , getCommandMiniHelp     , getSubcommands     , extractCommands     , superName-    , subusage     ) import Darcs.UI.Commands.GZCRCs ( doCRCWarnings ) import Darcs.UI.Commands.Clone ( makeRepoName, cloneToSSH )+import Darcs.UI.Usage+    ( getCommandHelp+    , getCommandMiniHelp+    , subusage+    )  import Darcs.Patch.Match ( checkMatchSyntax ) import Darcs.Repository.Prefs ( getGlobal, getPreflist )@@ -72,7 +73,6 @@ import Darcs.Util.Exception ( die ) import Darcs.Util.Global ( setDebugMode, setTimingsMode ) import Darcs.Util.Path ( AbsolutePath, getCurrentDirectory, toPath, ioAbsoluteOrRemote, makeAbsolute )-import Darcs.Util.Printer ( text ) import Darcs.Util.Progress ( setProgressMode ) import Darcs.Util.Text ( chompTrailingNewline, quote ) @@ -101,16 +101,18 @@       -- must use the (saved) original working directory to resolve possibly       -- relative paths to absolute paths.       prereq_errors <- commandPrereq cmd cmdline_flags+      -- we must get the cwd again because commandPrereq has the side-effect of changing it.+      new_wd <- getCurrentDirectory       user_defs <- getGlobal   "defaults"       repo_defs <- getPreflist "defaults"       let (flags,flag_errors) =             applyDefaults (fmap commandName msuper) cmd old_wd user_defs repo_defs cmdline_flags       case parseFlags stdCmdActions flags of-        Just Help -> viewDoc $ text $ getCommandHelp msuper cmd+        Just Help -> viewDoc $ getCommandHelp msuper cmd         Just ListOptions -> do           setProgressMode False-          file_args <- commandGetArgPossibilities cmd-          putStrLn $ intercalate "\n" $ getOptionsOptions options : file_args+          possible_args <- commandCompleteArgs cmd (new_wd, old_wd) flags orig_extra+          mapM_ putStrLn $ optionList options ++ possible_args         Just Disable ->           die $ "Command "++commandName cmd++" disabled with --disable option!"         Nothing -> case prereq_errors of@@ -121,35 +123,31 @@             [] -> do               extra <- commandArgdefaults cmd flags old_wd orig_extra               case extraArgumentsError extra cmd msuper of-                Nothing     -> runWithHooks cmd old_wd flags extra+                Nothing     -> runWithHooks cmd (new_wd, old_wd) flags extra                 Just msg    -> die msg             es -> die (intercalate "\n" es)  fixupMsgs :: (a, b, [String]) -> (a, b, [String]) fixupMsgs (fs,as,es) = (fs,as,map (("command line: "++).chompTrailingNewline) es) -withHookOpts :: DarcsOption a (t2 -> t3 -> t4 -> t1)-                      -> (t2 -> t3 -> t4 -> t -> t1) -> [DarcsFlag] -> t -> a-withHookOpts opts runHook flags path = oparse opts runHook' flags where-  runHook' mcmd ask verb = runHook mcmd ask verb path- runWithHooks :: DarcsCommand pf-             -> AbsolutePath -> [DarcsFlag] -> [String] -> IO ()-runWithHooks cmd old_wd flags extra = do-   -- NOTE: we must get the cwd again because commandPrereq has the side-effect of changing it.-   new_wd <- getCurrentDirectory-   checkMatchSyntax $ toMatchFlags flags+             -> (AbsolutePath, AbsolutePath)+             -> [DarcsFlag] -> [String] -> IO ()+runWithHooks cmd (new_wd, old_wd) flags extra = do+   checkMatchSyntax $ matchAny ? flags    -- set any global variables    oparse (anyVerbosity ^ network) setGlobalVariables flags    -- actually run the command and its hooks-   preHookExitCode <- withHookOpts (preHook ^ verbosity) runPrehook flags new_wd+   let hooksCfg = parseFlags hooks flags+   let verb = parseFlags verbosity flags+   preHookExitCode <- runPrehook (pre hooksCfg) verb new_wd    if preHookExitCode /= ExitSuccess       then exitWith preHookExitCode       else do fixedFlags <- fixRemoteRepos old_wd flags               phDir <- getPosthookDir new_wd cmd fixedFlags extra               let parsedFlags = commandParseOptions cmd fixedFlags               commandCommand cmd (new_wd, old_wd) parsedFlags extra-              postHookExitCode <- withHookOpts (postHook ^ verbosity) runPosthook flags phDir+              postHookExitCode <- runPosthook (post hooksCfg) verb phDir               exitWith postHookExitCode  setGlobalVariables :: Bool -> Bool -> Verbosity -> Bool -> NetworkOptions -> IO ()@@ -204,10 +202,13 @@             nthOf n (_:hs) = nthOf (n-1) hs             nthOf _ []     = "UNDOCUMENTED" -getOptionsOptions :: [OptDescr DarcsFlag] -> String-getOptionsOptions = intercalate "\n" . concatMap goo- where-  goo (Option _ os _ _) = map ("--"++) os+optionList :: [OptDescr DarcsFlag] -> [String]+optionList = concatMap names+  where+    names (Option sos los _ desc) =+      map (short desc) sos ++ map (long desc) los+    short d o = '-' : o : ";" ++ d+    long d o = "--" ++ o ++ ";" ++ d  runRawSupercommand :: DarcsCommand pf -> [String] -> IO () runRawSupercommand super [] =@@ -219,7 +220,7 @@     -- note: we do not apply defaults here     (flags,_,getopt_errs) -> case parseFlags stdCmdActions flags of       Just Help ->-        viewDoc $ text $ getCommandHelp Nothing super+        viewDoc $ getCommandHelp Nothing super       Just ListOptions -> do         putStrLn "--help"         mapM_ (putStrLn . wrappedCommandName) (extractCommands $ getSubcommands super)
src/Darcs/UI/SelectChanges.hs view
@@ -15,9 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}-- module Darcs.UI.SelectChanges     ( -- * Working with changes       WhichChanges(..)@@ -57,16 +54,16 @@ import Prelude () import Darcs.Prelude -import Prelude hiding ( (^) ) import Control.Monad ( liftM, unless, when, (>=>) ) import Control.Monad.Identity ( Identity (..) ) import Control.Monad.Reader-    ( Reader, ReaderT, asks-    , runReader, runReaderT+    ( ReaderT+    , asks+    , runReaderT     ) import Control.Monad.State     ( StateT, execStateT, gets-    , modify, runStateT+    , modify, runStateT, state     ) import Control.Monad.Trans ( liftIO ) import Data.List ( intercalate, union )@@ -74,41 +71,43 @@ import System.Exit ( exitSuccess )  import Darcs.Patch-    ( Patchy, PrimPatch, IsRepoType, RepoPatch, PrimOf+    ( IsRepoType, RepoPatch, PrimOf     , commuteFLorComplain, invert     , listTouchedFiles, fromPrims     ) import qualified Darcs.Patch ( thing, things, summary )-import Darcs.Patch.Apply ( ApplyState )+import Darcs.Patch.Apply ( Apply, ApplyState ) import Darcs.Patch.Choices     ( PatchChoices, Slot (..), LabelledPatch-    , patchChoicesLps, forceFirsts+    , mkPatchChoices, forceFirsts     , forceFirst, forceLast, forceMatchingFirst     , forceMatchingLast, getChoices     , makeEverythingLater, makeEverythingSooner-    , makeUncertain, patchChoices-    , patchChoicesLpsSub, patchSlot'+    , forceMiddle, patchChoices+    , patchSlot     , refineChoices, selectAllMiddles     , separateFirstFromMiddleLast-    , substitute, label, lpPatch+    , substitute, label, unLabel+    , labelPatches     )+import Darcs.Patch.Commute ( Commute ) import Darcs.Patch.Info ( PatchInfo ) import Darcs.Patch.Inspect ( PatchInspect ) import Darcs.Patch.Invert ( Invert )-import Darcs.Patch.Match ( haveNonrangeMatch, matchAPatch, matchAPatchread )+import Darcs.Patch.Match ( haveNonrangeMatch, matchAPatch ) import Darcs.Patch.Named.Wrapped ( anonymous ) import Darcs.Patch.PatchInfoAnd ( PatchInfoAnd, info, n2pia )-import Darcs.Patch.Set ( PatchSet(..), newset2RL )-import Darcs.Patch.Show ( ShowPatch )-import Darcs.Patch.Split ( Splitter (..) )-import qualified Darcs.Patch.TouchesFiles as TouchesFiles+import Darcs.Patch.Set ( PatchSet(..), patchSet2RL )+import Darcs.Patch.Show ( ShowPatch, ShowContextPatch )+import Darcs.Patch.Split ( Splitter(applySplitter,canonizeSplit) )+import Darcs.Patch.TouchesFiles ( selectNotTouching, deselectNotTouching ) import Darcs.Patch.Type ( PatchType (..) ) import Darcs.Patch.Witnesses.Eq ( unsafeCompare ) import Darcs.Patch.Witnesses.Ordered     ( (:>) (..), (:||:) (..), FL (..)     , RL (..), filterFL, lengthFL, mapFL-    , mapFL_FL, reverseFL, spanFL, spanFL_M-    , (+<+), (+>+), reverseRL+    , mapFL_FL, spanFL, spanFL_M+    , (+>+), (+<<+), (+>>+)     ) import Darcs.Patch.Witnesses.Sealed     ( FlippedSeal (..), Sealed2 (..)@@ -118,7 +117,7 @@     ( FZipper (..), left, right     , rightmost, toEnd, toStart     )-import Darcs.Repository ( Repository, readRepo, readTentativeRepo )+import Darcs.Repository ( Repository, repoLocation, readRepo, readTentativeRepo ) import Darcs.UI.External ( editText ) import Darcs.UI.Options.All     ( Verbosity(..), Summary(..)@@ -127,7 +126,8 @@     ( printFriendly, printPatch     , printPatchPager, showFriendly ) import Darcs.Util.English ( Noun (..), englishNum, capitalize )-import Darcs.Util.Printer ( prefix, putDocLn )+import Darcs.Util.Printer ( prefix, putDocLn, putDocLnWith, greenText )+import Darcs.Util.Printer.Color ( fancyPrinters ) import Darcs.Util.Prompt ( PromptConfig (..), askUser, promptChar ) import Darcs.Util.Tree ( Tree ) @@ -137,32 +137,42 @@ -- of the repository), and we either want an initial segment or a -- final segment of the poset of patches. ----- @First@: ask for an initial+-- 'First': ask for an initial -- segment, first patches first (default for all pull-like commands) ----- @FirstReversed@: ask for an initial segment, last patches first+-- 'FirstReversed': ask for an initial segment, last patches first -- (used to ask about dependencies in record, and for pull-like -- commands with the @--reverse@ flag). ----- @LastReversed@: ask for a final segment, last patches first. (default+-- 'LastReversed': ask for a final segment, last patches first. (default -- for unpull-like commands, except for selecting *primitive* patches in -- rollback) ----- @Last@: ask for a final segment, first patches first. (used for selecting+-- 'Last': ask for a final segment, first patches first. (used for selecting -- primitive patches in rollback, and for unpull-like commands with the -- @--reverse@ flag+--+-- IOW: First = initial segment+--      Last = final segment+--      Reversed = start with the newest patch instead of oldest+-- As usual, terminology is not, ahem, very intuitive. data WhichChanges = Last | LastReversed | First | FirstReversed deriving (Eq, Show) --- | A @WhichChanges@ is backwards if the order in which patches are presented--- is the opposite of the order of dependencies for that operation.+-- | A 'WhichChanges' is 'backward' if the segment of patches we ask for+-- is at the opposite end of where we start to present them. backward :: WhichChanges -> Bool backward w = w == Last || w == FirstReversed +-- | A 'WhichChanges' is reversed if the order in which patches are presented+-- is latest (or newest) patch first.+reversed :: WhichChanges -> Bool+reversed w = w == LastReversed || w == FirstReversed+ -- | The type of the function we use to filter patches when @--match@ is -- given. data MatchCriterion p = MatchCriterion    { mcHasNonrange :: Bool-   , mcFunction :: WhichChanges -> Sealed2 p -> Bool+   , mcFunction :: forall wA wB. WhichChanges -> LabelledPatch p wA wB -> Bool    }  data PatchSelectionOptions = PatchSelectionOptions@@ -187,8 +197,7 @@                                    }  -- | A 'PatchSelectionContext' for selecting 'Prim' patches.-selectionContextPrim :: PrimPatch prim-                     => WhichChanges+selectionContextPrim :: WhichChanges                      -> String                      -> PatchSelectionOptions                      -> Maybe (Splitter prim)@@ -207,8 +216,11 @@      }  -- | A 'PatchSelectionContext' for selecting full patches ('PatchInfoAnd' patches)-selectionContext :: (IsRepoType rt, RepoPatch p) => WhichChanges -> String -> PatchSelectionOptions -> Maybe (Splitter (PatchInfoAnd rt p))-                 -> Maybe [FilePath] -> PatchSelectionContext (PatchInfoAnd rt p)+selectionContext :: (IsRepoType rt, RepoPatch p)+                 => WhichChanges -> String -> PatchSelectionOptions+                 -> Maybe (Splitter (PatchInfoAnd rt p))+                 -> Maybe [FilePath]+                 -> PatchSelectionContext (PatchInfoAnd rt p) selectionContext whch jn o spl fs =  PSC { opts = o      , splitter = spl@@ -240,15 +252,12 @@      }  -- | The dynamic parameters for interactive selection of patches.-data InteractiveSelectionContext p wX wY = ISC { total :: Int-                                                  -- ^ total number of patches-                                                , current :: Int-                                                  -- ^ number of already-seen patches-                                                , lps :: FZipper (LabelledPatch p) wX wY-                                                  -- ^ the patches we offer-                                                , choices :: PatchChoices p wX wY-                                                  -- ^ the user's choices-                                                }+data InteractiveSelectionContext p wX wY =+ ISC { total :: Int                           -- ^ total number of patches+     , current :: Int                         -- ^ number of already-seen patches+     , lps :: FZipper (LabelledPatch p) wX wY -- ^ the patches we offer+     , choices :: PatchChoices p wX wY        -- ^ the user's choices+     }  type PatchSelectionM p a = ReaderT (PatchSelectionContext p) a @@ -256,9 +265,6 @@     StateT (InteractiveSelectionContext p wX wY)            (PatchSelectionM p IO) a -type PatchSelection p wX wY =-        PatchSelectionM p IO ((FL p :> FL p) wX wY)- -- Common match criteria  -- | For commands without @--match@, 'triv' matches all patches@@ -276,56 +282,92 @@     , mcFunction = isWantedMcFunction     }   where-    isWantedMcFunction x = unseal2 $ iw x-    iw First = unseal2 (matchAPatch mflags) . extract-    iw Last = unseal2 (matchAPatch mflags) . extract-    iw LastReversed = unseal2 (matchAPatch mflags) . extract . invert-    iw FirstReversed = unseal2 (matchAPatch mflags) . extract . invert--liftR :: Monad m => Reader r a -> ReaderT r m a-liftR = asks . runReader+    isWantedMcFunction w = unseal2 (matchAPatch mflags) . extract_reverse w . unLabel+    -- TODO inverting should not be necessary here, at least I would expect+    --+    -- prop> matchAPatch (invert x) == matchAPatch x+    extract_reverse w = if reversed w then extract . invert else extract --- | runs a 'PatchSelection' action in the given 'PatchSelectionContext'.-runSelection :: forall p wX wY . (Patchy p, PatchInspect p, ShowPatch p, ApplyState p ~ Tree)+-- | Run a 'PatchSelection' action in the given 'PatchSelectionContext'.+runSelection :: forall p wX wY . ( Invert p, Commute p, Apply p, PatchInspect p, ShowPatch p+                                 , ShowContextPatch p, ApplyState p ~ Tree )              => FL p wX wY              -> PatchSelectionContext p              -> IO ((FL p :> FL p) wX wY)-runSelection ps psc = runReaderT patchSelection psc- where-  patchSelection = do-    case whichChanges psc of-        First -> normal ps-        Last -> normal ps-        FirstReversed -> reversed ps-        LastReversed -> reversed ps-  normal fl = sc1 fl-  reversed fl = do let ifl = invert fl-                   choices_ <- sc1 ifl-                   return $ invertC choices_+runSelection ps psc = runReaderT (selection ps) psc where+  selection+    | reversed whch = fmap invert . doit . invert+    | otherwise = doit+  -- efficiency note: we should first filterUnwanted to apply matchers,+  -- as this often requires to read only metadata; then filterNotTouching+  -- applies path restrictions which needs to read patch contents+  doit =+    fmap (canonizeAfterSplitter . selectedPatches) .+    selectChanges . filterNotTouching . filterUnwanted . patchChoices -sc1 :: forall p wX wY . (Patchy p, PatchInspect p, ShowPatch p, ApplyState p ~ Tree) =>-                                FL p wX wY-                             -> PatchSelection p wX wY-sc1 fl = do ps <- liftR (patchesToConsider fl)-            patchChoices_ <- realSelectChanges ps-            whch <- asks whichChanges-            let sps = selectedPatches whch patchChoices_-            liftR (canonizeAfterSplitter sps)+  -- configuration+  whch = whichChanges psc+  fs = files psc+  os = opts psc+  crit = matchCriterion psc+  mspl = splitter psc --- | inverses the choices that have been made-invertC :: (Patchy p) => (FL p :> FL p) wX wY -> (FL p :> FL p) wY wX-invertC (a :> b) = invert b :> invert a+  -- after selecting with a splitter, the results may not be canonical+  canonizeAfterSplitter :: (FL p :> FL p) wA wB -> (FL p :> FL p) wA wB+  canonizeAfterSplitter (x :> y) =+    let canonizeIfNeeded = maybe id canonizeSplit mspl+    in canonizeIfNeeded x :> canonizeIfNeeded y --- | Shows the patch that is actually being selected the way the user--- should see it.-repr :: (Patchy p) => WhichChanges -> Sealed2 p -> Sealed2 p-repr First (Sealed2 p) = Sealed2 p-repr LastReversed (Sealed2 p) = Sealed2 (invert p)-repr Last (Sealed2 p) = Sealed2 p-repr FirstReversed (Sealed2 p) = Sealed2 (invert p)+  -- retrieve the results of patch selection+  selectedPatches :: PatchChoices p wA wB -> (FL p :> FL p) wA wB+  selectedPatches pc+    | backward whch =+        case getChoices pc of+          fc :> mc :> lc -> mapFL_FL unLabel (fc +>+ mc) :> mapFL_FL unLabel lc+    | otherwise =+        case separateFirstFromMiddleLast pc of+          xs :> ys -> mapFL_FL unLabel xs :> mapFL_FL unLabel ys +  selectChanges :: PatchChoices p wA wB+                -> PatchSelectionM p IO (PatchChoices p wA wB)+  selectChanges+    | interactive os = refineChoices textSelect+    | otherwise      = return . promote++  promote+    | backward whch = makeEverythingLater+    | otherwise     = makeEverythingSooner+  demote+    | backward whch = makeEverythingSooner+    | otherwise     = makeEverythingLater++  filterNotTouching+    | backward whch = selectNotTouching fs+    | otherwise     = deselectNotTouching fs++  -- when using @--match@, remove unmatched patches+  -- not depended upon by matched patches+  filterUnwanted :: PatchChoices p wA wB -> PatchChoices p wA wB+  filterUnwanted+    | mcHasNonrange crit =+        case selectDeps os of+          NoDeps -> deselectUnwanted+          _      -> demote . selectWanted+    | otherwise = id++  selectWanted+    | backward whch = forceMatchingLast iswanted_+    | otherwise     = forceMatchingFirst iswanted_+  deselectUnwanted+    | backward whch = forceMatchingFirst (not . iswanted_)+    | otherwise     = forceMatchingLast (not . iswanted_)+  iswanted_ = mcFunction crit whch++  {- end of runSelection -}+ -- | The equivalent of 'runSelection' for the @darcs log@ command-viewChanges :: (Patchy p, ShowPatch p, ApplyState p ~ Tree) => PatchSelectionOptions -> [Sealed2 p] -> IO ()+viewChanges :: (ShowPatch p, ShowContextPatch p, ApplyState p ~ Tree)+            => PatchSelectionOptions -> [Sealed2 p] -> IO () viewChanges ps_opts = textView ps_opts Nothing 0 []  -- | The type of the answers to a "shall I [wiggle] that [foo]?" question@@ -352,8 +394,8 @@ keysFor = concatMap (map kp)  -- | The function for selecting a patch to amend record. Read at your own risks.-withSelectedPatchFromRepo ::-       forall rt p wR wU wT. (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+withSelectedPatchFromRepo+    :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)     => String   -- name of calling command (always "amend" as of now)     -> Repository rt p wR wU wT     -> PatchSelectionOptions@@ -361,7 +403,7 @@     -> IO () withSelectedPatchFromRepo jn repository o job = do     patchSet <- readRepo repository-    sp <- wspfr jn (matchAPatchread $ matchFlags o) (newset2RL patchSet) NilFL+    sp <- wspfr jn (matchAPatch $ matchFlags o) (patchSet2RL patchSet) NilFL     case sp of         Just (FlippedSeal (skipped :> selected')) -> job (skipped :> selected')         Nothing ->@@ -369,7 +411,10 @@  data SkippedReason = SkippedAutomatically | SkippedManually -data WithSkipped p wX wY = WithSkipped { _skippedReason :: SkippedReason, skippedPatch :: p wX wY }+data WithSkipped p wX wY = WithSkipped+    { _skippedReason :: SkippedReason+    , skippedPatch :: p wX wY+    }  -- | This ensures that the selected patch commutes freely with the skipped -- patches, including pending and also that the skipped sequences has an@@ -416,7 +461,8 @@         nextPatch = wspfr jn matches pps (WithSkipped SkippedManually p:>:skipped)         previousPatch :: RL (PatchInfoAnd rt p) wX wQ                       -> FL (WithSkipped (PatchInfoAnd rt p)) wQ wU-                      -> IO (Maybe (FlippedSeal (FL (PatchInfoAnd rt p) :> PatchInfoAnd rt p) wU))+                      -> IO (Maybe (FlippedSeal+                              (FL (PatchInfoAnd rt p) :> PatchInfoAnd rt p) wU))         previousPatch remaining' NilFL = wspfr jn matches remaining' NilFL         previousPatch remaining' (WithSkipped sk prev :>: skipped'') =             case sk of@@ -437,111 +483,9 @@         defaultPrintFriendly =           printFriendly Nothing NormalVerbosity NoSummary NoContext --- After selecting with a splitter, the results may not be canonical-canonizeAfterSplitter :: (FL p :> FL p) wX wY -> Reader (PatchSelectionContext p) ((FL p :> FL p) wX wY)-canonizeAfterSplitter (x :> y) =-    do mspl <- asks splitter-       let canonizeIfNeeded = maybe id canonizeSplit mspl-       return $ canonizeIfNeeded x :> canonizeIfNeeded y--realSelectChanges :: forall p wX wY.-                     (Patchy p, ShowPatch p, PatchInspect p, ApplyState p ~ Tree)-                  => PatchChoices p wX wY-                  -> PatchSelectionM p IO (PatchChoices p wX wY)-realSelectChanges autoChoices =-    do-      o <- asks opts-      whch <- asks whichChanges-      if not $ interactive o-       then return $ promote whch autoChoices-       else refineChoices textSelect autoChoices-    where forward whch = not $ backward whch-          promote whch =-              if forward whch-                  then makeEverythingSooner-                  else makeEverythingLater---- | When using @--match@, remove unmatched patches not depended upon by matched--- patches.-deselectUnwanted :: forall p wX wY . Patchy p =>-                     PatchChoices p wX wY ->-                     Reader (PatchSelectionContext p) (PatchChoices p wX wY)-deselectUnwanted pc =-    do-      o <- asks opts-      mc <- asks matchCriterion-      whichch <- asks whichChanges-      let iswanted_ = mcFunction mc whichch . seal2 . lpPatch-          select = if forward whichch-                   then forceMatchingFirst iswanted_-                   else forceMatchingLast iswanted_-          deselect = if forward whichch-                     then forceMatchingLast (not . iswanted_)-                     else forceMatchingFirst (not . iswanted_)-      return $-        if mcHasNonrange mc-            then if selectDeps o == NoDeps-                 then deselect pc-                 else demote whichch $ select pc-            else pc-    where-      forward whichch = not $ backward whichch-      demote whichch =-          if forward whichch-            then makeEverythingLater-            else makeEverythingSooner---- | Selects the patches matching the match criterion, and puts them first or last--- according to whch, while respecting any dependencies.-patchesToConsider :: forall p wX wY-                      . (Patchy p, PatchInspect p, ApplyState p ~ Tree)-                     => FL p wX wY-                     -> Reader (PatchSelectionContext p) (PatchChoices p wX wY)-patchesToConsider ps =-    do-      fs <- asks files-      crit <- asks matchCriterion-      whch <- asks whichChanges-      let deselectNotTouching =-              case whch of-                First -> TouchesFiles.deselectNotTouching-                Last -> TouchesFiles.selectNotTouching-                FirstReversed -> TouchesFiles.selectNotTouching-                LastReversed -> TouchesFiles.deselectNotTouching-          everything = patchChoices ps-      -- first filter patches by matchers-      -- this often requires to read only metadata-      notUnwanted <- if not (mcHasNonrange crit)-                       then return everything-                       else deselectUnwanted everything-      -- if there are path restrictions, we need to read patch contents-      -- of what remains-      return $ if isJust fs then deselectNotTouching fs notUnwanted-                            else notUnwanted---- | Returns the results of a patch selection user interaction-selectedPatches :: Patchy p => WhichChanges -> PatchChoices p wY wZ-                      -> (FL p :> FL p) wY wZ-selectedPatches Last pc =-  case getChoices pc of-   fc :> mc :> lc -> mapFL_FL lpPatch (fc +>+ mc) :> mapFL_FL lpPatch lc--selectedPatches First pc =-  case separateFirstFromMiddleLast pc of-  xs :> ys -> mapFL_FL lpPatch xs :> mapFL_FL lpPatch ys--selectedPatches LastReversed pc =-  case separateFirstFromMiddleLast pc of-  xs :> ys -> mapFL_FL lpPatch xs :> mapFL_FL lpPatch ys--selectedPatches FirstReversed pc =-  case getChoices pc of-  fc :> mc :> lc -> mapFL_FL lpPatch (fc +>+ mc) :> mapFL_FL lpPatch lc- -- | Runs a function on the underlying @PatchChoices@ object-liftChoices :: forall p a wX wY . Patchy p =>-               StateT (PatchChoices p wX wY) Identity a-                   -> InteractiveSelectionM p wX wY a+liftChoices :: StateT (PatchChoices p wX wY) Identity a+            -> InteractiveSelectionM p wX wY a liftChoices act = do   ch <- gets choices   let (result, _) = runIdentity $ runStateT act ch@@ -549,12 +493,14 @@   return result  -- | @justDone n@ notes that @n@ patches have just been processed-justDone :: Patchy p => Int -> InteractiveSelectionM p wX wY ()+justDone :: Int -> InteractiveSelectionM p wX wY () justDone n = modify $ \isc -> isc{ current = current isc + n}  -- | The actual interactive selection process.-textSelect :: forall p wX wY . (Patchy p, ShowPatch p, PatchInspect p, ApplyState p ~ Tree)-           => FL (LabelledPatch p) wX wY -> PatchChoices p wX wY+textSelect :: ( Commute p, Invert p, ShowPatch p, ShowContextPatch p+              , PatchInspect p, ApplyState p ~ Tree )+           => FL (LabelledPatch p) wX wY+           -> PatchChoices p wX wY            -> PatchSelectionM p IO (PatchChoices p wX wY) textSelect lps' pcs = do     userSelection <- execStateT (skipMundane >>@@ -570,7 +516,8 @@             unless (rightmost z) $               textSelect' -textSelect' :: (Patchy p, ShowPatch p, PatchInspect p, ApplyState p ~ Tree)+textSelect' :: ( Commute p, Invert p, ShowPatch p, ShowContextPatch p+               , PatchInspect p, ApplyState p ~ Tree )             => InteractiveSelectionM p wX wY () textSelect' = do   z <- gets lps@@ -602,7 +549,8 @@  optionsQuit :: String -> Bool -> String -> [KeyPress] optionsQuit jn allowsa someThings =-    [ KeyPress 'd' (jn++" selected "++someThings++", skipping all the remaining "++someThings)+    [ KeyPress 'd' (jn++" selected "++someThings+++                    ", skipping all the remaining "++someThings)             | allowsa ]     ++     [ KeyPress 'a' (jn++" all the remaining "++someThings)@@ -632,8 +580,9 @@     , KeyPress 'd' "confirm this operation"     , KeyPress 'n' ("cancel " ++ jn) ]]) -options :: forall p wX wY . (Patchy p, ShowPatch p) => Bool ->-           InteractiveSelectionM p wX wY ([[KeyPress]],[[KeyPress]])+options :: (ShowPatch p)+        => Bool+        -> InteractiveSelectionM p wX wY ([[KeyPress]],[[KeyPress]]) options single = do   split <- asks splitter   jn <- asks jobname@@ -654,33 +603,28 @@  -- | Returns a @Sealed2@ version of the patch we are asking the user -- about.-currentPatch :: forall p wX wY . Patchy p =>-               InteractiveSelectionM p wX wY-                    (Maybe (Sealed2 (LabelledPatch p)))+currentPatch :: InteractiveSelectionM p wX wY (Maybe (Sealed2 (LabelledPatch p))) currentPatch = do-  (FZipper _ lps_todo) :: FZipper (LabelledPatch p) wX wY <- gets lps+  FZipper _ lps_todo <- gets lps   case lps_todo of     NilFL -> return Nothing     (lp:>:_) -> return $ Just (Sealed2 lp)  -- | Returns the patches we have yet to ask the user about.-todo :: forall p wX wY . Patchy p-        => InteractiveSelectionM p wX wY-              (FlippedSeal (FL (LabelledPatch p)) wY)+todo :: InteractiveSelectionM p wX wY (FlippedSeal (FL (LabelledPatch p)) wY) todo = do     (FZipper _ lps_todo) <- gets lps     return (FlippedSeal lps_todo)  -- | Modify the underlying @PatchChoices@ by some function-modChoices :: forall p wX wY . Patchy p =>-              (PatchChoices p wX wY -> PatchChoices p wX wY)+modifyChoices :: (PatchChoices p wX wY -> PatchChoices p wX wY)               -> InteractiveSelectionM p wX wY ()-modChoices f = modify $ \isc -> isc{choices = f $ choices isc}+modifyChoices f = modify $ \isc -> isc{choices = f $ choices isc}  -- | returns @Just f@ if the 'currentPatch' only modifies @f@, -- @Nothing@ otherwise.-currentFile :: forall p wX wY . (Patchy p, PatchInspect p)-               => InteractiveSelectionM p wX wY (Maybe FilePath)+currentFile :: (PatchInspect p)+            => InteractiveSelectionM p wX wY (Maybe FilePath) currentFile = do   c <- currentPatch   return $ case c of@@ -692,18 +636,19 @@  -- | @decide True@ selects the current patch, and @decide False@ deselects -- it.-decide :: forall p wX wY wT wU . Patchy p => Bool-         -> LabelledPatch p wT wU-         -> InteractiveSelectionM p wX wY ()+decide :: Commute p+       => Bool+       -> LabelledPatch p wT wU+       -> InteractiveSelectionM p wX wY () decide takeOrDrop lp = do     whch <- asks whichChanges     if backward whch == takeOrDrop -- we go backward xor we are dropping-    then modChoices $ forceLast (label lp)-    else modChoices $ forceFirst (label lp)+    then modifyChoices $ forceLast (label lp)+    else modifyChoices $ forceFirst (label lp)  -- | like 'decide', but for all patches touching @file@-decideWholeFile :: forall p wX wY. (Patchy p, PatchInspect p) =>-                  FilePath -> Bool -> InteractiveSelectionM p wX wY ()+decideWholeFile :: (Commute p, PatchInspect p)+                => FilePath -> Bool -> InteractiveSelectionM p wX wY () decideWholeFile file takeOrDrop =     do       FlippedSeal lps_todo <- todo@@ -712,30 +657,29 @@       mapM_ (unseal2 $ decide takeOrDrop) patches_to_skip  -- | Undecide the current patch.-postponeNext :: forall p wX wY . Patchy p => InteractiveSelectionM p wX wY ()+postponeNext :: Commute p => InteractiveSelectionM p wX wY () postponeNext =     do       Just (Sealed2 lp) <- currentPatch-      modChoices $ makeUncertain (label lp)+      modifyChoices $ forceMiddle (label lp)  -- | Focus the next patch.-skipOne :: forall p wX wY . Patchy p => InteractiveSelectionM p wX wY ()+skipOne :: InteractiveSelectionM p wX wY () skipOne = modify so     where so x = x{lps = right (lps x), current = current x +1}  -- | Focus the previous patch.-backOne :: forall p wX wY . Patchy p => InteractiveSelectionM p wX wY ()+backOne :: InteractiveSelectionM p wX wY () backOne = modify so     where so isc = isc{lps = left (lps isc), current = max (current isc-1) 0}  -- | Split the current patch (presumably a hunk), and add the replace it -- with its parts.-splitCurrent :: forall p wX wY . Patchy p-             => Splitter p+splitCurrent :: Splitter p              -> InteractiveSelectionM p wX wY () splitCurrent s = do     FZipper lps_done (lp:>:lps_todo) <- gets lps-    case applySplitter s (lpPatch lp) of+    case applySplitter s (unLabel lp) of       Nothing -> return ()       Just (text, parse) ->           do@@ -743,8 +687,7 @@             case parse newText of                Nothing -> return ()                Just ps -> do-                 lps_new <- liftIO . return . snd-                             $ patchChoicesLpsSub (Just (label lp)) ps+                 lps_new <- liftIO $ return $ labelPatches (Just (label lp)) ps                  modify $ \isc -> isc { total = total isc + lengthFL lps_new - 1                                       , lps = FZipper lps_done                                                (lps_new +>+ lps_todo)@@ -753,51 +696,50 @@                                                    (choices isc)                                       } +-- | Shows the patch that is actually being selected the way the user+-- should see it.+repr :: Invert p => WhichChanges -> LabelledPatch p wX wY -> Sealed2 p+repr w p+  | reversed w = Sealed2 (invert (unLabel p))+  | otherwise = Sealed2 (unLabel p)+ -- | Returns a list of the currently selected patches, in -- their original context, i.e., not commuted past unselected -- patches.-selected :: forall p wX wY. Patchy p =>-           InteractiveSelectionM p wX wY [Sealed2 p]+selected :: (Commute p, Invert p) => InteractiveSelectionM p wX wY [Sealed2 p] selected = do-  whichch <- asks whichChanges-  c <- gets choices-  (first_chs :> _ :> last_chs) <- return $ getChoices c-  return $ if backward whichch-           then-               mapFL (repr whichch . Sealed2 . lpPatch) last_chs-           else-               mapFL (repr whichch . Sealed2 . lpPatch) first_chs+  w <- asks whichChanges+  chs <- gets choices+  (first_chs :> _ :> last_chs) <- return $ getChoices chs+  return $ if backward w then mapFL (repr w) last_chs else mapFL (repr w) first_chs  -- | Prints the list of the selected patches. See 'selected'.-printSelected :: (Patchy p, ShowPatch p) =>+printSelected :: (Invert p, Commute p, ShowPatch p) =>                 InteractiveSelectionM p wX wY () printSelected = do   someThings <- things   o <- asks opts   s <- selected   liftIO $ do-    putStrLn $ "---- Already selected "++someThings++" ----"-    mapM_ (putDocLn . unseal2 (showFriendly (verbosity o) (summary o))) s-    putStrLn $ "---- end of already selected "++someThings++" ----"+    putDocLnWith fancyPrinters $ greenText $ "---- selected "++someThings++" ----"+    mapM_ (putDocLnWith fancyPrinters . unseal2 (showFriendly (verbosity o) (summary o))) s+    putDocLnWith fancyPrinters $ greenText $ "---- end of selected "++someThings++" ----" -printSummary :: forall p wX wY . ShowPatch p => p wX wY -> IO ()+printSummary :: ShowPatch p => p wX wY -> IO () printSummary = putDocLn . prefix "    " . Darcs.Patch.summary  -- | Skips all remaining patches.-skipAll :: forall p wX wY . Patchy p =>-          InteractiveSelectionM p wX wY ()+skipAll ::  InteractiveSelectionM p wX wY () skipAll = modify $ \isc -> isc {lps = toEnd $ lps isc} -backAll :: forall p wX wY . Patchy p =>-          InteractiveSelectionM p wX wY ()+backAll ::  InteractiveSelectionM p wX wY () backAll = modify $ \isc -> isc {lps = toStart $ lps isc                                ,current = 0}  isSingleFile :: PatchInspect p => p wX wY -> Bool isSingleFile p = length (listTouchedFiles p) == 1 -askConfirmation :: forall p wX wY . Patchy p =>-                   InteractiveSelectionM p wX wY ()+askConfirmation ::  InteractiveSelectionM p wX wY () askConfirmation = do     jn <- asks jobname     liftIO $ when (jn `elem` ["unpull", "unrecord", "obliterate"]) $ do@@ -807,21 +749,21 @@                  _ -> exitSuccess  -- | The singular form of the noun for items of type @p@.-thing :: (Patchy p, ShowPatch p) => InteractiveSelectionM p wX wY String+thing :: (ShowPatch p) => InteractiveSelectionM p wX wY String thing = (Darcs.Patch.thing . helper) `liftM` gets choices         where           helper :: PatchChoices p wA wB -> p wA wB           helper = undefined  -- | The plural form of the noun for items of type @p@.-things :: (Patchy p, ShowPatch p) => InteractiveSelectionM p wX wY String+things :: (ShowPatch p) => InteractiveSelectionM p wX wY String things = (Darcs.Patch.things . helper) `liftM` gets choices         where           helper :: PatchChoices p wA wB -> p wA wB           helper = undefined  -- | The question to ask about one patch.-prompt :: (Patchy p, ShowPatch p) => InteractiveSelectionM p wX wY String+prompt :: (ShowPatch p) => InteractiveSelectionM p wX wY String prompt = do   jn <- asks jobname   aThing <- thing@@ -831,8 +773,8 @@              ++ "(" ++ show (n+1) ++ "/" ++ show n_max ++ ") "  -- | Asks the user about one patch, returns their answer.-promptUser :: forall p wX wY . (Patchy p, ShowPatch p) => Bool -> Char-              -> InteractiveSelectionM p wX wY Char+promptUser :: (ShowPatch p)+           => Bool -> Char -> InteractiveSelectionM p wX wY Char promptUser single def = do   thePrompt <- prompt   (basicOptions,advancedOptions) <- options single@@ -844,7 +786,8 @@                                    }  -- | Ask the user what to do with the next patch.-textSelectOne :: forall p wX wY. (Patchy p, ShowPatch p, PatchInspect p, ApplyState p ~ Tree)+textSelectOne :: ( Invert p, Commute p, ShowPatch p, ShowContextPatch p, PatchInspect p+                 , ApplyState p ~ Tree )               => InteractiveSelectionM p wX wY Bool textSelectOne = do  c <- currentPatch@@ -855,11 +798,11 @@          jn <- asks jobname          spl <- asks splitter          whichch <- asks whichChanges-         let singleFile = isSingleFile (lpPatch lp)-             reprCur = repr whichch (Sealed2 (lpPatch lp))+         let singleFile = isSingleFile (unLabel lp)+             reprCur = repr whichch lp          (basicOptions,advancedOptions) <- options singleFile-         theSlot <- liftChoices $ patchSlot' lp-         let the_default = getDefault (whichch == Last || whichch == FirstReversed) theSlot+         theSlot <- liftChoices $ state $ patchSlot lp+         let the_default = getDefault (backward whichch) theSlot          yorn <- promptUser singleFile the_default          let nextPatch = skipMundane >> showCur          case yorn of@@ -888,7 +831,7 @@                'a' ->                    do                      askConfirmation-                     modChoices $ selectAllMiddles (whichch == Last || whichch == FirstReversed)+                     modifyChoices $ selectAllMiddles (backward whichch)                      skipAll                      return True                'q' -> liftIO $@@ -900,15 +843,16 @@                  liftIO . putStrLn $ helpFor jn basicOptions advancedOptions                  return False -lastQuestion :: forall p wX wY . (Patchy p, ShowPatch p, ApplyState p ~ Tree) =>-                InteractiveSelectionM p wX wY Bool+lastQuestion :: (Commute p, Invert p, ShowPatch p, ShowContextPatch p, ApplyState p ~ Tree)+             => InteractiveSelectionM p wX wY Bool lastQuestion = do   jn <- asks jobname   theThings <-things   aThing <- thing   let (basicOptions, advancedOptions) = optionsLast jn aThing   yorn <- liftIO . promptChar $-            PromptConfig { pPrompt = "Do you want to "++capitalize jn++" these "++theThings++"?"+            PromptConfig { pPrompt = "Do you want to "++capitalize jn+++                                      " these "++theThings++"?"                          , pBasicCharacters = "yglqk"                          , pAdvancedCharacters = "dan"                          , pDefault = Just 'y'@@ -921,11 +865,12 @@                'l' -> printSelected >> return False                'k' -> backOne >> showCur >> return False                _ -> do-                 liftIO . putStrLn $ helpFor "this confirmation prompt" basicOptions advancedOptions+                 liftIO . putStrLn $ helpFor "this confirmation prompt"+                    basicOptions advancedOptions                  return False  -- | Shows the current patch as it should be seen by the user.-showCur :: forall p wX wY . (Patchy p, ShowPatch p, ApplyState p ~ Tree)+showCur :: (Invert p, ShowPatch p, ShowContextPatch p, ApplyState p ~ Tree)         => InteractiveSelectionM p wX wY () showCur = do   o <- asks opts@@ -935,11 +880,11 @@   case c of       Nothing -> return ()       Just (Sealed2 lp) -> do-             let reprCur = repr whichch (Sealed2 (lpPatch lp))+             let reprCur = repr whichch lp              liftIO . unseal2 (printFriendly p (verbosity o) (summary o) (withContext o)) $ reprCur  -- | The interactive part of @darcs changes@-textView :: forall p . (Patchy p, ShowPatch p, ApplyState p ~ Tree)+textView :: (ShowPatch p, ShowContextPatch p, ApplyState p ~ Tree)          => PatchSelectionOptions -> Maybe Int -> Int          -> [Sealed2 p] -> [Sealed2 p]          -> IO ()@@ -1007,7 +952,7 @@                     | otherwise    = Just $ length ps_done + length ps_todo  -- | Skips patches we should not ask the user about-skipMundane :: (Patchy p, ShowPatch p)+skipMundane :: (Commute p, ShowPatch p)             => InteractiveSelectionM p wX wY () skipMundane = do   (FZipper lps_done lps_todo) <- gets lps@@ -1016,20 +961,21 @@   jn <- asks jobname   whichch <- asks whichChanges   (skipped :> unskipped) <- liftChoices $ spanFL_M-                                 (patchSlot' >=> return . decided)+                                 (state . patchSlot >=> return . decided)                                  lps_todo   let numSkipped = lengthFL skipped   when (numSkipped > 0) . liftIO $ show_skipped o jn numSkipped skipped   let boringThenInteresting =           if selectDeps o == AutoDeps-          then spanFL (not. mcFunction crit whichch . seal2 . lpPatch)+          then spanFL (not. mcFunction crit whichch)                                  unskipped           else NilFL :> unskipped   case boringThenInteresting of     boring :> interesting ->         do           justDone $ lengthFL boring + numSkipped-          modify $ \isc -> isc {lps = FZipper (lps_done +<+ reverseFL skipped +<+ reverseFL boring) interesting}+          modify $ \isc -> isc {lps = FZipper (lps_done +<<+ skipped +<<+ boring)+                                      interesting}     where       show_skipped o jn n ps = do putStrLn $ _nevermind_ jn ++ _these_ n ++ "."                                   when (verbosity o == Verbose) $@@ -1037,9 +983,8 @@       _nevermind_ jn = "Will not ask whether to " ++ jn ++ " "       _these_ n  = show n ++ " already decided " ++ _elem_ n ""       _elem_ n = englishNum n (Noun "patch")-      showskippedpatch :: (Patchy p, ShowPatch p) => FL (LabelledPatch p) wY wT -> IO ()-      showskippedpatch =-                    sequence_ . mapFL (printSummary . lpPatch)+      showskippedpatch :: ShowPatch p => FL (LabelledPatch p) wY wT -> IO ()+      showskippedpatch = sequence_ . mapFL (printSummary . unLabel)  decided :: Slot -> Bool decided InMiddle = False@@ -1054,7 +999,7 @@ getDefault False InFirst = 'y' getDefault False InLast  = 'n' -askAboutDepends :: forall rt p wR wU wT wY . (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)+askAboutDepends :: (IsRepoType rt, RepoPatch p, ApplyState p ~ Tree)                 => Repository rt p wR wU wT -> FL (PrimOf p) wT wY                 -> PatchSelectionOptions                 -> [PatchInfo] -> IO [PatchInfo]@@ -1062,49 +1007,23 @@   -- ideally we'd just default the olddeps to yes but still ask about them.   -- SelectChanges doesn't currently (17/12/09) offer a way to do this so would   -- have to have this support added first.-  pps <- readTentativeRepo repository+  pps <- readTentativeRepo repository (repoLocation repository)   pa <- n2pia `fmap` anonymous (fromPrims pa')   -- FIXME: this code is completely unreadable-  FlippedSeal ps <- return-                      ((case pps of-                          PatchSet _ x -> FlippedSeal (reverseRL x+>+(pa:>:NilFL)))-                         :: FlippedSeal (FL (PatchInfoAnd rt p)) wY)-  let (pc, my_lps) = patchChoicesLps ps-      tas = case catMaybes (mapFL (\lp -> if pa `unsafeCompare` lpPatch lp || info (lpPatch lp) `elem` olddeps+  FlippedSeal ps <-+    return $ case pps of PatchSet _ x -> FlippedSeal (x+>>+(pa:>:NilFL))+  let my_lps = labelPatches Nothing ps+      pc = mkPatchChoices my_lps+      tas =+        case catMaybes (mapFL (\lp -> if pa `unsafeCompare` unLabel lp || info (unLabel lp) `elem` olddeps                                           then Just (label lp) else Nothing) my_lps) of                  [] -> error "askAboutDepends: []"                 tgs -> tgs-  Sealed2 ps' <- return $ case getChoices (forceFirsts tas pc) of _ :> mc :> _ -> Sealed2 $ mapFL_FL lpPatch mc+  Sealed2 ps' <- return $+    case getChoices (forceFirsts tas pc) of+      _ :> mc :> _ -> Sealed2 $ mapFL_FL unLabel mc   (deps:>_) <- runSelection ps' $-                 selectionContext FirstReversed "depend on" ps_opts { matchFlags = [], interactive = True } Nothing Nothing+                 selectionContext FirstReversed "depend on" ps_opts+                    { matchFlags = [], interactive = True } Nothing Nothing   return $ olddeps `union` mapFL info deps-{--  where-    askdep_allowed = not . patchSelectFlag-    opts' = filter askdep_allowed cfg-    psOpts = (recordPatchSelOpts cfg)--}--{---- | @'patchSelectFlag' f@ holds whenever @f@ is a way of selecting--- patches such as @PatchName n@. <- ???-patchSelectFlag :: F.DarcsFlag -> Bool-patchSelectFlag F.All = True-patchSelectFlag (F.PatchName _) = True      -- ???-patchSelectFlag (F.OnePatch _) = True-patchSelectFlag (F.OneHash _) = True-patchSelectFlag (F.SeveralPatch _) = True-patchSelectFlag (F.AfterPatch _) = True-patchSelectFlag (F.UpToPatch _) = True-patchSelectFlag (F.TagName _) = True-patchSelectFlag (F.LastN _) = True-patchSelectFlag (F.OneTag _) = True-patchSelectFlag (F.AfterTag _) = True-patchSelectFlag (F.UpToTag _) = True-patchSelectFlag (F.OnePattern _) = True-patchSelectFlag (F.SeveralPattern _) = True-patchSelectFlag (F.AfterPattern _) = True-patchSelectFlag (F.UpToPattern _) = True-patchSelectFlag _ = False--}
src/Darcs/UI/TheCommands.hs view
@@ -15,7 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-} module Darcs.UI.TheCommands ( commandControlList ) where  import Prelude ()
src/Darcs/UI/Usage.hs view
@@ -9,39 +9,63 @@ --        --no-recursive        don't add contents of subdirectories --  @ -module Darcs.UI.Usage ( usageInfo ) where+{-# LANGUAGE OverloadedStrings #-}+module Darcs.UI.Usage+    ( usageInfo+    , formatOptions+    , getCommandHelp+    , getCommandMiniHelp+    , usage+    , subusage+    ) where  import Prelude () import Darcs.Prelude  import Data.Functor.Compose import System.Console.GetOpt( OptDescr(..), ArgDescr(..) )-import Darcs.UI.Options ( DarcsOptDescr )+import Darcs.UI.Options.All ( stdCmdActions )+import Darcs.UI.Commands+    ( CommandControl(..)+    , DarcsCommand(..)+    , wrappedCommandName+    , wrappedCommandDescription+    , getSubcommands+    , commandAlloptions+    )+import Darcs.UI.Options ( DarcsOptDescr, odesc )+import Darcs.Util.Printer+    ( Doc, text, vsep, ($$), vcat, hsep+    , renderString+    ) --- | Variant of 'System.Console.GetOpt.usageInfo'.--- Return a string describing the usage of a command, derived from the header--- (first argument) and the options described by the second argument.------ Sequences of long switches are presented on separate lines.-usageInfo :: String         -- header-          -> [DarcsOptDescr a]    -- option descriptors-          -> String          -- nicely formatted decription of options-usageInfo header optDescr = unlines (header:table)-   where (ss,ls,ds)     = (unzip3 . concatMap fmtOpt) optDescr+formatOptions :: [DarcsOptDescr a] -> [String]+formatOptions optDescrs = table+   where (ss,ls,ds)     = (unzip3 . concatMap fmtOpt) optDescrs          table          = zipWith3 paste                             shortPadded                             (zipWith (++) (map (unlines' . init) ls)                                           (sameLen $ map last ls))                             ds          shortPadded    = sameLen ss-         prePad         = replicate (4 + length (head shortPadded)) ' '+         prePad         = replicate (3 + length (head shortPadded)) ' '          -- Similar to unlines (additional ',' and padding):          unlines'       = concatMap (\x -> x ++ ",\n" ++ prePad)          -- Unchanged:-         paste x y z    = "  " ++ x ++ "  " ++ y ++ "  " ++ z+         paste x y z    = "  " ++ x ++ " " ++ y ++ "  " ++ z          sameLen xs     = flushLeft ((maximum . map length) xs) xs          flushLeft n xs = [ take n (x ++ repeat ' ') | x <- xs ] +-- | Variant of 'System.Console.GetOpt.usageInfo'.+-- Return a string describing the usage of a command, derived from the header+-- (first argument) and the options described by the second argument.+--+-- Sequences of long switches are presented on separate lines.+usageInfo :: String         -- header+          -> [DarcsOptDescr a]    -- option descriptors+          -> String          -- nicely formatted decription of options+usageInfo header optDescrs = unlines (header:formatOptions optDescrs)+ -- Mild variant of the standard definition: 'losFmt' is a list rather than a -- comma separated string. fmtOpt :: DarcsOptDescr a -> [(String,[String],String)]@@ -49,22 +73,137 @@    case lines descr of      []     -> [(sosFmt,losFmt,"")]      (d:ds) ->  (sosFmt,losFmt,d) : [ ("",[],d') | d' <- ds ]-   where sepBy _  []     = ""-         sepBy _  [x]    = x-         sepBy ch (x:xs) = x ++ ch:' ':sepBy ch xs-         sosFmt = sepBy ',' (map (fmtShort ad) sos)+   where endBy _  []     = ""+         endBy ch [x]    = x ++ [ch]+         endBy ch (x:xs) = x ++ ch:' ':endBy ch xs+         sosFmt = endBy ',' (map fmtShort sos)          losFmt = map (fmtLong ad) los  -------------------------------------------------------------------------------- -- Verbatim copies: these definitions aren't exported by System.Console.GetOpt -------------------------------------------------------------------------------- -fmtShort :: ArgDescr a -> Char -> String-fmtShort (NoArg  _   ) so = ['-', so]-fmtShort (ReqArg _ ad) so = "-" ++ [so] ++ " " ++ ad-fmtShort (OptArg _ ad) so = "-" ++ [so] ++ "[" ++ ad ++ "]"+fmtShort :: Char -> String+fmtShort so = "-" ++ [so]  fmtLong :: ArgDescr a -> String -> String fmtLong (NoArg  _   ) lo = "--" ++ lo fmtLong (ReqArg _ ad) lo = "--" ++ lo ++ "=" ++ ad fmtLong (OptArg _ ad) lo = "--" ++ lo ++ "[=" ++ ad ++ "]"+--------------------------------------------------------------------------------++usage :: [CommandControl] -> Doc+usage cs = vsep +    [ "Usage: darcs COMMAND ..."+    , "Commands:" $$ usageHelper cs+    , vcat+      [ "Use 'darcs COMMAND --help' for help on a single command."+      , "Use 'darcs --version' to see the darcs version number."+      , "Use 'darcs --exact-version' to see a detailed darcs version."+      , "Use 'darcs help patterns' for help on patch matching."+      , "Use 'darcs help environment' for help on environment variables."+      , "Use 'darcs help manpage' to display help in the manpage format."+      , "Use 'darcs help markdown' to display help in the markdown format."+      ]+    , "Check bug reports at http://bugs.darcs.net/"+    ]++subusage :: DarcsCommand pf -> String+subusage super = renderString $ vsep+    [ header+    , subcommandsHelp+    , vcat $ map text $ formatOptions $ odesc stdCmdActions+    , text $ commandHelp super+    ]+  where+    usageHelp = hsep $ map text+        [ "Usage:"+        , commandProgramName super+        , commandName super+        , "SUBCOMMAND ..."+        ]+    header = usageHelp $$ text (commandDescription super)+    subcommandsHelp = case getSubcommands super of+        [] -> mempty+        subcommands -> usageHelper subcommands++usageHelper :: [CommandControl] -> Doc+usageHelper xs = vsep (groups xs)+  where+    groups [] = []+    groups (HiddenCommand _:cs) = groups cs+    groups (GroupName n:cs) =+      mempty : case groups cs of+        [] -> [text n]+        (g:gs) -> (text n $$ g) : gs+    groups (CommandData c:cs) =+      case groups cs of+        [] -> [cmdHelp c]+        (g:gs) -> (cmdHelp c $$ g) : gs++    cmdHelp c = text $ "  " +++      padSpaces maxwidth (wrappedCommandName c) +++      wrappedCommandDescription c++    padSpaces n s = s ++ replicate (n - length s) ' '++    maxwidth = maximum $ 15 : (map cwidth xs)++    cwidth (CommandData c) = length (wrappedCommandName c) + 2+    cwidth _               = 0++getCommandMiniHelp :: Maybe (DarcsCommand pf1) -> DarcsCommand pf2 -> String+getCommandMiniHelp msuper cmd = renderString $ vsep+    [ getCommandHelpCore msuper cmd+    , hsep $ map text+        [ "See"+        , commandProgramName cmd+        , "help"+        , maybe "" ((++ " ") . commandName) msuper ++ commandName cmd+        , "for details."+        ]+    ]++getCommandHelp :: Maybe (DarcsCommand pf1) -> DarcsCommand pf2 -> Doc+getCommandHelp msuper cmd = vsep+    [ getCommandHelpCore msuper cmd+    , subcommandsHelp+    , withHeading "Options:" basicOptionsHelp+    , withHeading "Advanced options:" advancedOptionsHelp+    , text $ commandHelp cmd+    ]+  where+    withHeading _ [] = mempty+    withHeading h ls = vcat (text h : map text ls)++    (basic, advanced) = commandAlloptions cmd+    -- call formatOptions with combined options so that+    -- both get the same formatting+    (basicOptionsHelp, advancedOptionsHelp) =+        splitAt (length basic) $ formatOptions (basic ++ advanced)++    subcommandsHelp =+      case msuper of+        Nothing ->+          case getSubcommands cmd of+            [] -> mempty+            subcommands -> usageHelper subcommands+        -- we don't want to list subcommands if we're already specifying them+        Just _ -> mempty++getCommandHelpCore :: Maybe (DarcsCommand pf1) -> DarcsCommand pf2 -> Doc+getCommandHelpCore msuper cmd = vcat+    [ hsep $+        [ "Usage:"+        , text $ commandProgramName cmd+        , maybe mempty (text . commandName) msuper+        , text $ commandName cmd+        , "[OPTION]..."+        ]+        ++ args_help+    , text $ commandDescription cmd+    ]+  where+    args_help = case cmd of+                    (DarcsCommand {}) -> map text $ commandExtraArgHelp cmd+                    _ -> []
src/Darcs/Util/AtExit.hs view
@@ -15,8 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- -- | -- Module      : Darcs.Util.AtExit -- Copyright   : 2005 Tomasz Zielonka
− src/Darcs/Util/Bug.hs
@@ -1,30 +0,0 @@--- Reporting bugs in darcs.  See also impossible.h.-module Darcs.Util.Bug-    ( _bug, _bugDoc, _impossible, _fromJust-    ) where--import Prelude ()-import Darcs.Prelude--import Data.Maybe(fromMaybe)-import Darcs.Util.Printer ( Doc, errorDoc, text, ($$) )--type BugStuff = (String, Int, String, String)--_bug :: BugStuff -> String -> a-_bug bs s = _bugDoc bs (text s)--_bugDoc :: BugStuff -> Doc -> a-_bugDoc bs s = errorDoc $-   text ("bug at " ++ _bugLoc bs) $$ s $$-   text ("See http://wiki.darcs.net/BugTracker/Reporting " ++-         "for help on bug reporting.")--_bugLoc :: BugStuff -> String-_bugLoc (file, line, date, time) = file++":"++show line++" compiled "++time++" "++date--_impossible :: BugStuff -> a-_impossible bs = _bug bs $ "Impossible case at "++_bugLoc bs--_fromJust :: BugStuff -> Maybe a -> a-_fromJust bs = fromMaybe (_bug bs $ "fromJust error at " ++ _bugLoc bs)
src/Darcs/Util/ByteString.hs view
@@ -1,5 +1,4 @@-{-# LANGUAGE BangPatterns, ForeignFunctionInterface, CPP, ScopedTypeVariables #-}-+{-# LANGUAGE CPP #-} ----------------------------------------------------------------------------- -- | -- Module      :  Darcs.Util.ByteString@@ -15,119 +14,85 @@ -- GZIp and MMap IO for ByteStrings, encoding utilities, and miscellaneous -- functions for Data.ByteString ----module Darcs.Util.ByteString (--        unsafeWithInternals,-        unpackPSFromUTF8,-        packStringToUTF8,--        -- IO with mmap or gzip-        gzReadFilePS,-        mmapFilePS,-        gzWriteFilePS,-        gzWriteFilePSs,-        gzReadStdin,-        gzWriteHandle,-        FileSegment,-        readSegment,--        -- gzip handling-        isGZFile,-        gzDecompress,--        -- list utilities-        dropSpace,-        breakSpace,-        linesPS,-        unlinesPS,-        hashPS,-        breakFirstPS,-        breakLastPS,-        substrPS,-        readIntPS,-        isFunky,-        fromHex2PS,-        fromPS2Hex,-        betweenLinesPS,-        breakAfterNthNewline,-        breakBeforeNthNewline,-        intercalate,--        -- encoding and unicode utilities-        isAscii,-        decodeLocale,-        encodeLocale,-        decodeString+module Darcs.Util.ByteString+    (+    -- * IO with mmap or gzip+      gzReadFilePS+    , mmapFilePS+    , gzWriteFilePS+    , gzWriteFilePSs+    , gzReadStdin+    , gzWriteHandle+    , FileSegment+    , readSegment+    -- * gzip handling+    , isGZFile+    , gzDecompress+    -- * list utilities+    , dropSpace+    , breakSpace+    , linesPS+    , unlinesPS+    , hashPS+    , breakFirstPS+    , breakLastPS+    , substrPS+    , readIntPS+    , isFunky+    , fromHex2PS+    , fromPS2Hex+    , betweenLinesPS+    , intercalate+    -- * encoding and unicode utilities+    , isAscii+    , decodeLocale+    , encodeLocale+    , unpackPSFromUTF8+    , packStringToUTF8+    -- * properties+    , prop_unlinesPS_linesPS_left_inverse+    , prop_linesPS_length+    , prop_unlinesPS_length+    , propHexConversion+    , spec_betweenLinesPS     ) where  import Prelude () import Darcs.Prelude +import Codec.Binary.Base16 ( b16Enc, b16Dec )+ import qualified Data.ByteString            as B import qualified Data.ByteString.Char8      as BC-import qualified Data.ByteString.Internal   as BI-import qualified Data.ByteString.Lazy.Char8 as BL8+import qualified Data.ByteString.Lazy       as BL import Data.ByteString (intercalate)-import Data.ByteString.Internal (fromForeignPtr) -import Control.Exception ( catch, SomeException ) import System.IO ( withFile, IOMode(ReadMode)                  , hSeek, SeekMode(SeekFromEnd,AbsoluteSeek)                  , openBinaryFile, hClose, Handle, hGetChar                  , stdin)+import System.IO.Error          ( catchIOError ) import System.IO.Unsafe         ( unsafePerformIO ) -import Foreign.Storable         ( peek )-import Foreign.Marshal.Array    ( advancePtr )-import Foreign.C.Types          ( CInt(..) )- import Data.Bits                ( rotateL )-import Data.Char                ( ord, isSpace )+import Data.Char                ( ord, isSpace, toLower, toUpper ) import Data.Word                ( Word8 ) import Data.Int                 ( Int32, Int64 )-import qualified Data.Text as T ( pack, unpack )-import Data.Text.Encoding       ( encodeUtf8, decodeUtf8With )-import Data.Text.Encoding.Error ( lenientDecode )+import Data.List                ( intersperse ) import Control.Monad            ( when )-#if MIN_VERSION_zlib(0,6,0) import Control.Monad.ST.Lazy    ( ST )-#endif -import Foreign.Ptr              ( plusPtr, Ptr )-import Foreign.ForeignPtr       ( withForeignPtr )--#ifdef DEBUG_PS-import Foreign.ForeignPtr       ( addForeignPtrFinalizer )-import Foreign.Ptr              ( FunPtr )-#endif--import qualified Data.ByteString.Lazy as BL import qualified Codec.Compression.GZip as GZ import qualified Codec.Compression.Zlib.Internal as ZI-import Darcs.Util.Encoding ( decode, encode )+import Darcs.Util.Encoding ( decode, encode, decodeUtf8, encodeUtf8 ) import Darcs.Util.Global ( addCRCWarning )  #if mingw32_HOST_OS #else import System.IO.MMap( mmapFileByteString )-import System.Posix.Files( fileSize, getSymbolicLinkStatus ) #endif import System.Mem( performGC )-import qualified Bundled.Posix as Bundled ( getFileStatus, fileSize )---- -------------------------------------------------------------------------------- obsolete debugging code---- -------------------------------------------------------------------------------- unsafeWithInternals---- | Do something with the internals of a PackedString. Beware of--- altering the contents!-unsafeWithInternals :: B.ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a-unsafeWithInternals ps f- = case BI.toForeignPtr ps of-   (fp,s,l) -> withForeignPtr fp $ \p -> f (p `plusPtr` s) l+import System.Posix.Files( fileSize, getSymbolicLinkStatus )  -- | readIntPS skips any whitespace at the beginning of its argument, and -- reads an Int from the beginning of the PackedString.  If there is no@@ -138,33 +103,19 @@ readIntPS :: B.ByteString -> Maybe (Int, B.ByteString) readIntPS = BC.readInt . BC.dropWhile isSpace --- -------------------------------------------------------------------------------- Destructor functions (taking PackedStrings apart)---- | Decodes a 'ByteString' containing UTF-8 to a 'String'. Decoding errors are---   flagged with the U+FFFD character.-unpackPSFromUTF8 :: B.ByteString -> String-unpackPSFromUTF8  = T.unpack . decodeUtf8With lenientDecode--packStringToUTF8 :: String -> B.ByteString-packStringToUTF8 = encodeUtf8 . T.pack- --------------------------------------------------------------------------- A reimplementation of Data.ByteString.Char8.dropSpace, but--- specialised to darcs' need for a 4 way isspace.------ TODO: if it is safe to use the expanded definition of isSpaceWord8--- provided by Data.ByteString.Char8, then all this can go.- -- A locale-independent isspace(3) so patches are interpreted the same everywhere. -- ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\r') isSpaceWord8 :: Word8 -> Bool isSpaceWord8 = (`elem` [0x20, 0x09, 0x0A, 0x0D]) {-# INLINE isSpaceWord8 #-} +-- | Drop leading white space, where white space is defined as+-- consisting of ' ', '\t', '\n', or '\r'. dropSpace :: B.ByteString -> B.ByteString dropSpace bs = B.dropWhile isSpaceWord8 bs +-- | Split at first occurrence of ' ', '\t', '\n', or '\r'. breakSpace :: B.ByteString -> (B.ByteString, B.ByteString) breakSpace bs = B.break isSpaceWord8 bs @@ -172,50 +123,24 @@  {-# INLINE isFunky #-} isFunky :: B.ByteString -> Bool-isFunky ps = case BI.toForeignPtr ps of-   (x,s,l) ->-    unsafePerformIO $ withForeignPtr x $ \p->-    (/=0) `fmap` has_funky_char (p `plusPtr` s) (fromIntegral l)--foreign import ccall unsafe "fpstring.h has_funky_char" has_funky_char-    :: Ptr Word8 -> CInt -> IO CInt+isFunky ps = 0 `B.elem` ps || 26 `B.elem` ps  ------------------------------------------------------------------------ --- ByteString rewrites break (=='x') to breakByte 'x'---  break ((==) x) = breakChar x---  break (==x) = breakChar x-----{--{-# INLINE breakOnPS #-}-breakOnPS :: Char -> B.ByteString -> (B.ByteString, B.ByteString)-breakOnPS c p = case BC.elemIndex c p of-                Nothing -> (p, BC.empty)-                Just n  -> (B.take n p, B.drop n p)--}- {-# INLINE hashPS #-} hashPS :: B.ByteString -> Int32-hashPS ps =-   case BI.toForeignPtr ps of-   (x,s,l) ->-    unsafePerformIO $ withForeignPtr x $ \p->-    hash (p `plusPtr` s) l+hashPS = B.foldl' hashByte 0 -hash :: Ptr Word8 -> Int -> IO Int32-hash = f (0 :: Int32)- where f h _ 0 = return h-       f h p n = do x <- peek p-                    let !h' =  fromIntegral x + rotateL h 8-                    f h' (p `advancePtr` 1) (n-1)+{-# INLINE hashByte #-}+hashByte :: Int32 -> Word8 -> Int32+hashByte h x = fromIntegral x + rotateL h 8  {-# INLINE substrPS #-} substrPS :: B.ByteString -> B.ByteString -> Maybe Int substrPS tok str     | B.null tok = Just 0     | B.length tok > B.length str = Nothing-    | otherwise = do n <- BC.elemIndex (BC.head tok) str+    | otherwise = do n <- B.elemIndex (B.head tok) str                      let ttok = B.tail tok                          reststr = B.drop (n+1) str                      if ttok == B.take (B.length ttok) reststr@@ -238,49 +163,31 @@                   Nothing -> Nothing                   Just n -> Just (B.take n p, B.drop (n+1) p) --- TODO: rename+------------------------------------------------------------------------+-- linesPS and unlinesPS+ {-# INLINE linesPS #-} linesPS :: B.ByteString -> [B.ByteString] linesPS ps      | B.null ps = [B.empty]      | otherwise = BC.split '\n' ps -{- QuickCheck property:--import Test.QuickCheck-import qualified Data.ByteString.Char8 as BC-import Data.Char-instance Arbitrary BC.ByteString where-    arbitrary = fmap BC.pack arbitrary-instance Arbitrary Char where-  arbitrary = chr `fmap` choose (32,127)-deepCheck = check (defaultConfig { configMaxTest = 10000})-testLines =  deepCheck (\x -> (linesPS x == linesPSOld x))-linesPSOld ps = case  BC.elemIndex '\n' ps of-             Nothing -> [ps]-             Just n -> B.take n ps : linesPS (B.drop (n+1) ps) -}--{-| This function acts exactly like the "Prelude" unlines function, or like-"Data.ByteString.Char8" 'unlines', but with one important difference: it will-produce a string which may not end with a newline! That is:+{-# INLINE unlinesPS #-}+unlinesPS :: [B.ByteString] -> B.ByteString+unlinesPS [] = B.empty+unlinesPS x  = B.concat $ intersperse (BC.singleton '\n') x -> unlinesPS ["foo", "bar"]+-- properties of linesPS and unlinesPS -evaluates to \"foo\\nbar\", not \"foo\\nbar\\n\"! This point should hold true for-'linesPS' as well.+prop_unlinesPS_linesPS_left_inverse :: B.ByteString -> Bool+prop_unlinesPS_linesPS_left_inverse x = unlinesPS (linesPS x) == x -TODO: rename this function. -}-unlinesPS :: [B.ByteString] -> B.ByteString-unlinesPS [] = BC.empty-unlinesPS x  = BC.init $ BC.unlines x-{-# INLINE unlinesPS #-}-{- QuickCheck property:+prop_linesPS_length :: B.ByteString -> Bool+prop_linesPS_length x = length (linesPS x) == length (BC.elemIndices '\n' x) + 1 -testUnlines = deepCheck (\x -> (unlinesPS x == unlinesPSOld x))-unlinesPSOld ss = BC.concat $ intersperse_newlines ss-    where intersperse_newlines (a:b:s) = a : newline : intersperse_newlines (b:s)-          intersperse_newlines s = s-          newline = BC.pack "\n" -}+prop_unlinesPS_length :: [B.ByteString] -> Bool+prop_unlinesPS_length xs =+  B.length (unlinesPS xs) == if null xs then 0 else sum (map B.length xs) + length xs - 1  -- ----------------------------------------------------------------------------- -- gzReadFilePS@@ -293,17 +200,12 @@ gzDecompress mbufsize =     -- This is what the code would be without the bad CRC recovery logic:     -- return . BL.toChunks . GZ.decompressWith decompressParams-#if MIN_VERSION_zlib(0,6,0)     decompressWarn (ZI.decompressST ZI.gzipFormat decompressParams)-#else-    toListWarn . ZI.decompressWithErrors ZI.gzipFormat decompressParams-#endif   where         decompressParams = case mbufsize of                               Just bufsize -> GZ.defaultDecompressParams { GZ.decompressBufferSize = bufsize }                               Nothing -> GZ.defaultDecompressParams -#if MIN_VERSION_zlib(0,6,0)         decompressWarn :: (forall s . ZI.DecompressStream (ST s)) -> BL.ByteString -> ([B.ByteString], Bool)         decompressWarn = ZI.foldDecompressStreamWithInput                            (\x ~(xs, b) -> (x:xs, b))@@ -312,37 +214,18 @@                                       else error "trailing data at end of compressed stream"                            )                            handleBad-#else-        toListWarn :: ZI.DecompressStream -> ([B.ByteString], Bool)-        toListWarn = foldDecompressStream (\x ~(xs, b) -> (x:xs, b)) ([], False) handleBad -        -- cut and paste from Zlib since it's not currently exported (interface not yet certain)-        foldDecompressStream :: (B.ByteString -> a -> a) -> a-                             -> (ZI.DecompressError -> String -> a)-                             -> ZI.DecompressStream -> a-        foldDecompressStream chunk end err = fold-                   where-                       fold ZI.StreamEnd               = end-                       fold (ZI.StreamChunk bs stream) = chunk bs (fold stream)-                       fold (ZI.StreamError code msg)  = err code msg-#endif-         -- For a while a bug in darcs caused gzip files with good data but bad CRCs to be         -- produced. Trap bad CRC messages, run the specified action to report that it happened,         -- but continue on the assumption that the data is valid.-#if MIN_VERSION_zlib(0,6,0)         handleBad (ZI.DataFormatError "incorrect data check") = ([], True)         handleBad e = error (show e)-#else-        handleBad ZI.DataError "incorrect data check" = ([], True)-        handleBad _ msg = error msg-#endif  isGZFile :: FilePath -> IO (Maybe Int) isGZFile f = do     h <- openBinaryFile f ReadMode     header <- B.hGet h 2-    if header /= BC.pack "\31\139"+    if header /= B.pack [31,139]        then do hClose h                return Nothing        else do hSeek h SeekFromEnd (-4)@@ -394,7 +277,7 @@     rest   <- B.hGetContents stdin     let allStdin = B.concat [header,rest]     return $-     if header /= BC.pack "\31\139"+     if header /= B.pack [31,139]       then allStdin       else let decompress = fst . gzDecompress Nothing                compressed = BL.fromChunks [allStdin]@@ -409,12 +292,12 @@ readSegment :: FileSegment -> IO BL.ByteString readSegment (f,range) = do     bs <- tryToRead-       `catch` (\(_::SomeException) -> do-                     size <- Bundled.fileSize `fmap` Bundled.getFileStatus f+       `catchIOError` (\_ -> do+                     size <- fileSize `fmap` getSymbolicLinkStatus f                      if size == 0-                        then return BC.empty+                        then return B.empty                         else performGC >> tryToRead)-    return $ BL8.fromChunks [bs]+    return $ BL.fromChunks [bs]   where     tryToRead =         case range of@@ -435,8 +318,7 @@ -- be written to swap.  If you read many small files, mmapFilePS will be -- less memory-efficient than readFilePS, since each mmapFilePS takes up a -- separate page of memory.  Also, you can run into bus errors if the file--- is modified.  NOTE: as with 'readFilePS', the string representation in--- the file is assumed to be ISO-8859-1.+-- is modified.  mmapFilePS :: FilePath -> IO B.ByteString #if mingw32_HOST_OS@@ -444,7 +326,7 @@ #else mmapFilePS f =   mmapFileByteString f Nothing-   `catch` (\(_ :: SomeException) -> do+   `catchIOError` (\_ -> do                      size <- fileSize `fmap` getSymbolicLinkStatus f                      if size == 0                         then return B.empty@@ -454,97 +336,85 @@ -- ------------------------------------------------------------------------- -- fromPS2Hex -foreign import ccall unsafe "static fpstring.h conv_to_hex" conv_to_hex-    :: Ptr Word8 -> Ptr Word8 -> CInt -> IO ()- fromPS2Hex :: B.ByteString -> B.ByteString-fromPS2Hex ps = case BI.toForeignPtr ps of-          (x,s,l) ->-           BI.unsafeCreate (2*l) $ \p -> withForeignPtr x $ \f ->-           conv_to_hex p (f `plusPtr` s) $ fromIntegral l+fromPS2Hex = BC.map toLower . b16Enc  -- ------------------------------------------------------------------------- -- fromHex2PS -foreign import ccall unsafe "static fpstring.h conv_from_hex" conv_from_hex-    :: Ptr Word8 -> Ptr Word8 -> CInt -> IO ()- fromHex2PS :: B.ByteString -> B.ByteString-fromHex2PS ps = case BI.toForeignPtr ps of-          (x,s,l) ->-           BI.unsafeCreate (l `div` 2) $ \p -> withForeignPtr x $ \f ->-           conv_from_hex p (f `plusPtr` s) (fromIntegral $ l `div` 2)+fromHex2PS s =+  case b16Dec $ BC.map toUpper s of+    Right (result, remaining)+      | B.null remaining -> result+    _ -> error "fromHex2PS: input is not hex encoded" +propHexConversion :: B.ByteString -> Bool+propHexConversion x = fromHex2PS (fromPS2Hex x) == x+ -- ------------------------------------------------------------------------- -- betweenLinesPS --- | betweenLinesPS returns the B.ByteString between the two lines given,+-- | Return the B.ByteString between the two lines given, -- or Nothing if they do not appear.- betweenLinesPS :: B.ByteString -> B.ByteString -> B.ByteString                -> Maybe B.ByteString-betweenLinesPS start end ps- = case break (start ==) (linesPS ps) of-       (_, _:rest@(bs1:_)) ->-           case BI.toForeignPtr bs1 of-            (ps1,s1,_) ->-             case break (end ==) rest of-               (_, bs2:_) -> case BI.toForeignPtr bs2 of (_,s2,_) -> Just $ fromForeignPtr ps1 s1 (s2 - s1)-               _ -> Nothing-       _ -> Nothing---- ---------------------------------------------------------------------------- breakAfterNthNewline--breakAfterNthNewline :: Int -> B.ByteString-                        -> Maybe (B.ByteString, B.ByteString)-breakAfterNthNewline 0 the_ps | B.null the_ps = Just (B.empty, B.empty)-                              | otherwise     = Just (B.empty, the_ps)-breakAfterNthNewline n the_ps =-  go n (B.elemIndices (BI.c2w '\n') the_ps)-  where  go 0 []      = Just (the_ps, B.empty)-         go _ []      = Nothing-         go 1 (i:_)   = Just $ B.splitAt (i+1) the_ps-         go !m (_:is) = go (m-1) is---- ---------------------------------------------------------------------------- breakBeforeNthNewline+betweenLinesPS start end ps =+  case B.breakSubstring start_line ps of+    (before_start, at_start)+      | not (B.null at_start)+      , B.null before_start || BC.last before_start == '\n' ->+          case B.breakSubstring end_line (B.drop (B.length start_line) at_start) of+            (before_end, at_end)+              | not (B.null at_end)+              , B.null before_end || BC.last before_end == '\n' -> Just before_end+              | otherwise -> Nothing+      | otherwise -> Nothing+  where+    start_line = BC.snoc start '\n'+    end_line = BC.snoc end '\n' -breakBeforeNthNewline :: Int -> B.ByteString -> (B.ByteString, B.ByteString)-breakBeforeNthNewline 0 the_ps- | B.null the_ps = (B.empty, B.empty)-breakBeforeNthNewline n the_ps =-  go n (B.elemIndices (BI.c2w '\n') the_ps)-  where  go _ []      = (the_ps, B.empty)-         go 0 (i:_)   = B.splitAt i the_ps-         go !m (_:is) = go (m-1) is+-- | Simpler but less efficient variant of 'betweenLinesPS'.+spec_betweenLinesPS :: B.ByteString -> B.ByteString -> B.ByteString+                    -> Maybe B.ByteString+spec_betweenLinesPS start end ps =+  case break (start ==) (linesPS ps) of+    (_, _:after_start) ->+      case break (end ==) after_start of+        (before_end, _:_) ->+          Just $ BC.unlines before_end+        _ -> Nothing+    _ -> Nothing  -- | Test if a ByteString is made of ascii characters isAscii :: B.ByteString -> Bool isAscii = B.all (< 128) --- | Decode a ByteString to a String according to the current locale--- unsafePerformIO in the locale function is ratified by the fact that GHC 6.12--- and above also supply locale conversion with functions with a pure type.--- Unrecognized byte sequences in the input are skipped.+-- * Encoding functions++-- Use of 'unsafePerformIO' is ratified by the fact that these+-- really are pure functions.++-- | Decode a 'ByteString' containing UTF-8 to a 'String'. Decoding errors+-- are flagged with the U+FFFD character.+unpackPSFromUTF8 :: B.ByteString -> String+unpackPSFromUTF8  = unsafePerformIO . decodeUtf8++-- | Encode a 'String' to a 'ByteString' using UTF-8.+packStringToUTF8 :: String -> B.ByteString+packStringToUTF8 = unsafePerformIO . encodeUtf8++-- | Decode a 'ByteString' to a 'String' according to the current locale,+-- using lone surrogates for un-decodable bytes. decodeLocale :: B.ByteString -> String decodeLocale = unsafePerformIO . decode --- | Encode a String to a ByteString with char8 encoding (i.e., the values of the--- characters become the values of the bytes; if a character value is greater--- than 255, its byte becomes the character value modulo 256)-encodeChar8 :: String -> B.ByteString-encodeChar8 = B.pack . map (fromIntegral . ord)---- | Encode a String to a ByteString according to the current locale+-- | Encode a 'String' to a 'ByteString' according to the current locale,+-- converting lone surrogates back to the original byte. If that+-- fails (because the locale does not support the full unicode range)+-- then encode using utf-8, assuming that the un-ecodable characters+-- come from patch meta data.+--+-- See also 'Darcs.UI.Commands.setEnvCautiously'. encodeLocale :: String -> B.ByteString-encodeLocale = unsafePerformIO . encode---- | Take a 'String' that represents byte values and re-decode it acording to--- the current locale.--- Note: we globally enforce char8 as the default encoding, see "Main" and--- "Darcs.Utils". This means we get command line args and environment variables--- as 'String's with char8 encoding, too. So we need this to convert such--- strings back to the user's encoding.-decodeString :: String -> IO String-decodeString = decode . encodeChar8+encodeLocale s = unsafePerformIO $ encode s `catchIOError` (\_ -> encodeUtf8 s)
src/Darcs/Util/CommandLine.hs view
@@ -28,28 +28,7 @@ -- the commandline can end with "%<" specifying that the command -- expects input on stdin. ----- Some tests for the parser.------ > formatTable = [('s',"<insert subject here>"),--- >                ('a',"<insert author here>")]--- >--- > testParser :: (Show a, Eq a) => Parser a -> String -> a -> a--- > testParser p s ok = case parse p "" s of--- >                     Left e -> error $ "Parser failed with: " ++ (show e)--- >                     Right res -> if res == ok--- >                                  then res--- >                                  else error $ "Parser failed: got "--- >                                         ++ (show res) ++ ", expected "--- >                                         ++ (show ok)--- >--- > testCases = [("a b",(["a","b"], False)),--- >              ("a b %<",(["a","b"], True)),--- >              ("a b %< ",(["a","b"], True)),--- >              ("\"arg0 contains spaces \\\"quotes\\\"\" b",--- >               (["arg0 contains spaces \"quotes\"","b"],False)),--- >              ("a %s %<",(["a","<insert subject here>"], True))]--- >--- > runTests = map (uncurry $ testParser (commandline formatTable)) testCases+-- See Darcs.Test.Misc.CommandLine for tests.  module Darcs.Util.CommandLine     ( parseCmd
− src/Darcs/Util/Crypt/SHA1.hs
@@ -1,225 +0,0 @@--- Copyright (C) 2001, 2004 Ian Lynagh <igloo@earth.li>------ 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.---- name shadowing disabled because a,b,c,d,e are shadowed loads in step 4-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}--{-# LANGUAGE CPP #-}---- |--- Module      : Darcs.Util.Crypt.SHA1--- Copyright   : 2001, 2004 Ian Lynagh <igloo@earth.li>--- License     : GPL--- Maintainer  : darcs-devel@darcs.net--- Stability   : experimental--- Portability : portable--module Darcs.Util.Crypt.SHA1 ( sha1PS, SHA1(..), showAsHex, sha1Xor, zero ) where--import Prelude ()-import Darcs.Prelude--import Darcs.Util.ByteString (unsafeWithInternals)-import qualified Data.ByteString as B (ByteString, pack, length, concat)-import Data.Binary ( Binary(..) )-import Data.Char (intToDigit)-import Data.Bits (xor, (.&.), (.|.), complement, rotateL, shiftL, shiftR)-import Data.Word (Word8, Word32)-import Foreign.Ptr (Ptr, castPtr)-import Foreign.Marshal.Array (advancePtr)-import Foreign.Storable (peek, poke)-import System.IO.Unsafe (unsafePerformIO)--data SHA1 = SHA1 !Word32 !Word32 !Word32 !Word32 !Word32-  deriving (Eq,Ord)-data XYZ = XYZ !Word32 !Word32 !Word32--instance Show SHA1 where- show (SHA1 a b c d e) = concatMap showAsHex [a, b, c, d, e]--instance Binary SHA1 where-  put (SHA1 a b c d e) = put a >> put b >> put c >> put d >> put e-  get = do a <- get ; b <- get ; c <- get ; d <- get ; e <- get ; return (SHA1 a b c d e)--sha1Xor :: SHA1 -> SHA1 -> SHA1-sha1Xor (SHA1 a1 b1 c1 d1 e1) (SHA1 a2 b2 c2 d2 e2) =- SHA1 (a1 `xor` a2) (b1 `xor` b2) (c1 `xor` c2) (d1 `xor` d2) (e1 `xor` e2)--zero :: SHA1-zero = SHA1 0 0 0 0 0--sha1PS:: B.ByteString -> SHA1-sha1PS s = abcde'- where s1_2 = sha1Step12PadLength s-       abcde = sha1Step3Init-       abcde' = unsafePerformIO-              $ unsafeWithInternals s1_2 (\ptr len ->-                    do let ptr' = castPtr ptr-#ifndef BIGENDIAN-                       fiddleEndianness ptr' len-#endif-                       sha1Step4Main abcde ptr' len)--fiddleEndianness :: Ptr Word32 -> Int -> IO ()-fiddleEndianness p 0 = p `seq` return ()-fiddleEndianness p n- = do x <- peek p-      poke p $ shiftL x 24-           .|. shiftL (x .&. 0xff00) 8-           .|. (shiftR x 8 .&. 0xff00)-           .|. shiftR x 24-      fiddleEndianness (p `advancePtr` 1) (n - 4)---- sha1Step12PadLength assumes the length is at most 2^61.--- This seems reasonable as the Int used to represent it is normally 32bit,--- but obviously could go wrong with large inputs on 64bit machines.--- The B.ByteString library should probably move to Word64s if this is an--- issue, though.--sha1Step12PadLength :: B.ByteString -> B.ByteString-sha1Step12PadLength s- = let len = B.length s-       num_nuls = (55 - len) `mod` 64-       padding = 128:replicate num_nuls 0-       len_w8s = reverse $ sizeSplit 8 (fromIntegral len*8)-   in B.concat [s, B.pack padding, B.pack len_w8s]--sizeSplit :: Int -> Integer -> [Word8]-sizeSplit 0 _ = []-sizeSplit p n = fromIntegral d:sizeSplit (p-1) n'- where (n', d) = divMod n 256--sha1Step3Init :: SHA1-sha1Step3Init = SHA1 0x67452301 0xefcdab89 0x98badcfe 0x10325476 0xc3d2e1f0--sha1Step4Main :: SHA1 -> Ptr Word32 -> Int -> IO SHA1-sha1Step4Main abcde _ 0 = return $! abcde-sha1Step4Main (SHA1 a0@a b0@b c0@c d0@d e0@e) s len-    = do-         (e, b) <- doit f1 0x5a827999 (x 0) a b c d e-         (d, a) <- doit f1 0x5a827999 (x 1) e a b c d-         (c, e) <- doit f1 0x5a827999 (x 2) d e a b c-         (b, d) <- doit f1 0x5a827999 (x 3) c d e a b-         (a, c) <- doit f1 0x5a827999 (x 4) b c d e a-         (e, b) <- doit f1 0x5a827999 (x 5) a b c d e-         (d, a) <- doit f1 0x5a827999 (x 6) e a b c d-         (c, e) <- doit f1 0x5a827999 (x 7) d e a b c-         (b, d) <- doit f1 0x5a827999 (x 8) c d e a b-         (a, c) <- doit f1 0x5a827999 (x 9) b c d e a-         (e, b) <- doit f1 0x5a827999 (x 10) a b c d e-         (d, a) <- doit f1 0x5a827999 (x 11) e a b c d-         (c, e) <- doit f1 0x5a827999 (x 12) d e a b c-         (b, d) <- doit f1 0x5a827999 (x 13) c d e a b-         (a, c) <- doit f1 0x5a827999 (x 14) b c d e a-         (e, b) <- doit f1 0x5a827999 (x 15) a b c d e-         (d, a) <- doit f1 0x5a827999 (m 16) e a b c d-         (c, e) <- doit f1 0x5a827999 (m 17) d e a b c-         (b, d) <- doit f1 0x5a827999 (m 18) c d e a b-         (a, c) <- doit f1 0x5a827999 (m 19) b c d e a-         (e, b) <- doit f2 0x6ed9eba1 (m 20) a b c d e-         (d, a) <- doit f2 0x6ed9eba1 (m 21) e a b c d-         (c, e) <- doit f2 0x6ed9eba1 (m 22) d e a b c-         (b, d) <- doit f2 0x6ed9eba1 (m 23) c d e a b-         (a, c) <- doit f2 0x6ed9eba1 (m 24) b c d e a-         (e, b) <- doit f2 0x6ed9eba1 (m 25) a b c d e-         (d, a) <- doit f2 0x6ed9eba1 (m 26) e a b c d-         (c, e) <- doit f2 0x6ed9eba1 (m 27) d e a b c-         (b, d) <- doit f2 0x6ed9eba1 (m 28) c d e a b-         (a, c) <- doit f2 0x6ed9eba1 (m 29) b c d e a-         (e, b) <- doit f2 0x6ed9eba1 (m 30) a b c d e-         (d, a) <- doit f2 0x6ed9eba1 (m 31) e a b c d-         (c, e) <- doit f2 0x6ed9eba1 (m 32) d e a b c-         (b, d) <- doit f2 0x6ed9eba1 (m 33) c d e a b-         (a, c) <- doit f2 0x6ed9eba1 (m 34) b c d e a-         (e, b) <- doit f2 0x6ed9eba1 (m 35) a b c d e-         (d, a) <- doit f2 0x6ed9eba1 (m 36) e a b c d-         (c, e) <- doit f2 0x6ed9eba1 (m 37) d e a b c-         (b, d) <- doit f2 0x6ed9eba1 (m 38) c d e a b-         (a, c) <- doit f2 0x6ed9eba1 (m 39) b c d e a-         (e, b) <- doit f3 0x8f1bbcdc (m 40) a b c d e-         (d, a) <- doit f3 0x8f1bbcdc (m 41) e a b c d-         (c, e) <- doit f3 0x8f1bbcdc (m 42) d e a b c-         (b, d) <- doit f3 0x8f1bbcdc (m 43) c d e a b-         (a, c) <- doit f3 0x8f1bbcdc (m 44) b c d e a-         (e, b) <- doit f3 0x8f1bbcdc (m 45) a b c d e-         (d, a) <- doit f3 0x8f1bbcdc (m 46) e a b c d-         (c, e) <- doit f3 0x8f1bbcdc (m 47) d e a b c-         (b, d) <- doit f3 0x8f1bbcdc (m 48) c d e a b-         (a, c) <- doit f3 0x8f1bbcdc (m 49) b c d e a-         (e, b) <- doit f3 0x8f1bbcdc (m 50) a b c d e-         (d, a) <- doit f3 0x8f1bbcdc (m 51) e a b c d-         (c, e) <- doit f3 0x8f1bbcdc (m 52) d e a b c-         (b, d) <- doit f3 0x8f1bbcdc (m 53) c d e a b-         (a, c) <- doit f3 0x8f1bbcdc (m 54) b c d e a-         (e, b) <- doit f3 0x8f1bbcdc (m 55) a b c d e-         (d, a) <- doit f3 0x8f1bbcdc (m 56) e a b c d-         (c, e) <- doit f3 0x8f1bbcdc (m 57) d e a b c-         (b, d) <- doit f3 0x8f1bbcdc (m 58) c d e a b-         (a, c) <- doit f3 0x8f1bbcdc (m 59) b c d e a-         (e, b) <- doit f2 0xca62c1d6 (m 60) a b c d e-         (d, a) <- doit f2 0xca62c1d6 (m 61) e a b c d-         (c, e) <- doit f2 0xca62c1d6 (m 62) d e a b c-         (b, d) <- doit f2 0xca62c1d6 (m 63) c d e a b-         (a, c) <- doit f2 0xca62c1d6 (m 64) b c d e a-         (e, b) <- doit f2 0xca62c1d6 (m 65) a b c d e-         (d, a) <- doit f2 0xca62c1d6 (m 66) e a b c d-         (c, e) <- doit f2 0xca62c1d6 (m 67) d e a b c-         (b, d) <- doit f2 0xca62c1d6 (m 68) c d e a b-         (a, c) <- doit f2 0xca62c1d6 (m 69) b c d e a-         (e, b) <- doit f2 0xca62c1d6 (m 70) a b c d e-         (d, a) <- doit f2 0xca62c1d6 (m 71) e a b c d-         (c, e) <- doit f2 0xca62c1d6 (m 72) d e a b c-         (b, d) <- doit f2 0xca62c1d6 (m 73) c d e a b-         (a, c) <- doit f2 0xca62c1d6 (m 74) b c d e a-         (e, b) <- doit f2 0xca62c1d6 (m 75) a b c d e-         (d, a) <- doit f2 0xca62c1d6 (m 76) e a b c d-         (c, e) <- doit f2 0xca62c1d6 (m 77) d e a b c-         (b, d) <- doit f2 0xca62c1d6 (m 78) c d e a b-         (a, c) <- doit f2 0xca62c1d6 (m 79) b c d e a-         let abcde' = SHA1 (a0 + a) (b0 + b) (c0 + c) (d0 + d) (e0 + e)-         sha1Step4Main abcde' (s `advancePtr` 16) (len - 64)- where {-# INLINE f1 #-}-       f1 (XYZ x y z) = (x .&. y) .|. (complement x .&. z)-       {-# INLINE f2 #-}-       f2 (XYZ x y z) = x `xor` y `xor` z-       {-# INLINE f3 #-}-       f3 (XYZ x y z) = (x .&. y) .|. (x .&. z) .|. (y .&. z)-       {-# INLINE x #-}-       x n = peek (s `advancePtr` n)-       {-# INLINE m #-}-       m n = do let base = s `advancePtr` (n .&. 15)-                x0 <- peek base-                x1 <- peek (s `advancePtr` ((n - 14) .&. 15))-                x2 <- peek (s `advancePtr` ((n - 8) .&. 15))-                x3 <- peek (s `advancePtr` ((n - 3) .&. 15))-                let res = rotateL (x0 `xor` x1 `xor` x2 `xor` x3) 1-                poke base res-                return res-       {-# INLINE doit #-}-       doit f k i a b c d e = a `seq` c `seq`-           do i' <- i-              return (rotateL a 5 + f (XYZ b c d) + e + i' + k,-                      rotateL b 30)--showAsHex :: Word32 -> String-showAsHex n = showIt 8 n ""-   where-    showIt :: Int -> Word32 -> String -> String-    showIt 0 _ r = r-    showIt i x r = case quotRem x 16 of-                       (y, z) -> let c = intToDigit (fromIntegral z)-                                 in c `seq` showIt (i-1) y (c:r)
− src/Darcs/Util/Crypt/SHA256.hs
@@ -1,12 +0,0 @@-module Darcs.Util.Crypt.SHA256 ( sha256sum ) where--import Prelude ()-import Darcs.Prelude--import Crypto.Hash.SHA256 ( hash )-import Data.ByteString ( ByteString )-import Data.ByteString.Base16 ( encode )-import Data.ByteString.Char8 ( unpack )--sha256sum :: ByteString -> String-sha256sum = unpack . encode . hash
src/Darcs/Util/DateMatcher.hs view
@@ -31,6 +31,9 @@     -- for debugging only     , DateMatcher(..)     , getMatchers+    -- for testing (GHCi, etc)+    , testDate+    , testDateAt     ) where  import Prelude ()@@ -47,7 +50,7 @@     ( parseDate, englishDateTime, englishInterval, englishLast     , iso8601Interval, resetCalendar, subtractFromMCal, getLocalTz     , MCalendarTime(..), toMCalendarTime, unsafeToCalendarTime-    , unsetTime+    , unsetTime, readUTCDate     )  -- | 'withinDay' @x y@ is true if @x <= y < (x + one_day)@@@ -179,6 +182,12 @@     tillEof p = do { x <- p; eof; return x }     parseDateWith p = parse (tillEof p) "" d ++--- The following functions are for toying around in GHCi+---+--- > testDate   "2008/05/22 10:34"+--- > testDateAt "2006-03-22 09:36" "2008/05/22 10:34"+ -- | 'tryMatchers' @ms@ returns the first successful match in @ms@ --   It is an error if there are no matches tryMatchers :: [DateMatcher] -> CalendarTime -> Bool@@ -190,3 +199,32 @@  now :: IO CalendarTime now = getClockTime >>= toCalendarTime++-- | 'testDate' @d@ shows the possible interpretations+--   for the date string @d@ and how they match against+--   the current date+testDate :: String -> IO ()+testDate d = do cnow <- now+                testDateAtCal cnow d++-- | 'testDate' @iso d@ shows the possible interpretations+--   for the date string @d@ and how they match against+--   the date represented by the ISO 8601 string @iso@+testDateAt :: String -> String -> IO ()+testDateAt iso = testDateAtCal (readUTCDate iso)++-- | helper function for 'testDate' and 'testDateAt'+testDateAtCal :: CalendarTime -> String -> IO ()+testDateAtCal c d =+ do ms <- getMatchers d+    putStr . unlines . map (showMatcher c) $ ms++-- | 'showMatcher' @c dm@ tells us if @dm@ applies to+--   'CalendarTime' @c@; or if @dm@ just represents the+--   failure to parse a date, in which case @c@ is moot.+showMatcher :: CalendarTime -> DateMatcher -> String+showMatcher cnow (DM n p m) =+   "==== " ++ n ++ " ====\n" +++   (case p of+     Left err -> shows err ""+     Right x  -> show x ++ "\n" ++ show (m x cnow))
src/Darcs/Util/DateTime.hs view
@@ -2,7 +2,6 @@ -- --  BSD3 -{-# LANGUAGE CPP #-} module Darcs.Util.DateTime     ( getCurrentTime, toSeconds     , formatDateTime, fromClockTime, parseDateTime, startOfTime
src/Darcs/Util/Diff/Myers.hs view
@@ -16,8 +16,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- -- | -- Module      : Darcs.Util.Diff.Myers -- Copyright   : 2003 David Roundy@@ -72,8 +70,6 @@ import Data.Array.Base import Data.Array.Unboxed import qualified Data.Map as Map ( lookup, empty, insertWith )--#include "impossible.h"  -- | create a list of changes between a and b, each change has the form --   (starta, lima, startb, limb) which means that a[starta, lima)
src/Darcs/Util/Diff/Patience.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE CPP #-}- --  Copyright (C) 2002,2008-2009 David Roundy -- --  This program is free software; you can redistribute it and/or modify@@ -34,8 +32,6 @@     ( Map, lookup, insertWith, empty, elems ) import qualified Data.Hashable as H ( hash ) import Darcs.Util.Diff.Myers (initP, aLen, PArray, getSlice)--#include "impossible.h"  empty :: HunkMap empty = HunkMapInfo 0 M.empty
src/Darcs/Util/Download.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS_GHC -fno-warn-deprecations #-} -- using isEmptyChan {-# LANGUAGE CPP #-}  -- |@@ -27,12 +26,13 @@  import Control.Arrow ( (&&&) ) import Control.Concurrent ( forkIO )-import Control.Concurrent.Chan ( isEmptyChan, newChan, readChan, writeChan,-                                 Chan )+import Control.Concurrent.STM.TChan+  ( isEmptyTChan, newTChanIO, readTChan, writeTChan, TChan ) import Control.Concurrent.MVar ( isEmptyMVar, modifyMVar_, modifyMVar, newEmptyMVar,                                  newMVar, putMVar, readMVar, withMVar, MVar ) import Control.Monad ( unless, when ) import Control.Monad.State ( evalStateT, get, modify, put, StateT )+import Control.Monad.STM ( atomically ) import Control.Monad.Trans ( liftIO ) import Data.IORef ( newIORef, readIORef, writeIORef, IORef ) import Data.Map ( Map )@@ -55,8 +55,6 @@ import qualified Darcs.Util.Download.HTTP as HTTP #endif -#include "impossible.h"- {-# NOINLINE maxPipelineLengthRef #-} maxPipelineLengthRef :: IORef Int maxPipelineLengthRef = unsafePerformIO $ do@@ -76,15 +74,15 @@ urlNotifications = unsafePerformIO $ newMVar Map.empty  {-# NOINLINE urlChan #-}-urlChan :: Chan UrlRequest+urlChan :: TChan UrlRequest urlChan = unsafePerformIO $ do-    ch <- newChan+    ch <- newTChanIO     _ <- forkIO (urlThread ch)     return ch  type UrlM a = StateT UrlState IO a -urlThread :: Chan UrlRequest -> IO ()+urlThread :: TChan UrlRequest -> IO () urlThread ch = do     junk <- flip showHex "" `fmap` randomRIO rrange     evalStateT urlThread' (UrlState Map.empty emptyQ 0 junk)@@ -93,7 +91,7 @@      urlThread' :: UrlM ()     urlThread' = do-        empty <- liftIO $ isEmptyChan ch+        empty <- liftIO $ atomically $ isEmptyTChan ch         (l, w) <- (pipeLength &&& waitToStart) `fmap` get         -- If we've got UrlRequests waiting on the chan, or there's nothing         -- waiting to start and nothing already downloading, we just block@@ -108,10 +106,10 @@      readAllRequests :: IO [UrlRequest]     readAllRequests = do-        r <- readChan ch+        r <- atomically $ readTChan ch         debugMessage $ "URL.urlThread (" ++ url r ++ "\n"++                        "-> " ++ file r ++ ")"-        empty <- isEmptyChan ch+        empty <- atomically $ isEmptyTChan ch         reqs <- if not empty                 then readAllRequests                 else return []@@ -205,7 +203,7 @@     v <- newEmptyMVar     old_mv <- modifyMVar urlNotifications (return . swap . Map.insertLookupWithKey (\_k _n old -> old) u v)     case old_mv of-        Nothing -> writeChan urlChan $ UrlRequest u f c p -- ok, new URL+        Nothing -> atomically $ writeTChan urlChan $ UrlRequest u f c p -- ok, new URL         Just _  -> debugMessage $ "URL.copyUrlWithPriority already in progress, skip (" ++ u ++ "\n" ++ "-> " ++ f ++ ")"  createDownloadFileName :: FilePath -> UrlState -> FilePath
src/Darcs/Util/Encoding.hs view
@@ -23,27 +23,47 @@ -- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. {-# LANGUAGE CPP #-} module Darcs.Util.Encoding-    ( encode,decode+    ( encode, decode+    , encodeUtf8, decodeUtf8     ) where  import Prelude () import Darcs.Prelude -import Data.ByteString ( ByteString )+import qualified Data.ByteString as B+import GHC.IO.Encoding ( TextEncoding, mkTextEncoding )+import GHC.Foreign ( withCStringLen, peekCStringLen )  #ifdef WIN32-import qualified Darcs.Util.Encoding.Win32 as Backend ( encode, decode )+import Darcs.Util.Encoding.Win32 ( encode, decode ) #else-import qualified Darcs.Util.Encoding.IConv as Backend ( encode, decode )++import GHC.IO.Encoding ( getFileSystemEncoding )++-- | Encode a 'String' into a 'B.ByteString' according to the user's locale+-- with the ghc specific //ROUNDTRIP feature added. This means the argument+-- is allowed to contain non-Unicode 'Char's as produced by 'decode'.+encode :: String -> IO B.ByteString+encode s = getFileSystemEncoding >>= textEncode s++-- | Decode a 'B.ByteString' into a 'String' according to the user's locale+-- with the ghc specific //ROUNDTRIP feature added. This means the result+-- may contain 'Char's that are not valid Unicode in case decoding with the+-- user's locale fails.+decode :: B.ByteString -> IO String+decode bs = getFileSystemEncoding >>= textDecode bs+ #endif --- functions redefined to add haddock (there might well be a better way!)+encodeUtf8 :: String -> IO B.ByteString+encodeUtf8 s = mkTextEncoding "UTF-8//TRANSLIT" >>= textEncode s --- | Encode a Unicode 'String' into a 'ByteString' suitable for the current--- console.-encode :: String -> IO ByteString-encode = Backend.encode+decodeUtf8 :: B.ByteString -> IO String+decodeUtf8 bs = mkTextEncoding "UTF-8//TRANSLIT" >>= textDecode bs --- | Convert a 'ByteString' from the console's encoding into a Unicode 'String'.-decode :: ByteString -> IO String-decode = Backend.decode+textEncode :: String -> TextEncoding -> IO B.ByteString+textEncode s enc = withCStringLen enc s B.packCStringLen++textDecode :: B.ByteString -> TextEncoding -> IO String+textDecode bs enc = B.useAsCStringLen bs (peekCStringLen enc)+
− src/Darcs/Util/Encoding/IConv.hsc
@@ -1,185 +0,0 @@--- Copyright 2007-2009, Judah Jacobson.--- All Rights Reserved.---- Redistribution and use in source and binary forms, with or without--- modification, are permitted provided that the following conditions are met:---- - Redistribution of source code must retain the above copyright notice,--- this list of conditions and the following disclaimer.---- - Redistribution in binary form must reproduce the above copyright notice,--- this list of conditions and the following disclaimer in the documentation--- and/or other materials provided with the distribution.---- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY--- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED--- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE--- DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR THE CONTRIBUTORS BE LIABLE--- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL--- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR--- SERVICES; LOSS OF USE, DATA OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER--- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,--- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE--- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.-{-# LANGUAGE ForeignFunctionInterface #-}-module Darcs.Util.Encoding.IConv-    ( encode, decode-    ) where--import Foreign.C-    ( CString, CSize(..), CInt(..)-    , peekCAString, withCAString-    , Errno(..), getErrno, throwErrno, eINVAL, e2BIG-    )-import Foreign-    ( Ptr, castPtr, nullPtr, plusPtr-    , peek, maybePeek-    , with, maybeWith-    , ForeignPtr, withForeignPtr, newForeignPtr-    , FunPtr-    , #type nl_item-    , Word8-    )-import Control.Exception ( bracket )-import Data.ByteString ( ByteString, useAsCStringLen, append )-import Data.ByteString.Internal ( createAndTrim' )-import qualified Data.ByteString as B-import qualified Data.ByteString.UTF8 as UTF8-import Data.Maybe ( fromMaybe )--#include <locale.h>-#include <langinfo.h>-#include "h_iconv.h"--getLocaleCodeset :: IO String-getLocaleCodeset = bracket (setLocale (Just "")) setLocale (const getCodeset)--encode :: String -> IO ByteString-encode str = getLocaleCodeset >>= \codeset -> openEncoder codeset >>= ($ str)--decode :: ByteString -> IO String-decode str = getLocaleCodeset >>= \codeset -> openDecoder codeset >>= ($ str)--openEncoder :: String -> IO (String -> IO ByteString)-openEncoder codeset = do-    encodeT <- iconvOpen codeset "UTF-8"-    return $ simpleIConv dropUTF8Char encodeT . UTF8.fromString--openDecoder :: String -> IO (ByteString -> IO String)-openDecoder codeset = do-    decodeT <- iconvOpen "UTF-8" codeset-    return $ fmap UTF8.toString . simpleIConv (B.drop 1) decodeT--dropUTF8Char :: ByteString -> ByteString-dropUTF8Char = fromMaybe B.empty . fmap snd . UTF8.uncons--replacement :: Word8-replacement = toEnum (fromEnum '?')---- handle errors by dropping unuseable chars.-simpleIConv :: (ByteString -> ByteString) -> IConvT -> ByteString -> IO ByteString-simpleIConv dropper t bs = do-    (cs,result) <- iconv t bs-    case result of-        Invalid rest    -> continueOnError cs rest-        Incomplete rest -> continueOnError cs rest-        _               -> return cs-  where-    continueOnError cs rest = fmap ((cs `append`) . (replacement `B.cons`))-                                $ simpleIConv dropper t (dropper rest)-------------------------- Setting the locale--foreign import ccall "setlocale" c_setlocale :: CInt -> CString -> IO CString--setLocale :: Maybe String -> IO (Maybe String)-setLocale oldLocale = (maybeWith withCAString) oldLocale $ \loc_p -> do-    c_setlocale (#const LC_CTYPE) loc_p >>= maybePeek peekCAString---------------------- Getting the encoding--type NLItem = #type nl_item--foreign import ccall nl_langinfo :: NLItem -> IO CString--getCodeset :: IO String-getCodeset = do-    str <- nl_langinfo (#const CODESET) >>= peekCAString-    -- check for codesets which may be returned by Solaris, but not understood-    -- by GNU iconv.-    if str `elem` ["","646"]-        then return "ISO-8859-1"-        else return str--------------------- Iconv---- TODO: This may not work on platforms where iconv_t is not a pointer.-type IConvT = ForeignPtr ()-type IConvTPtr = Ptr ()--foreign import ccall "darcs_iconv_open" iconv_open-    :: CString -> CString -> IO IConvTPtr--iconvOpen :: String -> String -> IO IConvT-iconvOpen destName srcName = withCAString destName $ \dest ->-                            withCAString srcName $ \src -> do-                                res <- iconv_open dest src-                                if res == nullPtr `plusPtr` (-1)-                                    then throwErrno $ "iconvOpen "-                                            ++ show (srcName,destName)-                                    -- list the two it couldn't convert between?-                                    else newForeignPtr iconv_close res---- really this returns a CInt, but it's easiest to just ignore that, I think.-foreign import ccall "& darcs_iconv_close" iconv_close :: FunPtr (IConvTPtr -> IO ())--foreign import ccall "darcs_iconv" c_iconv :: IConvTPtr -> Ptr CString -> Ptr CSize-                            -> Ptr CString -> Ptr CSize -> IO CSize--data Result = Successful-            | Invalid ByteString-            | Incomplete ByteString-    deriving Show--iconv :: IConvT -> ByteString -> IO (ByteString,Result)-iconv cd inStr = useAsCStringLen inStr $ \(inPtr, inBuffLen) ->-        with inPtr $ \inBuff ->-        with (toEnum inBuffLen) $ \inBytesLeft -> do-                out <- loop inBuffLen (castPtr inBuff) inBytesLeft-                return out-    where-        -- TODO: maybe a better algorithm for increasing the buffer size?-        -- and also maybe a different starting buffer size?-        biggerBuffer = (+1)-        loop outSize inBuff inBytesLeft = do-            (bs, errno) <- partialIconv cd outSize inBuff inBytesLeft-            inLeft <- fmap fromEnum $ peek inBytesLeft-            let rest = B.drop (B.length inStr - inLeft) inStr-            case errno of-                Nothing -> return (bs,Successful)-                Just err -                    | err == e2BIG  -> do -- output buffer too small-                            (bs',result) <- loop (biggerBuffer outSize) inBuff inBytesLeft-                            -- TODO: is this efficient enough?-                            return (bs `append` bs', result)-                    | err == eINVAL -> return (bs,Incomplete rest)-                    | otherwise     -> return (bs, Invalid rest)--partialIconv :: IConvT -> Int -> Ptr CString -> Ptr CSize -> IO (ByteString, Maybe Errno)-partialIconv cd outSize inBuff inBytesLeft =-    withForeignPtr cd $ \cd_p ->-    createAndTrim' outSize $ \outPtr ->-    with outPtr $ \outBuff ->-    with (toEnum outSize) $ \outBytesLeft -> do-        -- ignore the return value; checking the errno is more reliable.-        _ <- c_iconv cd_p inBuff inBytesLeft (castPtr outBuff) outBytesLeft-        outLeft <- fmap fromEnum $ peek outBytesLeft-        inLeft <- peek inBytesLeft-        errno <- if inLeft > 0-                    then fmap Just getErrno-                    else return Nothing-        return (0,outSize - outLeft,errno)-
src/Darcs/Util/Encoding/Win32.hs view
@@ -39,9 +39,12 @@     ( CodePage, nullPtr, getConsoleCP, getACP     , LPCSTR, LPWSTR, LPCWSTR, LPBOOL, DWORD ) +-- | Encode a Unicode 'String' into a 'ByteString' suitable for the current+-- console. encode :: String -> IO B.ByteString encode str = getCodePage >>= flip unicodeToCodePage str +-- | Convert a 'ByteString' from the console's encoding into a Unicode 'String'. decode :: B.ByteString -> IO String decode str = getCodePage >>= flip codePageToUnicode str 
− src/Darcs/Util/Environment.hs
@@ -1,15 +0,0 @@-module Darcs.Util.Environment-    (-      maybeGetEnv-    ) where--import Prelude ()-import Darcs.Prelude--import System.Environment ( getEnv )--import Darcs.Util.Exception ( catchall )--maybeGetEnv :: String-            -> IO (Maybe String)-maybeGetEnv s = fmap Just (getEnv s) `catchall` return Nothing -- err can only be isDoesNotExist
src/Darcs/Util/External.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} module Darcs.Util.External     ( cloneTree     , cloneFile
src/Darcs/Util/File.hs view
@@ -24,12 +24,11 @@ import System.Directory ( removeFile, getHomeDirectory,                           getAppUserDataDirectory, doesDirectoryExist,                           createDirectory, getDirectoryContents )-import System.IO.Error ( isDoesNotExistError )-import System.Posix.Files( getSymbolicLinkStatus, FileStatus, isDirectory+import System.IO.Error ( isDoesNotExistError, catchIOError )+import System.Posix.Files( getSymbolicLinkStatus, FileStatus, isDirectory ) #ifndef WIN32-                         , setFileMode, ownerModes+import System.Posix.Files( setFileMode, ownerModes ) #endif-                         ) import System.FilePath.Posix ( (</>) )  import Darcs.Util.Exception ( catchall )@@ -47,10 +46,9 @@         (\oldwd -> setCurrentDirectory oldwd `catchall` return ())         (const m) -getFileStatus :: FilePath-              -> IO (Maybe FileStatus)+getFileStatus :: FilePath -> IO (Maybe FileStatus) getFileStatus f =-  Just `fmap` getSymbolicLinkStatus f `catchall` return Nothing+  Just `fmap` getSymbolicLinkStatus f `catchIOError` (\_-> return Nothing)  doesDirectoryReallyExist :: FilePath -> IO Bool doesDirectoryReallyExist f =
src/Darcs/Util/Global.hs view
@@ -15,8 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- -- | -- Module      : Darcs.Util.Global -- Copyright   : 2005 Tomasz Zielonka
src/Darcs/Util/Hash.hs view
@@ -1,63 +1,269 @@---  Copyright (C) 2009-2011 Petr Rockai------  BSD3-{-# LANGUAGE DeriveDataTypeable #-}-module Darcs.Util.Hash( Hash(..)-                      , encodeBase16, decodeBase16, sha256, rawHash-                      , match ) where+--  Copyright (C) 2009-2011 Petr Rockai BSD3+--  Copyright (C) 2001, 2004 Ian Lynagh <igloo@earth.li> -import qualified Crypto.Hash.SHA256 as SHA256 ( hash )-import qualified Data.ByteString as BS+{-# LANGUAGE CPP, DeriveDataTypeable #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing #-}++-- TODO switch to cryptonite++module Darcs.Util.Hash+    ( Hash(..)+    , encodeBase16, decodeBase16, sha256, sha256sum, rawHash+    , match+    -- SHA1 related (patch metadata hash)+    , sha1PS, SHA1, showAsHex, sha1Xor, sha1zero, sha1short+ ) where++import qualified Crypto.Hash.SHA256 as SHA256 ( hashlazy, hash )+import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL-import qualified Data.ByteString.Char8 as BS8+import qualified Data.ByteString.Char8 as BC+import qualified Data.ByteString.Internal as BI ( toForeignPtr )  import qualified Codec.Binary.Base16 as B16  import Data.Maybe( isJust, fromJust )-import Data.Char( toLower, toUpper )+import Data.Char( toLower, toUpper, intToDigit ) +import Data.Binary ( Binary(..) )+import Data.Bits (xor, (.&.), (.|.), complement, rotateL, shiftL, shiftR)+import Data.Word (Word8, Word32) import Data.Data( Data ) import Data.Typeable( Typeable )+import Foreign.ForeignPtr ( withForeignPtr )+import Foreign.Ptr (Ptr, castPtr, plusPtr)+import Foreign.Marshal.Array (advancePtr)+import Foreign.Storable (peek, poke)+import System.IO.Unsafe (unsafePerformIO) -data Hash = SHA256 !BS.ByteString-          | SHA1 !BS.ByteString++data Hash = SHA256 !B.ByteString           | NoHash             deriving (Show, Eq, Ord, Read, Typeable, Data) -base16 :: BS.ByteString -> BS.ByteString-debase16 :: BS.ByteString -> Maybe BS.ByteString+base16 :: B.ByteString -> B.ByteString+debase16 :: B.ByteString -> Maybe B.ByteString -base16 = BS8.map toLower . B16.b16Enc-debase16 bs = case B16.b16Dec $ BS8.map toUpper bs of+base16 = BC.map toLower . B16.b16Enc+debase16 bs = case B16.b16Dec $ BC.map toUpper bs of                 Right (s, _) -> Just s                 Left _ -> Nothing  -- | Produce a base16 (ascii-hex) encoded string from a hash. This can be -- turned back into a Hash (see "decodeBase16". This is a loss-less process.-encodeBase16 :: Hash -> BS.ByteString+encodeBase16 :: Hash -> B.ByteString encodeBase16 (SHA256 bs) = base16 bs-encodeBase16 (SHA1 bs) = base16 bs-encodeBase16 NoHash = BS.empty+encodeBase16 NoHash = B.empty  -- | Take a base16-encoded string and decode it as a "Hash". If the string is -- malformed, yields NoHash.-decodeBase16 :: BS.ByteString -> Hash-decodeBase16 bs | BS.length bs == 64 && isJust (debase16 bs) = SHA256 (fromJust $ debase16 bs)-                | BS.length bs == 40 && isJust (debase16 bs) = SHA1 (fromJust $ debase16 bs)+decodeBase16 :: B.ByteString -> Hash+decodeBase16 bs | B.length bs == 64 && isJust (debase16 bs) = SHA256 (fromJust $ debase16 bs)                 | otherwise = NoHash --- | Compute a sha256 of a (lazy) ByteString. However, although this works--- correctly for any bytestring, it is only efficient if the bytestring only--- has a sigle chunk.+-- | Compute a sha256 of a (lazy) ByteString. sha256 :: BL.ByteString -> Hash-sha256 bits = SHA256 $ SHA256.hash $ BS.concat $ BL.toChunks bits+sha256 bits = SHA256 $ SHA256.hashlazy bits -rawHash :: Hash -> BS.ByteString+-- | Same as previous but general purpose.+sha256sum :: B.ByteString -> String+sha256sum = BC.unpack . base16 . SHA256.hash++rawHash :: Hash -> B.ByteString rawHash NoHash = error "Cannot obtain raw hash from NoHash."-rawHash (SHA1 s) = s rawHash (SHA256 s) = s  match :: Hash -> Hash -> Bool NoHash `match` _ = False _ `match` NoHash = False x `match` y = x == y++data SHA1 = SHA1 !Word32 !Word32 !Word32 !Word32 !Word32+  deriving (Eq,Ord)+data XYZ = XYZ !Word32 !Word32 !Word32++instance Show SHA1 where+ show (SHA1 a b c d e) = concatMap showAsHex [a, b, c, d, e]++instance Binary SHA1 where+  put (SHA1 a b c d e) = put a >> put b >> put c >> put d >> put e+  get = do a <- get ; b <- get ; c <- get ; d <- get ; e <- get ; return (SHA1 a b c d e)++sha1Xor :: SHA1 -> SHA1 -> SHA1+sha1Xor (SHA1 a1 b1 c1 d1 e1) (SHA1 a2 b2 c2 d2 e2) =+ SHA1 (a1 `xor` a2) (b1 `xor` b2) (c1 `xor` c2) (d1 `xor` d2) (e1 `xor` e2)++sha1zero :: SHA1+sha1zero = SHA1 0 0 0 0 0++sha1short :: SHA1 -> Word32+sha1short (SHA1 a _ _ _ _) = a++-- | Do something with the internals of a PackedString. Beware of+-- altering the contents!+unsafeWithInternals :: B.ByteString -> (Ptr Word8 -> Int -> IO a) -> IO a+unsafeWithInternals ps f+ = case BI.toForeignPtr ps of+   (fp,s,l) -> withForeignPtr fp $ \p -> f (p `plusPtr` s) l++sha1PS:: B.ByteString -> SHA1+sha1PS s = abcde'+ where s1_2 = sha1Step12PadLength s+       abcde = sha1Step3Init+       abcde' = unsafePerformIO+              $ unsafeWithInternals s1_2 (\ptr len ->+                    do let ptr' = castPtr ptr+#ifndef BIGENDIAN+                       fiddleEndianness ptr' len+#endif+                       sha1Step4Main abcde ptr' len)++fiddleEndianness :: Ptr Word32 -> Int -> IO ()+fiddleEndianness p 0 = p `seq` return ()+fiddleEndianness p n+ = do x <- peek p+      poke p $ shiftL x 24+           .|. shiftL (x .&. 0xff00) 8+           .|. (shiftR x 8 .&. 0xff00)+           .|. shiftR x 24+      fiddleEndianness (p `advancePtr` 1) (n - 4)++-- sha1Step12PadLength assumes the length is at most 2^61.+-- This seems reasonable as the Int used to represent it is normally 32bit,+-- but obviously could go wrong with large inputs on 64bit machines.+-- The B.ByteString library should probably move to Word64s if this is an+-- issue, though.++sha1Step12PadLength :: B.ByteString -> B.ByteString+sha1Step12PadLength s+ = let len = B.length s+       num_nuls = (55 - len) `mod` 64+       padding = 128:replicate num_nuls 0+       len_w8s = reverse $ sizeSplit 8 (fromIntegral len*8)+   in B.concat [s, B.pack padding, B.pack len_w8s]++sizeSplit :: Int -> Integer -> [Word8]+sizeSplit 0 _ = []+sizeSplit p n = fromIntegral d:sizeSplit (p-1) n'+ where (n', d) = divMod n 256++sha1Step3Init :: SHA1+sha1Step3Init = SHA1 0x67452301 0xefcdab89 0x98badcfe 0x10325476 0xc3d2e1f0++sha1Step4Main :: SHA1 -> Ptr Word32 -> Int -> IO SHA1+sha1Step4Main abcde _ 0 = return $! abcde+sha1Step4Main (SHA1 a0@a b0@b c0@c d0@d e0@e) s len+    = do+         (e, b) <- doit f1 0x5a827999 (x 0) a b c d e+         (d, a) <- doit f1 0x5a827999 (x 1) e a b c d+         (c, e) <- doit f1 0x5a827999 (x 2) d e a b c+         (b, d) <- doit f1 0x5a827999 (x 3) c d e a b+         (a, c) <- doit f1 0x5a827999 (x 4) b c d e a+         (e, b) <- doit f1 0x5a827999 (x 5) a b c d e+         (d, a) <- doit f1 0x5a827999 (x 6) e a b c d+         (c, e) <- doit f1 0x5a827999 (x 7) d e a b c+         (b, d) <- doit f1 0x5a827999 (x 8) c d e a b+         (a, c) <- doit f1 0x5a827999 (x 9) b c d e a+         (e, b) <- doit f1 0x5a827999 (x 10) a b c d e+         (d, a) <- doit f1 0x5a827999 (x 11) e a b c d+         (c, e) <- doit f1 0x5a827999 (x 12) d e a b c+         (b, d) <- doit f1 0x5a827999 (x 13) c d e a b+         (a, c) <- doit f1 0x5a827999 (x 14) b c d e a+         (e, b) <- doit f1 0x5a827999 (x 15) a b c d e+         (d, a) <- doit f1 0x5a827999 (m 16) e a b c d+         (c, e) <- doit f1 0x5a827999 (m 17) d e a b c+         (b, d) <- doit f1 0x5a827999 (m 18) c d e a b+         (a, c) <- doit f1 0x5a827999 (m 19) b c d e a+         (e, b) <- doit f2 0x6ed9eba1 (m 20) a b c d e+         (d, a) <- doit f2 0x6ed9eba1 (m 21) e a b c d+         (c, e) <- doit f2 0x6ed9eba1 (m 22) d e a b c+         (b, d) <- doit f2 0x6ed9eba1 (m 23) c d e a b+         (a, c) <- doit f2 0x6ed9eba1 (m 24) b c d e a+         (e, b) <- doit f2 0x6ed9eba1 (m 25) a b c d e+         (d, a) <- doit f2 0x6ed9eba1 (m 26) e a b c d+         (c, e) <- doit f2 0x6ed9eba1 (m 27) d e a b c+         (b, d) <- doit f2 0x6ed9eba1 (m 28) c d e a b+         (a, c) <- doit f2 0x6ed9eba1 (m 29) b c d e a+         (e, b) <- doit f2 0x6ed9eba1 (m 30) a b c d e+         (d, a) <- doit f2 0x6ed9eba1 (m 31) e a b c d+         (c, e) <- doit f2 0x6ed9eba1 (m 32) d e a b c+         (b, d) <- doit f2 0x6ed9eba1 (m 33) c d e a b+         (a, c) <- doit f2 0x6ed9eba1 (m 34) b c d e a+         (e, b) <- doit f2 0x6ed9eba1 (m 35) a b c d e+         (d, a) <- doit f2 0x6ed9eba1 (m 36) e a b c d+         (c, e) <- doit f2 0x6ed9eba1 (m 37) d e a b c+         (b, d) <- doit f2 0x6ed9eba1 (m 38) c d e a b+         (a, c) <- doit f2 0x6ed9eba1 (m 39) b c d e a+         (e, b) <- doit f3 0x8f1bbcdc (m 40) a b c d e+         (d, a) <- doit f3 0x8f1bbcdc (m 41) e a b c d+         (c, e) <- doit f3 0x8f1bbcdc (m 42) d e a b c+         (b, d) <- doit f3 0x8f1bbcdc (m 43) c d e a b+         (a, c) <- doit f3 0x8f1bbcdc (m 44) b c d e a+         (e, b) <- doit f3 0x8f1bbcdc (m 45) a b c d e+         (d, a) <- doit f3 0x8f1bbcdc (m 46) e a b c d+         (c, e) <- doit f3 0x8f1bbcdc (m 47) d e a b c+         (b, d) <- doit f3 0x8f1bbcdc (m 48) c d e a b+         (a, c) <- doit f3 0x8f1bbcdc (m 49) b c d e a+         (e, b) <- doit f3 0x8f1bbcdc (m 50) a b c d e+         (d, a) <- doit f3 0x8f1bbcdc (m 51) e a b c d+         (c, e) <- doit f3 0x8f1bbcdc (m 52) d e a b c+         (b, d) <- doit f3 0x8f1bbcdc (m 53) c d e a b+         (a, c) <- doit f3 0x8f1bbcdc (m 54) b c d e a+         (e, b) <- doit f3 0x8f1bbcdc (m 55) a b c d e+         (d, a) <- doit f3 0x8f1bbcdc (m 56) e a b c d+         (c, e) <- doit f3 0x8f1bbcdc (m 57) d e a b c+         (b, d) <- doit f3 0x8f1bbcdc (m 58) c d e a b+         (a, c) <- doit f3 0x8f1bbcdc (m 59) b c d e a+         (e, b) <- doit f2 0xca62c1d6 (m 60) a b c d e+         (d, a) <- doit f2 0xca62c1d6 (m 61) e a b c d+         (c, e) <- doit f2 0xca62c1d6 (m 62) d e a b c+         (b, d) <- doit f2 0xca62c1d6 (m 63) c d e a b+         (a, c) <- doit f2 0xca62c1d6 (m 64) b c d e a+         (e, b) <- doit f2 0xca62c1d6 (m 65) a b c d e+         (d, a) <- doit f2 0xca62c1d6 (m 66) e a b c d+         (c, e) <- doit f2 0xca62c1d6 (m 67) d e a b c+         (b, d) <- doit f2 0xca62c1d6 (m 68) c d e a b+         (a, c) <- doit f2 0xca62c1d6 (m 69) b c d e a+         (e, b) <- doit f2 0xca62c1d6 (m 70) a b c d e+         (d, a) <- doit f2 0xca62c1d6 (m 71) e a b c d+         (c, e) <- doit f2 0xca62c1d6 (m 72) d e a b c+         (b, d) <- doit f2 0xca62c1d6 (m 73) c d e a b+         (a, c) <- doit f2 0xca62c1d6 (m 74) b c d e a+         (e, b) <- doit f2 0xca62c1d6 (m 75) a b c d e+         (d, a) <- doit f2 0xca62c1d6 (m 76) e a b c d+         (c, e) <- doit f2 0xca62c1d6 (m 77) d e a b c+         (b, d) <- doit f2 0xca62c1d6 (m 78) c d e a b+         (a, c) <- doit f2 0xca62c1d6 (m 79) b c d e a+         let abcde' = SHA1 (a0 + a) (b0 + b) (c0 + c) (d0 + d) (e0 + e)+         sha1Step4Main abcde' (s `advancePtr` 16) (len - 64)+ where {-# INLINE f1 #-}+       f1 (XYZ x y z) = (x .&. y) .|. (complement x .&. z)+       {-# INLINE f2 #-}+       f2 (XYZ x y z) = x `xor` y `xor` z+       {-# INLINE f3 #-}+       f3 (XYZ x y z) = (x .&. y) .|. (x .&. z) .|. (y .&. z)+       {-# INLINE x #-}+       x n = peek (s `advancePtr` n)+       {-# INLINE m #-}+       m n = do let base = s `advancePtr` (n .&. 15)+                x0 <- peek base+                x1 <- peek (s `advancePtr` ((n - 14) .&. 15))+                x2 <- peek (s `advancePtr` ((n - 8) .&. 15))+                x3 <- peek (s `advancePtr` ((n - 3) .&. 15))+                let res = rotateL (x0 `xor` x1 `xor` x2 `xor` x3) 1+                poke base res+                return res+       {-# INLINE doit #-}+       doit f k i a b c d e = a `seq` c `seq`+           do i' <- i+              return (rotateL a 5 + f (XYZ b c d) + e + i' + k,+                      rotateL b 30)++showAsHex :: Word32 -> String+showAsHex n = showIt 8 n ""+   where+    showIt :: Int -> Word32 -> String -> String+    showIt 0 _ r = r+    showIt i x r = case quotRem x 16 of+                       (y, z) -> let c = intToDigit (fromIntegral z)+                                 in c `seq` showIt (i-1) y (c:r)
src/Darcs/Util/Index.hs view
@@ -68,55 +68,64 @@     where  import Prelude hiding ( lookup, readFile, writeFile, filter, (<$>) )-import Darcs.Util.ByteString ( readSegment )+import Darcs.Util.ByteString ( readSegment, decodeLocale )+import Darcs.Util.File ( getFileStatus )+import Darcs.Util.Hash( sha256, rawHash ) import Darcs.Util.Tree-import Darcs.Util.Path hiding ( getCurrentDirectory )-import Data.Int( Int64, Int32 )--import Bundled.Posix( getFileStatusBS, modificationTime,-                      getFileStatus, fileSize, fileExists, isDirectory )-import System.IO.MMap( mmapFileForeignPtr, mmapFileByteString, Mode(..) )-import System.IO( )-import System.Directory( doesFileExist, getCurrentDirectory, doesDirectoryExist )-#if mingw32_HOST_OS-import System.Directory( renameFile )-import System.FilePath( (<.>) )-#else-import System.Directory( removeFile )-#endif-import System.FilePath( (</>) )-import System.Posix.Types ( FileID )-+import Darcs.Util.Path+    ( AnchoredPath(..)+    , anchorPath+    , anchoredRoot+    , unsafeMakeName+    , appendPath+    , flatten+    ) import Control.Monad( when ) import Control.Exception( catch, SomeException ) import Control.Applicative( (<$>) ) -import qualified Data.ByteString as BS-import qualified Data.ByteString.Char8 as BSC+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as BC import Data.ByteString.Unsafe( unsafeHead, unsafeDrop ) import Data.ByteString.Internal( toForeignPtr, fromForeignPtr, memcpy                                , nullForeignPtr, c2w ) -import Data.IORef( )-import Data.Maybe( fromJust, isJust, fromMaybe ) import Data.Bits( Bits ) #ifdef BIGENDIAN import Data.Bits( (.&.), (.|.), shift, shiftL, rotateR ) #endif+import Data.Int( Int64, Int32 )+import Data.IORef( )+import Data.Maybe( fromJust, isJust, fromMaybe )  import Foreign.Storable import Foreign.ForeignPtr( ForeignPtr, withForeignPtr, castForeignPtr ) import Foreign.Ptr( Ptr, plusPtr ) -import Darcs.Util.Hash( sha256, rawHash )+import System.IO.MMap( mmapFileForeignPtr, mmapFileByteString, Mode(..) )+import System.Directory( doesFileExist, getCurrentDirectory, doesDirectoryExist )+#if mingw32_HOST_OS+import System.Directory( renameFile )+import System.FilePath( (<.>) )+#else+import System.Directory( removeFile )+#endif+ #ifdef WIN32 import System.Win32.File ( createFile, getFileInformationByHandle, BY_HANDLE_FILE_INFORMATION(..),                            fILE_SHARE_NONE, fILE_FLAG_BACKUP_SEMANTICS,                            gENERIC_NONE, oPEN_EXISTING, closeHandle ) #else-import System.PosixCompat ( fileID, getSymbolicLinkStatus )+import qualified System.Posix.Files as F ( getSymbolicLinkStatus, fileID ) #endif +import System.FilePath ( (</>) )+import qualified System.Posix.Files as F+    ( modificationTime, fileSize, isDirectory+    , FileStatus+    )+import System.Posix.Types ( FileID, EpochTime, FileOffset )+ -------------------------- -- Indexed trees --@@ -131,7 +140,7 @@ -- recursive Tree object, which is rather expensive... As a bonus, we can also -- efficiently implement subtree queries this way (cf. 'readIndex'). data Item = Item { iBase :: !(Ptr ())-                 , iHashAndDescriptor :: !BS.ByteString+                 , iHashAndDescriptor :: !B.ByteString                  } deriving Show  size_magic :: Int@@ -154,17 +163,19 @@  itemAllocSize :: AnchoredPath -> Int itemAllocSize apath =-    align 4 $ size_hash + size_size + size_aux + size_fileid + size_dsclen + 2 + BS.length (flatten apath)+    align 4 $ size_hash + size_size + size_aux + size_fileid + size_dsclen + 2 + B.length (flatten apath)  itemSize, itemNext :: Item -> Int-itemSize i = size_size + size_aux + size_fileid + size_dsclen + (BS.length $ iHashAndDescriptor i)+itemSize i = size_size + size_aux + size_fileid + size_dsclen + (B.length $ iHashAndDescriptor i) itemNext i = align 4 (itemSize i + 1) -iPath, iHash, iDescriptor :: Item -> BS.ByteString+iHash, iDescriptor :: Item -> B.ByteString iDescriptor = unsafeDrop size_hash . iHashAndDescriptor-iPath = unsafeDrop 1 . iDescriptor-iHash = BS.take size_hash . iHashAndDescriptor+iHash = B.take size_hash . iHashAndDescriptor +iPath :: Item -> FilePath+iPath = decodeLocale . unsafeDrop 1 . iDescriptor+ iSize, iAux :: Item -> Ptr Int64 iSize i = plusPtr (iBase i) off_size iAux i = plusPtr (iBase i) off_aux@@ -183,15 +194,29 @@ xlatePoke64 :: (Storable a, Num a, Bits a) => Ptr a -> a -> IO () xlatePoke64 ptr v = poke ptr (xlate64 v) +type FileStatus = Maybe F.FileStatus++modificationTime :: FileStatus -> EpochTime+modificationTime = maybe 0 F.modificationTime++fileSize :: FileStatus -> FileOffset+fileSize = maybe 0 F.fileSize++fileExists :: FileStatus -> Bool+fileExists = maybe False (const True)++isDirectory :: FileStatus -> Bool+isDirectory = maybe False F.isDirectory+ -- | Lay out the basic index item structure in memory. The memory location is -- given by a ForeignPointer () and an offset. The path and type given are -- written out, and a corresponding Item is given back. The remaining bits of -- the item can be filled out using 'update'. createItem :: ItemType -> AnchoredPath -> ForeignPtr () -> Int -> IO Item createItem typ apath fp off =- do let dsc = BS.concat [ BSC.singleton $ if typ == TreeType then 'D' else 'F'+ do let dsc = B.concat [ BC.singleton $ if typ == TreeType then 'D' else 'F'                         , flatten apath-                        , BS.singleton 0 ]+                        , B.singleton 0 ]         (dsc_fp, dsc_start, dsc_len) = toForeignPtr dsc     withForeignPtr fp $ \p ->         withForeignPtr dsc_fp $ \dsc_p ->@@ -221,7 +246,7 @@ -- when updating directory entries). updateItem :: Item -> Int64 -> Hash -> IO () updateItem item _ NoHash =-    fail $ "Index.update NoHash: " ++ BSC.unpack (iPath item)+    fail $ "Index.update NoHash: " ++ iPath item updateItem item size hash =     do xlatePoke64 (iSize item) size        unsafePokeBS (iHash item) (rawHash hash)@@ -241,9 +266,7 @@ -- the index file. mmapIndex will grow the index if it is smaller than this. mmapIndex :: forall a. FilePath -> Int -> IO (ForeignPtr a, Int) mmapIndex indexpath req_size = do-  exist <- doesFileExist indexpath-  act_size <- fromIntegral `fmap` if exist then fileSize `fmap` getFileStatus indexpath-                                           else return 0+  act_size <- fromIntegral . fileSize <$> getFileStatus indexpath   let size = case req_size > 0 of         True -> req_size         False | act_size >= size_magic -> act_size - size_magic@@ -293,19 +316,19 @@   return res'  readDir :: Index -> State -> Item -> IO Result-readDir index state item =-    do following <- fromIntegral <$> xlatePeek64 (iAux item)-       st <- getFileStatusBS (iPath item)+readDir index state item = do+       following <- fromIntegral <$> xlatePeek64 (iAux item)+       st <- getFileStatus (iPath item)        let exists = fileExists st && isDirectory st        fileid <- fromIntegral <$> (xlatePeek64 $ iFileID item)-       fileid' <- fromMaybe fileid <$> (getFileID' $ BSC.unpack $ iPath item)+       fileid' <- fromMaybe fileid <$> (getFileID' $ iPath item)        when (fileid == 0) $ updateFileID item fileid'-       let name it dirlen = Name $ (BS.drop (dirlen + 1) $ iDescriptor it) -- FIXME MAGIC-           namelength = (BS.length $ iDescriptor item) - (dirlength state)+       let name it dirlen = unsafeMakeName $ (B.drop (dirlen + 1) $ iDescriptor it) -- FIXME MAGIC+           namelength = (B.length $ iDescriptor item) - (dirlength state)            myname = name item (dirlength state)            substate = state { start = start state + itemNext item                             , path = path state `appendPath` myname-                            , dirlength = if myname == Name (BSC.singleton '.')+                            , dirlength = if myname == unsafeMakeName (BC.singleton '.')                                              then dirlength state                                              else dirlength state + namelength } @@ -325,7 +348,7 @@         let we_changed = or [ changed x | (_, x) <- inferiors ] || nullleaf            nullleaf = null inferiors && oldhash == nullsha-           nullsha = SHA256 (BS.replicate 32 0)+           nullsha = SHA256 (B.replicate 32 0)            tree' = makeTree [ (n, fromJust $ treeitem s) | (n, s) <- inferiors, isJust $ treeitem s ]            treehash = if we_changed then hashtree index tree' else oldhash            tree = tree' { treeHash = treehash }@@ -338,15 +361,15 @@                        , resitem = item }  readFile :: Index -> State -> Item -> IO Result-readFile index state item =-    do st <- getFileStatusBS (iPath item)+readFile index state item = do+       st <- getFileStatus (iPath item)        mtime <- fromIntegral <$> (xlatePeek64 $ iAux item)        size <- xlatePeek64 $ iSize item        fileid <- fromIntegral <$> (xlatePeek64 $ iFileID item)-       fileid' <- fromMaybe fileid <$> (getFileID' $ BSC.unpack $ iPath item)+       fileid' <- fromMaybe fileid <$> (getFileID' $ iPath item)        let mtime' = modificationTime st            size' = fromIntegral $ fileSize st-           readblob = readSegment (basedir index </> BSC.unpack (iPath item), Nothing)+           readblob = readSegment (basedir index </> (iPath item), Nothing)            exists = fileExists st && not (isDirectory st)            we_changed = mtime /= mtime' || size /= size'            hash = iHash' item@@ -394,12 +417,12 @@ readDirFileIDs index state item =     do fileid <- fromIntegral <$> (xlatePeek64 $ iFileID item)        following <- fromIntegral <$> xlatePeek64 (iAux item)-       let name it dirlen = Name $ (BS.drop (dirlen + 1) $ iDescriptor it) -- FIXME MAGIC-           namelength = (BS.length $ iDescriptor item) - (dirlength state)+       let name it dirlen = unsafeMakeName $ (B.drop (dirlen + 1) $ iDescriptor it) -- FIXME MAGIC+           namelength = (B.length $ iDescriptor item) - (dirlength state)            myname = name item (dirlength state)            substate = state { start = start state + itemNext item                             , path = path state `appendPath` myname-                            , dirlength = if myname == Name (BSC.singleton '.')+                            , dirlength = if myname == unsafeMakeName (BC.singleton '.')                                              then dirlength state                                              else dirlength state + namelength }            subs off | off < following = do@@ -417,7 +440,7 @@ readFileFileID :: Index -> State -> Item -> IO ResultF readFileFileID _ state item =     do fileid' <- fromIntegral <$> (xlatePeek64 $ iFileID item)-       let name it dirlen = Name $ (BS.drop (dirlen + 1) $ iDescriptor it)+       let name it dirlen = unsafeMakeName $ (B.drop (dirlen + 1) $ iDescriptor it)            myname = name item (dirlength state)        return $ ResultF { nextF = start state + itemNext item                         , resitemF = item@@ -448,11 +471,11 @@ formatIndex :: ForeignPtr () -> Tree IO -> Tree IO -> IO () formatIndex mmap_ptr old reference =     do _ <- create (SubTree reference) (AnchoredPath []) size_magic-       unsafePokeBS magic (BSC.pack "HSI5")+       unsafePokeBS magic (BC.pack "HSI5")     where magic = fromForeignPtr (castForeignPtr mmap_ptr) 0 4           create (File _) path' off =                do i <- createItem BlobType path' mmap_ptr off-                  let flatpath = BSC.unpack $ flatten path'+                  let flatpath = anchorPath "" path'                   case find old path' of                     Nothing -> return ()                     -- TODO calling getFileStatus here is both slightly@@ -503,12 +526,13 @@ -- | Check that a given file is an index file with a format we can handle. You -- should remove and re-create the index whenever this is not true. indexFormatValid :: FilePath -> IO Bool-indexFormatValid path' =-    do magic <- mmapFileByteString path' (Just (0, size_magic))-       return $ case BSC.unpack magic of-                  "HSI5" -> True-                  _ -> False-    `catch` \(_::SomeException) -> return False+indexFormatValid path' = do+    v <- do magic <- mmapFileByteString path' (Just (0, size_magic))+            return $ case BC.unpack magic of+                       "HSI5" -> True+                       _ -> False+         `catch` \(_::SomeException) -> return False+    return v  instance FilterTree IndexM IO where     filter _ EmptyIndex = EmptyIndex@@ -530,13 +554,13 @@                               closeHandle h                               return fhnumber #else-                      then (Just . fileID) <$> getSymbolicLinkStatus fp+                      then (Just . F.fileID) <$> F.getSymbolicLinkStatus fp #endif                       else return Nothing   -- Wow, unsafe.-unsafePokeBS :: BSC.ByteString -> BSC.ByteString -> IO ()+unsafePokeBS :: BC.ByteString -> BC.ByteString -> IO () unsafePokeBS to from =     do let (fp_to, off_to, len_to) = toForeignPtr to            (fp_from, off_from, len_from) = toForeignPtr from
src/Darcs/Util/IsoDate.hs view
@@ -26,7 +26,7 @@ -- Portability : portable  module Darcs.Util.IsoDate-    ( getIsoDateTime, readUTCDate+    ( getIsoDateTime, readUTCDate, readUTCDateOldFashioned     , parseDate, getLocalTz     , englishDateTime, englishInterval, englishLast     , iso8601Interval, iso8601Duration@@ -34,6 +34,7 @@     , MCalendarTime(..), subtractFromMCal, addToMCal     , toMCalendarTime, unsafeToCalendarTime     , unsetTime, TimeInterval+    , showIsoDateTime     ) where  import Prelude ( (^) )@@ -45,7 +46,7 @@ import Data.Char ( toUpper, isDigit ) import Data.Maybe ( fromMaybe ) import Control.Monad ( liftM, liftM2 )-import qualified Data.ByteString.Char8 as B+import qualified Data.ByteString.Char8 as BC  type TimeInterval = (Maybe CalendarTime, Maybe CalendarTime) @@ -77,25 +78,36 @@              Left e -> error $ "bad date: "++d++" - "++show e              Right ct -> resetCalendar $ unsafeToCalendarTime ct +-- | Similar to 'readUTCDate', except we /ignore/ timezone info+-- in the input string. This is incorrect and ugly. The only reason+-- it still exists is so we can generate file names for old-fashioned+-- repositories in the same way that old darcs versions expected them.+-- You should not use this function except for the above stated purpose.+readUTCDateOldFashioned :: String -> CalendarTime+readUTCDateOldFashioned d = +             case parseDate 0 d of+             Left e -> error $ "bad date: "++d++" - "++show e+             Right ct -> (unsafeToCalendarTime ct) { ctTZ = 0 }+ -- | Parse a date string, assuming a default timezone if --   the date string does not specify one.  The date formats --   understood are those of 'showIsoDateTime' and 'dateTime' parseDate :: Int -> String -> Either ParseError MCalendarTime parseDate tz d =-              if length d >= 14 && B.all isDigit bd+              if length d >= 14 && BC.all isDigit bd               then Right $ toMCalendarTime $-                   CalendarTime (readI $ B.take 4 bd)-                                (toEnum $ (+ (-1)) $ readI $ B.take 2 $ B.drop 4 bd)-                                (readI $ B.take 2 $ B.drop 6 bd) -- Day-                                (readI $ B.take 2 $ B.drop 8 bd) -- Hour-                                (readI $ B.take 2 $ B.drop 10 bd) -- Minute-                                (readI $ B.take 2 $ B.drop 12 bd) -- Second+                   CalendarTime (readI $ BC.take 4 bd)+                                (toEnum $ (+ (-1)) $ readI $ BC.take 2 $ BC.drop 4 bd)+                                (readI $ BC.take 2 $ BC.drop 6 bd) -- Day+                                (readI $ BC.take 2 $ BC.drop 8 bd) -- Hour+                                (readI $ BC.take 2 $ BC.drop 10 bd) -- Minute+                                (readI $ BC.take 2 $ BC.drop 12 bd) -- Second                                 0 Sunday 0 -- Picosecond, weekday and day of year unknown                                 "GMT" 0 False               else let dt = do { x <- dateTime tz; eof; return x }                    in parse dt "" d-  where bd = B.pack (take 14 d)-        readI s = fst $ fromMaybe (error "parseDate: invalid date") (B.readInt s)+  where bd = BC.pack (take 14 d)+        readI s = fst $ fromMaybe (error "parseDate: invalid date") (BC.readInt s)  -- | Display a 'CalendarTime' in the ISO 8601 format without any --   separators, e.g. 20080825142503
src/Darcs/Util/Lock.hs view
@@ -15,8 +15,6 @@ -- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -- Boston, MA 02110-1301, USA. -{-# LANGUAGE CPP #-}- module Darcs.Util.Lock     ( withLock     , withLockCanFail@@ -28,15 +26,14 @@     , withPermDir     , withDelayedDir     , withNamedTemp-    , writeToFile-    , appendToFile     , writeBinFile-    , writeLocaleFile+    , writeTextFile     , writeDocBinFile     , appendBinFile+    , appendTextFile     , appendDocBinFile     , readBinFile-    , readLocaleFile+    , readTextFile     , readDocBinFile     , writeAtomicFilePS     , gzWriteAtomicFilePS@@ -46,23 +43,31 @@     , removeFileMayNotExist     , canonFilename     , maybeRelink-    , worldReadableTemp     , tempdirLoc     , environmentHelpTmpdir     , environmentHelpKeepTmpdir     , addToErrorLoc+    , withNewDirectory     ) where +import Prelude ()+import Darcs.Prelude+ import Data.List ( inits ) import Data.Maybe ( isJust, listToMaybe ) import System.Exit ( exitWith, ExitCode(..) )-import System.IO ( withBinaryFile, openBinaryTempFile,-                   hClose, hPutStr, Handle,-                   IOMode(WriteMode, AppendMode), hFlush, stdout )+import System.IO+    ( withFile, withBinaryFile, openBinaryTempFile+    , hClose, Handle, hPutStr, hSetEncoding+    , IOMode(WriteMode, AppendMode), hFlush, stdout+    ) import System.IO.Error     ( isAlreadyExistsError+    , alreadyExistsErrorType     , annotateIOError+    , mkIOError     )+import System.IO.Temp ( withTempDirectory ) import Control.Exception     ( IOException     , bracket@@ -71,17 +76,28 @@     , try     , SomeException     )-import System.Directory ( removeFile, removeDirectory,-                   doesFileExist, doesDirectoryExist,-                   getDirectoryContents, createDirectory,-                   getTemporaryDirectory,-                 )+import System.Directory+    ( removeFile+    , removeDirectory+    , doesFileExist+    , doesDirectoryExist+    , getDirectoryContents+    , createDirectory+    , getTemporaryDirectory+    , renameDirectory+    ) import System.FilePath.Posix ( splitDirectories )+import qualified System.FilePath as NativeFilePath ( takeDirectory )+import System.Environment ( lookupEnv )+ import Control.Concurrent ( threadDelay ) import Control.Monad ( unless, when, liftM ) +import System.Posix.Files ( fileMode, getFileStatus, setFileMode )++import GHC.IO.Encoding ( getFileSystemEncoding )+ import Darcs.Util.URL ( isRelative )-import Darcs.Util.Environment ( maybeGetEnv ) import Darcs.Util.Exception     ( firstJustIO     , catchall@@ -91,12 +107,11 @@ import Darcs.Util.Path ( AbsolutePath, FilePathLike, toFilePath,                         getCurrentDirectory, setCurrentDirectory ) -import Darcs.Util.ByteString ( gzWriteFilePSs, decodeLocale, encodeLocale )+import Darcs.Util.ByteString ( gzWriteFilePSs ) import qualified Data.ByteString as B (null, readFile, hPut, ByteString)-import qualified Data.ByteString.Char8 as BC (unpack)  import Darcs.Util.SignalHandler ( withSignalsBlocked )-import Darcs.Util.Printer ( Doc, hPutDoc, packedString, empty, renderPSs, RenderMode(..) )+import Darcs.Util.Printer ( Doc, hPutDoc, packedString, empty, renderPSs ) import Darcs.Util.AtExit ( atexit ) import Darcs.Util.Global ( darcsdir ) import Darcs.Util.Workaround ( renameFile )@@ -107,9 +122,8 @@     , atomicCreate     , sloppyAtomicCreate     )-import System.Posix.Files ( fileMode, getFileStatus, setFileMode )+import Darcs.Util.Progress ( debugMessage ) import Darcs.Util.Prompt ( askUser )-#include "impossible.h"  withLock :: String -> IO a -> IO a withLock s job = bracket (getlock s 30) releaseLock (\_ -> job)@@ -173,7 +187,7 @@ -- -- The temp file operations are rather similar to the locking operations, in -- that they both should always try to clean up, so exitWith causes trouble.-withTemp :: (String -> IO a) -> IO a+withTemp :: (FilePath -> IO a) -> IO a withTemp = bracket get_empty_file removeFileMayNotExist     where get_empty_file = do (f,h) <- openBinaryTempFile "." "darcs"                               hClose h@@ -184,20 +198,20 @@ -- both of them (to my knowledge) are not susceptible to race conditions on -- the temporary file (as long as you never delete the temporary file; that -- would reintroduce a race condition).-withOpenTemp :: ((Handle, String) -> IO a) -> IO a+withOpenTemp :: ((Handle, FilePath) -> IO a) -> IO a withOpenTemp = bracket get_empty_file cleanup     where cleanup (h,f) = do _ <- try (hClose h) :: IO (Either SomeException ())                              removeFileMayNotExist f           get_empty_file = invert `fmap` openBinaryTempFile "." "darcs"           invert (a,b) = (b,a) -withStdoutTemp :: (String -> IO a) -> IO a+withStdoutTemp :: (FilePath -> IO a) -> IO a withStdoutTemp = bracket (mkStdoutTemp "stdout_") removeFileMayNotExist  tempdirLoc :: IO FilePath tempdirLoc = liftM fromJust $-    firstJustIO [ liftM (Just . head . words) (readBinFile (darcsdir++"/prefs/tmpdir")) >>= chkdir,-                  maybeGetEnv "DARCS_TMPDIR" >>= chkdir,+    firstJustIO [ liftM (Just . head . words) (readFile (darcsdir++"/prefs/tmpdir")) >>= chkdir,+                  lookupEnv "DARCS_TMPDIR" >>= chkdir,                   getTemporaryDirectory >>= chkdir . Just,                   getCurrentDirectorySansDarcs,                   return $ Just "."  -- always returns a Just@@ -227,7 +241,7 @@ -- If an absolute path is given this dir will be created if it doesn't exist. -- If it is specified as a temporary dir, it is deleted after finishing the job. withDir :: WithDirKind  -- specifies if and when directory will be deleted-        -> String       -- path parameter+        -> FilePath     -- path parameter         -> (AbsolutePath -> IO a) -> IO a withDir _ "" _ = bug "withDir called with empty directory name" withDir kind absoluteOrRelativeName job = do@@ -253,7 +267,7 @@                 `catch` (\e -> if isAlreadyExistsError e                                then createDir name (n+1)                                else throwIO e)-          keepTempDir = isJust `fmap` maybeGetEnv "DARCS_KEEP_TMPDIR"+          keepTempDir = isJust `fmap` lookupEnv "DARCS_KEEP_TMPDIR"  environmentHelpKeepTmpdir :: ([String], [String]) environmentHelpKeepTmpdir = (["DARCS_KEEP_TMPDIR"],[@@ -265,11 +279,11 @@  -- |'withPermDir' is like 'withTempDir', except that it doesn't -- delete the directory afterwards.-withPermDir :: String -> (AbsolutePath -> IO a) -> IO a+withPermDir :: FilePath -> (AbsolutePath -> IO a) -> IO a withPermDir = withDir Perm --- |'withTempDir' creates an empty directory and then removes it when it--- is no longer needed.  withTempDir creates a temporary directory.  The+-- |'withTempDir' creates a temporary directory, runs the action and then+-- removes the directory. The -- location of that directory is determined by the contents of -- _darcs/prefs/tmpdir, if it exists, otherwise by @$DARCS_TMPDIR@, and if -- that doesn't exist then whatever your operating system considers to be a@@ -283,10 +297,10 @@ -- This should not fail, but if it does indeed fail, we go ahead and use the -- current directory anyway. If @$DARCS_KEEP_TMPDIR@ variable is set -- temporary directory is not removed, this can be useful for debugging.-withTempDir :: String -> (AbsolutePath -> IO a) -> IO a+withTempDir :: FilePath -> (AbsolutePath -> IO a) -> IO a withTempDir = withDir Temp -withDelayedDir :: String -> (AbsolutePath -> IO a) -> IO a+withDelayedDir :: FilePath -> (AbsolutePath -> IO a) -> IO a withDelayedDir = withDir Delayed  rmRecursive :: FilePath -> IO ()@@ -302,50 +316,62 @@               do c <- getDirectoryContents d                  return $ filter (/=".") $ filter (/="..") c -worldReadableTemp :: String -> IO String+worldReadableTemp :: FilePath -> IO FilePath worldReadableTemp f = wrt 0-    where wrt :: Int -> IO String+    where wrt :: Int -> IO FilePath           wrt 100 = fail $ "Failure creating temp named "++f           wrt n = let f_new = f++"-"++show n                   in do ok <- takeFile f_new                         if ok then return f_new                               else wrt (n+1) -withNamedTemp :: String -> (String -> IO a) -> IO a-withNamedTemp n = bracket get_empty_file removeFileMayNotExist-    where get_empty_file = worldReadableTemp n+withNamedTemp :: FilePath -> (FilePath -> IO a) -> IO a+withNamedTemp n f = do+    debugMessage $ "withNamedTemp: " ++ show n+    bracket (worldReadableTemp n) removeFileMayNotExist f -readBinFile :: FilePathLike p => p -> IO String-readBinFile = fmap BC.unpack . B.readFile . toFilePath+readBinFile :: FilePathLike p => p -> IO B.ByteString+readBinFile = B.readFile . toFilePath --- | Reads a file. Differs from readBinFile in that it interprets the file in---   the current locale instead of as ISO-8859-1.-readLocaleFile :: FilePathLike p => p -> IO String-readLocaleFile f = decodeLocale `fmap` B.readFile (toFilePath f)+-- NOTE using 'seq' on the last element of the result causes the content to be+-- fully evaluated, so the file is read strictly; this is more efficient than+-- counting the number of characters; and in the (few) places where we use this+-- function we need the lines anyway.+readTextFile :: FilePathLike p => p -> IO [String]+readTextFile f = do+  result <- lines <$> readFile (toFilePath f)+  case result of+    [] -> return result+    xs -> last xs `seq` return result  readDocBinFile :: FilePathLike p => p -> IO Doc readDocBinFile fp = do ps <- B.readFile $ toFilePath fp                        return $ if B.null ps then empty else packedString ps -appendBinFile :: FilePathLike p => p -> String -> IO ()-appendBinFile f s = appendToFile f $ \h -> hPutStr h s+appendBinFile :: FilePathLike p => p -> B.ByteString -> IO ()+appendBinFile f s = appendToFile Binary f $ \h -> B.hPut h s +appendTextFile :: FilePathLike p => p -> String -> IO ()+appendTextFile f s = appendToFile Text f $ \h -> hPutStr h s+ appendDocBinFile :: FilePathLike p => p -> Doc -> IO ()-appendDocBinFile f d = appendToFile f $ \h -> hPutDoc Standard h d+appendDocBinFile f d = appendToFile Binary f $ \h -> hPutDoc h d -writeBinFile :: FilePathLike p => p -> String -> IO ()-writeBinFile f s = writeToFile f $ \h -> hPutStr h s+data FileType = Text | Binary --- | Writes a file. Differs from writeBinFile in that it writes the string---   encoded with the current locale instead of what GHC thinks is right.-writeLocaleFile :: FilePathLike p => p -> String -> IO ()-writeLocaleFile f s = writeToFile f $ \h -> B.hPut h (encodeLocale s)+writeBinFile :: FilePathLike p => p -> B.ByteString -> IO ()+writeBinFile f s = writeToFile Binary f $ \h -> B.hPut h s +writeTextFile :: FilePathLike p => p -> String -> IO ()+writeTextFile f s = writeToFile Text f $ \h -> do+  getFileSystemEncoding >>= hSetEncoding h+  hPutStr h s+ writeDocBinFile :: FilePathLike p => p -> Doc -> IO ()-writeDocBinFile f d = writeToFile f $ \h -> hPutDoc Standard h d+writeDocBinFile f d = writeToFile Binary f $ \h -> hPutDoc h d  writeAtomicFilePS :: FilePathLike p => p -> B.ByteString -> IO ()-writeAtomicFilePS f ps = writeToFile f $ \h -> B.hPut h ps+writeAtomicFilePS f ps = writeToFile Binary f $ \h -> B.hPut h ps  gzWriteAtomicFilePS :: FilePathLike p => p -> B.ByteString -> IO () gzWriteAtomicFilePS f ps = gzWriteAtomicFilePSs f [ps]@@ -361,24 +387,43 @@     renameFile newf (toFilePath f)  gzWriteDocFile :: FilePathLike p => p -> Doc -> IO ()-gzWriteDocFile f d = gzWriteAtomicFilePSs f $ renderPSs Standard d+gzWriteDocFile f d = gzWriteAtomicFilePSs f $ renderPSs d -writeToFile :: FilePathLike p => p -> (Handle -> IO ()) -> IO ()-writeToFile f job =+writeToFile :: FilePathLike p => FileType -> p -> (Handle -> IO ()) -> IO ()+writeToFile t f job =     withSignalsBlocked $ withNamedTemp (toFilePath f) $ \newf -> do-    withBinaryFile newf WriteMode job+    (case t of+      Text -> withFile+      Binary -> withBinaryFile) newf WriteMode job     already_exists <- doesFileExist (toFilePath f)     when already_exists $ do mode <- fileMode `fmap` getFileStatus (toFilePath f)                              setFileMode newf mode              `catchall` return ()     renameFile newf (toFilePath f) -appendToFile :: FilePathLike p => p -> (Handle -> IO ()) -> IO ()-appendToFile f job = withSignalsBlocked $-    withBinaryFile (toFilePath f) AppendMode job+appendToFile :: FilePathLike p => FileType -> p -> (Handle -> IO ()) -> IO ()+appendToFile t f job = withSignalsBlocked $+    (case t of+      Binary -> withBinaryFile+      Text -> withFile) (toFilePath f) AppendMode job   addToErrorLoc :: IOException               -> String               -> IOException addToErrorLoc ioe s = annotateIOError ioe s Nothing Nothing++-- | Do an action in a newly created directory of the given name. The directory+-- is first created with a different temporary name (but under the same parent+-- directory), and becomes renamed to the final name when the action returns+-- without an exception. This operation raises an alreadyExists exception if a+-- file system object of the given name already exists.+withNewDirectory :: FilePath -> IO () -> IO ()+withNewDirectory name action = do+  exists1 <- doesFileExist name        -- TODO when depending on directory >= 1.2.7+  exists2 <- doesDirectoryExist name   --      just use doesPathExist+  when (exists1 || exists2) $+    throwIO (mkIOError alreadyExistsErrorType name Nothing Nothing)+  withTempDirectory (NativeFilePath.takeDirectory name) "darcs_new" $ \path -> do+    withCurrentDirectory path action+    renameDirectory path name
src/Darcs/Util/Path.hs view
@@ -28,8 +28,6 @@     , fn2fp     , fn2ps     , ps2fn-    , niceps2fn-    , fn2niceps     , breakOnDir     , normPath     , ownName@@ -37,6 +35,8 @@     , movedirfilename     , encodeWhite     , decodeWhite+    , encodeWhiteName+    , decodeWhiteName     , isParentOrEqOf     -- * AbsolutePath     , AbsolutePath@@ -76,7 +76,9 @@     -- * AnchoredPaths: relative paths within a Tree. All paths are     -- anchored at a certain root (this is usually the Tree root). They are     -- represented by a list of Names (these are just strict bytestrings).-    , Name(..)+    , Name+    , unsafeMakeName+    , eqAnycase     , AnchoredPath(..)     , anchoredRoot     , appendPath@@ -84,7 +86,7 @@     , isPrefix     , parent, parents, catPaths, flatten, makeName, appendToName     -- * Unsafe AnchoredPath functions.-    , floatBS, floatPath, replacePrefixPath ) where+    , floatPath, replacePrefixPath ) where  import Prelude () import Darcs.Prelude@@ -96,7 +98,7 @@     , intersect     , inits     )-import Data.Char ( isSpace, chr, ord )+import Data.Char ( isSpace, chr, ord, toLower ) import Control.Exception ( tryJust, bracket_ ) import Control.Monad ( when ) import System.IO.Error ( isDoesNotExistError )@@ -109,17 +111,14 @@ import System.FilePath( (</>), splitDirectories, normalise, dropTrailingPathSeparator ) import System.Posix.Files ( isDirectory, getSymbolicLinkStatus ) -import Darcs.Util.ByteString ( packStringToUTF8, unpackPSFromUTF8 )+import Darcs.Util.ByteString ( encodeLocale, decodeLocale ) import qualified Data.ByteString.Char8 as BC-import qualified Data.ByteString       as B  (ByteString)+import qualified Data.ByteString       as B  import Data.Binary import Darcs.Util.Global ( darcsdir ) import Darcs.Util.URL ( isAbsolute, isRelative, isSshNopath ) -#include "impossible.h"-- -- | FileName is an abstract type intended to facilitate the input and output of -- unicode filenames. newtype FileName = FN FilePath deriving ( Eq, Ord )@@ -140,21 +139,13 @@ fn2fp :: FileName -> FilePath fn2fp (FN fp) = fp -{-# INLINE niceps2fn #-}-niceps2fn :: B.ByteString -> FileName-niceps2fn = FN . decodeWhite . BC.unpack--{-# INLINE fn2niceps #-}-fn2niceps :: FileName -> B.ByteString-fn2niceps (FN fp) = BC.pack $ encodeWhite fp- {-# INLINE fn2ps #-} fn2ps :: FileName -> B.ByteString-fn2ps (FN fp) = packStringToUTF8 $ encodeWhite fp+fn2ps (FN fp) = encodeLocale $ encodeWhite fp  {-# INLINE ps2fn #-} ps2fn :: B.ByteString -> FileName-ps2fn ps = FN $ decodeWhite $ unpackPSFromUTF8 ps+ps2fn ps = FN $ decodeWhite $ decodeLocale ps  {-# INLINE sp2fn #-} sp2fn :: SubPath -> FileName@@ -190,6 +181,12 @@            _ -> error "malformed filename"        go (c:cs) acc modified = go cs (c:acc) modified +encodeWhiteName :: Name -> B.ByteString+encodeWhiteName = encodeLocale . encodeWhite . decodeLocale . unName++decodeWhiteName :: B.ByteString -> Name+decodeWhiteName = Name . encodeLocale . decodeWhite . decodeLocale+ ownName :: FileName -> FileName ownName (FN f) =  case breakLast '/' f of Nothing -> FN f                                           Just (_,f') -> FN f'@@ -568,7 +565,7 @@ -- AnchoredPath utilities -- -newtype Name = Name BC.ByteString  deriving (Eq, Show, Ord)+newtype Name = Name { unName :: B.ByteString } deriving (Eq, Show, Ord)  -- | This is a type of "sane" file paths. These are always canonic in the sense -- that there are no stray slashes, no ".." components and similar. They are@@ -586,7 +583,7 @@ appendPath :: AnchoredPath -> Name -> AnchoredPath appendPath (AnchoredPath p) n =     case n of-      (Name s) | s == BC.empty -> AnchoredPath p+      (Name s) | B.null s -> AnchoredPath p                | s == BC.pack "." -> AnchoredPath p                | otherwise -> AnchoredPath $ p ++ [n] @@ -608,14 +605,9 @@ -- 'FilePath'. Moreover, you can use @anchorPath \"\"@ to get a relative -- 'FilePath'. anchorPath :: FilePath -> AnchoredPath -> FilePath-anchorPath dir p = dir </> BC.unpack (flatten p)+anchorPath dir p = dir </> decodeLocale (flatten p) {-# INLINE anchorPath #-} --- | Unsafe. Only ever use on bytestrings that came from flatten on a--- pre-existing AnchoredPath.-floatBS :: BC.ByteString -> AnchoredPath-floatBS = AnchoredPath . map Name . takeWhile (not . BC.null) . BC.split '/'- flatten :: AnchoredPath -> BC.ByteString flatten (AnchoredPath []) = BC.singleton '.' flatten (AnchoredPath p) = BC.intercalate (BC.singleton '/')@@ -624,7 +616,7 @@ makeName :: String -> Name makeName ".." = error ".. is not a valid AnchoredPath component name" makeName n | '/' `elem` n = error "/ may not occur in a valid AnchoredPath component name"-           | otherwise = Name $ BC.pack n+           | otherwise = Name $ encodeLocale n  -- | Take a relative FilePath and turn it into an AnchoredPath. The operation -- is (relatively) unsafe. Basically, by using floatPath, you are testifying@@ -637,7 +629,7 @@ floatPath :: FilePath -> AnchoredPath floatPath = make . splitDirectories . normalise . dropTrailingPathSeparator   where make ["."] = AnchoredPath []-        make x = AnchoredPath $ map (Name . BC.pack) x+        make x = AnchoredPath $ map (Name . encodeLocale) x   anchoredRoot :: AnchoredPath@@ -653,11 +645,17 @@     | otherwise = AnchoredPath [] replacePrefixPath _ _ _ = AnchoredPath [] --- | Append a ByteString to the last Name of an AnchoredPath.+-- | Append a String to the last Name of an AnchoredPath. appendToName :: AnchoredPath -> String -> AnchoredPath appendToName (AnchoredPath p) s = AnchoredPath (init p++[Name finalname])-    where suffix = BC.pack s+    where suffix = encodeLocale s           finalname | suffix `elem` (BC.tails lastname) = lastname                     | otherwise = BC.append lastname suffix           lastname = case last p of                         Name name -> name++unsafeMakeName :: B.ByteString -> Name+unsafeMakeName = Name++eqAnycase :: Name -> Name -> Bool+eqAnycase (Name a) (Name b) = BC.map toLower a == BC.map toLower b
src/Darcs/Util/Printer.hs view
@@ -52,9 +52,10 @@     , insertBeforeLastline     , prefixLines     , invisiblePS, userchunkPS-    -- * Rendering-    , RenderMode(..)-    , renderString, renderStringWith, renderPS, renderPSWith+    -- * Rendering to 'String'+    , renderString, renderStringWith+    -- * Rendering to 'ByteString'+    , renderPS, renderPSWith     , renderPSs, renderPSsWith     -- * Printers     , Printers@@ -70,14 +71,14 @@     , blueText, redText, greenText, magentaText, cyanText     , colorText     , lineColor-    -- * IO+    -- * IO, uses 'Data.ByteString.hPut' for output     , hPutDoc,     hPutDocLn,     putDoc,     putDocLn     , hPutDocWith, hPutDocLnWith, putDocWith, putDocLnWith     , hPutDocCompr     , debugDocLn     , ePutDocLn     , errorDoc-    -- * Unsafe constructors+    -- * TODO: It is unclear what is unsafe about these constructors     , unsafeText, unsafeBoth, unsafeBothText, unsafeChar     , unsafePackedString     ) where@@ -85,17 +86,12 @@ import Prelude () import Darcs.Prelude -import Control.Exception ( throwIO, ErrorCall(..) ) import Data.String ( IsString(..) )-import Data.List (intersperse)-import Data.Monoid ( (<>) )-import GHC.Stack ( currentCallStack )-import System.IO (Handle, stdout, stderr, hPutStr)-import System.IO.Unsafe ( unsafePerformIO )-import qualified Data.ByteString as B (ByteString, hPut, concat)-import qualified Data.ByteString.Char8 as BC (unpack, pack, singleton)+import System.IO ( Handle, stdout, stderr )+import qualified Data.ByteString as B ( ByteString, hPut, concat )+import qualified Data.ByteString.Char8 as BC ( singleton ) -import Darcs.Util.ByteString ( linesPS, encodeLocale, gzWriteHandle )+import Darcs.Util.ByteString ( linesPS, decodeLocale, encodeLocale, gzWriteHandle ) import Darcs.Util.Global ( debugMessage )  -- | A 'Printable' is either a String, a packed string, or a chunk of@@ -146,74 +142,71 @@  -- | Fail with a stack trace and the given 'Doc' as error message. errorDoc :: Doc -> a-errorDoc x = unsafePerformIO $ do-   stack <- currentCallStack-   throwIO $ ErrorCall $ renderString Encode $ x $$ vcat (map text stack)+errorDoc x = error $ renderString x --- | 'putDocWith' puts a doc on stdout using the given printer.+-- | 'putDocWith' puts a 'Doc' on stdout using the given printer. putDocWith :: Printers -> Doc -> IO ()-putDocWith prs = hPutDocWith prs Encode stdout+putDocWith prs = hPutDocWith prs stdout --- | 'putDocLnWith' puts a doc, followed by a newline on stdout using+-- | 'putDocLnWith' puts a 'Doc', followed by a newline on stdout using -- the given printer. putDocLnWith :: Printers -> Doc -> IO ()-putDocLnWith prs = hPutDocLnWith prs Encode stdout+putDocLnWith prs = hPutDocLnWith prs stdout --- | 'putDoc' puts a doc on stdout using the simple printer 'simplePrinters'.+-- | 'putDoc' puts a 'Doc' on stdout using the simple printer 'simplePrinters'. putDoc :: Doc -> IO ()-putDoc = hPutDoc Encode stdout+putDoc = hPutDoc stdout --- | 'putDocLn' puts a doc, followed by a newline on stdout using+-- | 'putDocLn' puts a 'Doc', followed by a newline on stdout using -- 'simplePrinters' putDocLn :: Doc -> IO ()-putDocLn = hPutDocLn Encode stdout+putDocLn = hPutDocLn stdout --- | 'eputDocLn' puts a doc, followed by a newline to stderr using+-- | 'eputDocLn' puts a 'Doc', followed by a newline to stderr using -- 'simplePrinters'. Like putDocLn, it encodes with the user's locale. -- This function is the recommended way to output messages that should -- be visible to users on the console, but cannot (or should not) be -- silenced even when --quiet is in effect. ePutDocLn :: Doc -> IO ()-ePutDocLn = hPutDocLn Encode stderr+ePutDocLn = hPutDocLn stderr --- | 'hputDocWith' puts a doc on the given handle using the given printer.-hPutDocWith :: Printers -> RenderMode -> Handle -> Doc -> IO ()-hPutDocWith prs target h d = hPrintPrintables target h (renderWith (prs h) d)+-- | 'hputDocWith' puts a 'Doc' on the given handle using the given printer.+hPutDocWith :: Printers -> Handle -> Doc -> IO ()+hPutDocWith prs h d = hPrintPrintables h (renderWith (prs h) d) --- | 'hputDocLnWith' puts a doc, followed by a newline on the given+-- | 'hputDocLnWith' puts a 'Doc', followed by a newline on the given -- handle using the given printer.-hPutDocLnWith :: Printers -> RenderMode -> Handle -> Doc -> IO ()-hPutDocLnWith prs target h d = hPutDocWith prs target h (d <?> newline)+hPutDocLnWith :: Printers -> Handle -> Doc -> IO ()+hPutDocLnWith prs h d = hPutDocWith prs h (d <?> newline) --- |'hputDoc' puts a doc on the given handle using 'simplePrinters'-hPutDoc :: RenderMode -> Handle -> Doc -> IO ()+-- |'hputDoc' puts a 'Doc' on the given handle using 'simplePrinters'+hPutDoc :: Handle -> Doc -> IO () hPutDoc = hPutDocWith simplePrinters --- | 'hputDocLn' puts a doc, followed by a newline on the given handle using+-- | 'hputDocLn' puts a 'Doc', followed by a newline on the given handle using -- 'simplePrinters'.-hPutDocLn :: RenderMode -> Handle -> Doc -> IO ()+hPutDocLn :: Handle -> Doc -> IO () hPutDocLn = hPutDocLnWith simplePrinters  -- | like 'hPutDoc' but with compress data before writing-hPutDocCompr :: RenderMode -> Handle -> Doc -> IO ()-hPutDocCompr target h = gzWriteHandle h . renderPSs target+hPutDocCompr :: Handle -> Doc -> IO ()+hPutDocCompr h = gzWriteHandle h . renderPSs  -- | Write a 'Doc' to stderr if debugging is turned on. debugDocLn :: Doc -> IO ()-debugDocLn = debugMessage . renderString Standard+debugDocLn = debugMessage . renderString  -- | @'hPrintPrintables' h@ prints a list of 'Printable's to the handle @h@-hPrintPrintables :: RenderMode -> Handle -> [Printable] -> IO ()-hPrintPrintables target h = mapM_ (hPrintPrintable target h)+-- It uses binary output of 'ByteString's. If these not available,+-- converts according to locale.+hPrintPrintables :: Handle -> [Printable] -> IO ()+hPrintPrintables h = mapM_ (hPrintPrintable h)  -- | @'hPrintPrintable' h@ prints a 'Printable' to the handle @h@.-hPrintPrintable :: RenderMode -> Handle -> Printable -> IO ()-hPrintPrintable Standard h (S ps) = hPutStr h ps-hPrintPrintable Encode  h (S ps) = B.hPut h (encodeLocale ps)-hPrintPrintable Standard h (PS ps) = B.hPut h ps-hPrintPrintable Encode  h (PS ps) = B.hPut h ps-hPrintPrintable Standard h (Both _ ps) = B.hPut h ps-hPrintPrintable Encode  h (Both _ ps) = B.hPut h ps+hPrintPrintable :: Handle -> Printable -> IO ()+hPrintPrintable h (S ps) = B.hPut h (encodeLocale ps)+hPrintPrintable h (PS ps) = B.hPut h ps+hPrintPrintable h (Both _ ps) = B.hPut h ps  -- | A 'Doc' is a bit of enriched text. 'Doc's are concatenated using -- '<>' from class 'Monoid', which is right-associative.@@ -224,22 +217,7 @@ instance IsString Doc where    fromString = text --- TODO this is a rather ad-hoc hack that further complicates--- some already confusing code. We should find a more general--- solution. See the discussion on issue1639.--- | Used when rendering a 'Doc' to indicate if the result--- should be encoded to the current locale or left alone.--- In practice this only affects output when a relevant--- DARCS_DONT_ESCAPE_XXX option is set (see Darcs.Util.Printer.Color)--- If in doubt, choose 'Standard'.-data RenderMode =-      Encode       -- ^Encode Strings with the current locale.-                   -- At present ByteStrings are assumed to be in-                   -- UTF8 and are left alone, so will be mis-encoded-                   -- in non-UTF8 locales.-    | Standard     -- ^Don't encode.---- | The State associated with a doc. Contains a set of printers for each+-- | The State associated with a 'Doc'. Contains a set of printers for each -- hanlde, and the current prefix of the document. data St = St { printers :: !Printers',                currentPrefix :: !([Printable] -> [Printable]) }@@ -259,54 +237,50 @@ data Color = Blue | Red | Green | Cyan | Magenta  -- | 'Document' is a wrapper around '[Printable] -> [Printable]' which allows--- for empty Documents. The simplest 'Documents' are built from 'String's--- using 'text'.+-- to handle the special case of an empty 'Document' in a non-uniform manner.+-- The simplest 'Documents' are built from 'String's using 'text'. data Document = Document ([Printable] -> [Printable])               | Empty  -- | renders a 'Doc' into a 'String' with control codes for the--- special features of the doc.-renderString :: RenderMode -> Doc -> String+-- special features of the 'Doc'.+renderString :: Doc -> String renderString = renderStringWith simplePrinters'  -- | renders a 'Doc' into a 'String' using a given set of printers.-renderStringWith :: Printers' -> RenderMode -> Doc -> String-renderStringWith prs target d = concatMap (toString target) $ renderWith prs d-    where toString Standard (S s) = s-          toString Encode  (S s) = BC.unpack . encodeLocale $ s-          toString Standard (PS ps) = BC.unpack ps-          toString Encode  (PS ps) = BC.unpack ps-          toString Standard (Both s _) = s-          toString Encode  (Both s _) = BC.unpack . encodeLocale $ s+-- If content is only available as 'ByteString', decode according to+-- the current locale.+renderStringWith :: Printers' -> Doc -> String+renderStringWith prs d = concatMap (toString) $ renderWith prs d+    where toString (S s) = s+          toString (PS ps) = decodeLocale ps+          toString (Both s _) = s  -- | renders a 'Doc' into 'B.ByteString' with control codes for the -- special features of the Doc. See also 'readerString'.-renderPS :: RenderMode -> Doc -> B.ByteString+renderPS :: Doc -> B.ByteString renderPS = renderPSWith simplePrinters'  -- | renders a 'Doc' into a list of 'PackedStrings', one for each line.-renderPSs :: RenderMode -> Doc -> [B.ByteString]+renderPSs :: Doc -> [B.ByteString] renderPSs = renderPSsWith simplePrinters' --- | renders a doc into a 'B.ByteString' using a given set of printers.-renderPSWith :: Printers' -> RenderMode -> Doc -> B.ByteString-renderPSWith prs target d = B.concat $ renderPSsWith prs target d+-- | renders a 'Doc' into a 'B.ByteString' using a given set of printers.+renderPSWith :: Printers' -> Doc -> B.ByteString+renderPSWith prs d = B.concat $ renderPSsWith prs d  -- | renders a 'Doc' into a list of 'PackedStrings', one for each--- chunk of text that was added to the doc, using the given set of+-- chunk of text that was added to the 'Doc', using the given set of -- printers.-renderPSsWith :: Printers' -> RenderMode -> Doc -> [B.ByteString]-renderPSsWith prs target d = map (toPS target) $ renderWith prs d-    where toPS Standard (S s)        = BC.pack s-          toPS Encode  (S s)        = encodeLocale s-          toPS Standard (PS ps)      = ps-          toPS Encode  (PS ps)      = ps-          toPS Standard (Both _ ps)  = ps-          toPS Encode  (Both _ ps)  = ps+renderPSsWith :: Printers' -> Doc -> [B.ByteString]+renderPSsWith prs d = map toPS $ renderWith prs d+    where toPS (S s)        = encodeLocale s+          toPS (PS ps)      = ps+          toPS (Both _ ps)  = ps  -- | renders a 'Doc' into a list of 'Printables' using a set of -- printers. Each item of the list corresponds to a string that was--- added to the doc.+-- added to the 'Doc'. renderWith :: Printers' -> Doc -> [Printable] renderWith ps (Doc d) = case d (initState ps) of                         Empty -> []@@ -327,21 +301,16 @@ -- of the Doc abstraction prefixLines :: Doc -> Doc -> Doc prefixLines prefixer prefixee =-   vcat $ map (prefixer <+>) $ map packedString $ linesPS $-   -- this will just get round-tripped back into a Doc,-   renderPS Standard prefixee+  vcat $ map (prefixer <+>) $ map packedString $ linesPS $ renderPS prefixee  -- TODO try to find another way to do this, it's rather a violation -- of the Doc abstraction insertBeforeLastline :: Doc -> Doc -> Doc insertBeforeLastline a b =-   -- as this will just get round-tripped back into a Doc,-   -- we use 'Standard' as the Target type so the encoding-   -- is left alone-   case reverse $ map packedString $ linesPS $ renderPS Standard a of-   (ll:ls) -> vcat (reverse ls) $$ b $$ ll-   [] -> error "empty Doc given as first argument of Printer.insert_before_last_line"-+  case reverse $ map packedString $ linesPS $ renderPS a of+    (ll:ls) -> vcat (reverse ls) $$ b $$ ll+    [] ->+      error "empty Doc given as first argument of Printer.insert_before_last_line"  lineColor :: Color -> Doc -> Doc lineColor c d = Doc $ \st -> case lineColorT (printers st) c d of@@ -350,7 +319,7 @@ hiddenPrefix :: String -> Doc -> Doc hiddenPrefix s (Doc d) =     Doc $ \st -> let pr = printers st-                     p = S (renderStringWith pr Standard $ hiddenText s)+                     p = S (renderStringWith pr $ hiddenText s)                      st' = st { currentPrefix = currentPrefix st . (p:) }                  in case d st' of                       Document d'' -> Document $ (p:) . d''@@ -364,7 +333,7 @@ -- | 'unsafeBothText' builds a 'Doc' from a 'String'. The string is stored in the -- Doc as both a String and a 'B.ByteString'. unsafeBothText :: String -> Doc-unsafeBothText s = Doc $ simplePrinter (Both s (BC.pack s))+unsafeBothText s = Doc $ simplePrinter (Both s (encodeLocale s))  -- | 'packedString' builds a 'Doc' from a 'B.ByteString' using 'printable' packedString :: B.ByteString -> Doc@@ -478,6 +447,7 @@  infixr 6 `append` infixr 6 <+>+infixr 5 `vplus` infixr 5 $$  -- | The empty 'Doc'@@ -487,6 +457,9 @@ doc :: ([Printable] -> [Printable]) -> Doc doc f = Doc $ const $ Document f +instance Semigroup Doc where+  (<>) = append+ -- | 'mappend' ('<>') is concatenation, 'mempty' is the 'empty' 'Doc' instance Monoid Doc where   mempty = empty@@ -511,7 +484,7 @@                                                      Empty -> s                                                      Document bf -> bf s) --- | @a '<+>' b@ is @a@ followed by a space, then @b@+-- | @a '<+>' b@ is @a@ followed by @b@ with a space in between if both are non-empty (<+>) :: Doc -> Doc -> Doc Doc a <+> Doc b =     Doc $ \st -> case a st of@@ -533,15 +506,25 @@                         where pf = currentPrefix st                               sf = lineColorS $ printers st +-- | @vplus a b@ is @a@ above @b@ with an empty line in between if both are non-empty+vplus :: Doc -> Doc -> Doc+Doc a `vplus` Doc b =+   Doc $ \st -> case a st of+                Empty -> b st+                Document af ->+                    Document (\s -> af $ case b st of+                                         Empty -> s+                                         Document bf -> sf (newlineP:newlineP:pf (bf s)))+                        where pf = currentPrefix st+                              sf = lineColorS $ printers st+ -- | Pile 'Doc's vertically vcat :: [Doc] -> Doc-vcat [] = empty-vcat ds = foldr1 ($$) ds+vcat = foldr ($$) empty  -- | Pile 'Doc's vertically, with a blank line in between vsep :: [Doc] -> Doc-vsep [] = empty-vsep ds = foldr1 ($$) $ intersperse (text "") ds+vsep = foldr vplus empty  -- | Concatenate 'Doc's horizontally hcat :: [Doc] -> Doc
src/Darcs/Util/Printer/Color.hs view
@@ -8,18 +8,16 @@ import Darcs.Prelude  import Darcs.Util.Printer-    ( Printer, Printers, Printers'(..), Printable(..), Color(..), RenderMode(..)+    ( Printer, Printers, Printers'(..), Printable(..), Color(..)     , invisiblePrinter, (<>), (<?>), Doc(Doc,unDoc), unsafeBothText, simplePrinter, hcat     , unsafeText, unsafePackedString     , renderStringWith, prefix     ) -import Control.Monad ( liftM )-import Control.Exception ( catch, IOException ) import Debug.Trace ( trace ) import Data.Char ( isAscii, isPrint, isSpace, isControl, ord, chr ) import Data.Bits ( bit, xor )-import System.Environment ( getEnv )+import System.Environment ( lookupEnv ) import qualified Data.ByteString.Char8 as BC (unpack, any, last, spanEnd) import qualified Data.ByteString       as B (null, init) import System.IO.Unsafe ( unsafePerformIO )@@ -35,20 +33,19 @@ cr     = unsafeBothText "\r"  errorDoc :: Doc -> a-errorDoc = error . showDoc Encode+errorDoc = error . showDoc  traceDoc :: Doc -> a -> a-traceDoc d = trace (showDoc Encode d)+traceDoc d = trace (showDoc d)  assertDoc :: Maybe Doc -> a -> a assertDoc Nothing x = x assertDoc (Just e) _ = errorDoc e -showDoc :: RenderMode -> Doc -> String+showDoc :: Doc -> String showDoc = renderStringWith (fancyPrinters stderr) --- policy--- | the 'Policy' type is a record containing the variables which control+-- | The 'Policy' type is a record containing the variables which control -- how 'Doc's will be rendered on some output. data Policy = Policy { poColor :: Bool    -- ^ overall use of color                      , poEscape :: Bool   -- ^ overall use of escaping@@ -74,8 +71,8 @@      envDontEscapeAnything  <- getEnvBool "DARCS_DONT_ESCAPE_ANYTHING"     envDontEscapeIsprint   <- getEnvBool "DARCS_DONT_ESCAPE_ISPRINT"-    envUseIsprint          <- getEnvBool "DARCS_USE_ISPRINT" -- for backwards-compatibility-    envDontEscape8bit      <- getEnvBool "DARCS_DONT_ESCAPE_8BIT"+    envUseIsprint          <- getEnvBool "DARCS_USE_ISPRINT"+    envEscape8bit      <- getEnvBool "DARCS_ESCAPE_8BIT"      envDontEscapeExtra  <- getEnvString "DARCS_DONT_ESCAPE_EXTRA"     envEscapeExtra      <- getEnvString "DARCS_ESCAPE_EXTRA"@@ -95,7 +92,7 @@                     poEscape   = not envDontEscapeAnything,                     poLineColor= doColor && envDoColorLines,                     poIsprint  = envDontEscapeIsprint || envUseIsprint,-                    po8bit     = envDontEscape8bit,+                    po8bit     = not envEscape8bit,                     poNoEscX   = envDontEscapeExtra,                     poEscX     = envEscapeExtra,                     poTrailing = not envDontEscapeTrailingSpace,@@ -105,9 +102,8 @@                     poSpace = False                   }  where-  getEnvBool s = (/= "0") `liftM` safeGetEnv s-  safeGetEnv s = getEnv s `catch` \(_ :: IOException) -> return "0"-  getEnvString s = getEnv s `catch` \(_ :: IOException) -> return ""+  getEnvBool s = maybe False (/= "0") <$> lookupEnv s+  getEnvString s = maybe "" id <$> lookupEnv s   {-@@ -336,47 +332,47 @@  environmentHelpEscape :: ([String], [String]) environmentHelpEscape = (["DARCS_DONT_ESCAPE_ANYTHING",-                          "DARCS_DONT_ESCAPE_ISPRINT",-                          "DARCS_DONT_ESCAPE_8BIT",                           "DARCS_DONT_ESCAPE_EXTRA",-                          "DARCS_ESCAPE_EXTRA"],[+                          "DARCS_ESCAPE_EXTRA",+                          "DARCS_DONT_ESCAPE_ISPRINT",+                          "DARCS_ESCAPE_8BIT"],[   "Darcs needs to escape certain characters when printing patch contents to",-  "a terminal. Characters like backspace can otherwise hide patch content",-  "from the user, and other character sequences can even in some cases",-  "redirect commands to the shell if the terminal allows it.",+  "a terminal, depending on the encoding specified in your locale setting.",   "",-  "By default darcs will only allow printable 7-bit ASCII",-  "characters (including space), and the two control characters tab and",-  "newline. All other octets are printed in quoted form (as `^<control letter>`",-  "or `\\<hex code>`).",+  "By default, darcs assumes that your locale encoding is ASCII compatible.",+  "This includes UTF-8 and some 8-bit encodings like ISO/IEC-8859 (including",+  "its variants). Since ASCII contains control characters like backspace",+  "(which could hide patch content from the user when printed literally to",+  "the terminal), and even ones that may introduce security risks such as",+  "redirecting commands to the shell, darcs needs to escape such characters.",+  "They are printed as `^<control letter>` or `\\<hex code>`. Darcs also uses",+  "special markup for line endings that are preceeded by white space, since",+  "the white space would otherwise not be recognizable.",   "",-  "Darcs has some limited support for locales. If the system's locale is a ",-  "single-byte character encoding, like the Latin encodings, you can set the",-  "environment variable DARCS_DONT_ESCAPE_ISPRINT to 1 and darcs will display",-  "all the printables in the current system locale instead of just the ASCII",-  "ones. NOTE: This curently does not work on some architectures if darcs",-  "is compiled with GHC 6.4 or later. Some non-ASCII control characters might",-  "be printed and can possibly spoof the terminal.",+  "If you use an encoding that is not ASCII compatible, things are somewhat",+  "less smooth. Such encodings include UTF-16 and UTF-32, as well as many of",+  "the encodings that became obsolete with unicode. In this case you have two",+  "options: you can set DARCS_DONT_ESCAPE_ANYTHING to 1. Then everything that",+  "doesn't flip code sets should work, and so will all the bells and whistles",+  "in your terminal. This environment variable can also be handy if you pipe",+  "the output to a pager or external filter that knows better than darcs how to",+  "handle your encoding. Note that all escaping, including the special escaping",+  "of any line ending spaces, will be turned off by this setting.",   "",-  "For multi-byte character encodings things are less smooth. UTF-8 will",-  "work if you set DARCS_DONT_ESCAPE_8BIT to 1, but non-printables outside",-  "the 7-bit ASCII range are no longer escaped. E.g., the extra control",-  "characters from Latin-1 might leave your terminal at the mercy of the",-  "patch contents. Space characters outside the 7-bit ASCII range are no",-  "longer recognized and will not be properly escaped at line endings.",+  "Another possibility is to explicitly tell darcs to not escape or escape",+  "certain bytes, using DARCS_DONT_ESCAPE_EXTRA and DARCS_ESCAPE_EXTRA. Their",+  "values should be strings consisting of the verbatim bytes in question. The",+  "do-escapes take precedence over the dont-escapes. Space characters are still",+  "escaped at line endings though. The special environment variable",+  "DARCS_DONT_ESCAPE_TRAILING_CR turns off escaping of carriage return last on",+  "the line (DOS style).",   "",-  "As a last resort you can set DARCS_DONT_ESCAPE_ANYTHING to 1. Then",-  "everything that doesn't flip code sets should work, and so will all the",-  "bells and whistles in your terminal. This environment variable can also",-  "be handy if you pipe the output to a pager or external filter that knows",-  "better than darcs how to handle your encoding. Note that all escaping,",-  "including the special escaping of any line ending spaces, will be turned",-  "off by this setting.",+  "For historical reasons, darcs also supports DARCS_DONT_ESCAPE_ISPRINT and",+  "DARCS_USE_ISPRINT (which are synonyms). These make sense only for 8-bit",+  "encodings like ISO-8859 and are no longer needed since nowadays darcs does",+  "the right thing here by default.",   "",-  "There are two environment variables you can set to explicitly tell darcs",-  "to not escape or escape octets. They are DARCS_DONT_ESCAPE_EXTRA and",-  "DARCS_ESCAPE_EXTRA. Their values should be strings consisting of the",-  "verbatim octets in question. The do-escapes take precedence over the",-  "dont-escapes. Space characters are still escaped at line endings though.",-  "The special environment variable DARCS_DONT_ESCAPE_TRAILING_CR turns off",-  "escaping of carriage return last on the line (DOS style)."])+  "Finally, if you are in a highly security sensitive situation (or just",+  "paranoid for other reasons), you can set DARCS_ESCAPE_8BIT to 1. This will",+  "cause darcs to escape every non-ASCII byte in addition to ASCII control",+  "characters."])
src/Darcs/Util/Progress.hs view
@@ -1,6 +1,3 @@-{-# LANGUAGE CPP #-}-- -- | -- Module      : Darcs.Util.Progress -- Copyright   : 2008 David Roundy@@ -30,7 +27,7 @@   import Prelude ()-import Darcs.Prelude hiding ( lookup )+import Darcs.Prelude  import Prelude hiding (lookup) 
src/Darcs/Util/Ssh.hs view
@@ -50,7 +50,7 @@  import Darcs.Util.SignalHandler ( catchNonSignal ) import Darcs.Util.URL ( SshFilePath, sshFilePathOf, sshUhost, sshRepo, sshFile )-import Darcs.Util.Text ( breakCommand )+import Darcs.Util.Text ( breakCommand, showCommandLine ) import Darcs.Util.Exception ( prettyException, catchall ) import Darcs.Util.Exec ( readInteractiveProcess, ExecException(..), Redirect(AsIs) ) import Darcs.Util.Progress ( withoutProgress, debugMessage, debugFail )@@ -177,9 +177,9 @@ newSshConnection rdarcs sshfp = do   (sshcmd,sshargs_) <- getSSH SSH   debugMessage $ "Starting new ssh connection to " ++ sshUhost sshfp-  let sshargs = sshargs_ ++ [sshUhost sshfp, rdarcs,-                             "transfer-mode","--repodir",sshRepo sshfp]-  debugMessage $ unwords (sshcmd : sshargs)+  let sshargs = sshargs_ ++ ["--", sshUhost sshfp, rdarcs,+                             "transfer-mode", "--repodir", sshRepo sshfp]+  debugMessage $ "Exec: " ++ showCommandLine (sshcmd:sshargs)   (i,o,e,_) <- runInteractiveProcess sshcmd sshargs Nothing Nothing   do     hSetBinaryMode i True@@ -245,7 +245,8 @@         -- remote 'darcs transfer-mode' does not work => use scp         let u = escape_dollar $ sshFilePathOf src         (scpcmd, args) <- getSSH SCP-        let scp_args = filter (/="-q") args ++ [u, dest]+        let scp_args = filter (/="-q") args ++ ["--", u, dest]+        debugMessage $ "Exec: " ++ showCommandLine (scpcmd:scp_args)         (r, scp_err) <- readInteractiveProcess scpcmd scp_args         unless (r == ExitSuccess) $           throwIO $ ExecException scpcmd scp_args (AsIs,AsIs,AsIs) scp_err
src/Darcs/Util/Text.hs view
@@ -13,6 +13,7 @@     , breakCommand     , quote     , pathlist+    , showCommandLine     ) where  import Prelude ()@@ -21,7 +22,7 @@ import Control.Arrow ( first ) import Data.List ( intercalate ) -import Darcs.Util.Printer ( Doc, (<>), renderString, RenderMode(..), quoted, hsep )+import Darcs.Util.Printer ( Doc, (<>), renderString, quoted, hsep )  sentence :: Doc -> Doc sentence = (<> ".")@@ -56,7 +57,7 @@  -- | Quote a string for screen output. quote :: String -> String-quote = renderString Encode . quoted+quote = renderString . quoted  -- | Format a list of 'FilePath's as quoted text. It deliberately refuses to -- use English.andClauses but rather separates the quoted strings only with a@@ -64,3 +65,10 @@ -- another shell command. pathlist :: [FilePath] -> Doc pathlist paths = hsep (map quoted paths)++-- | Produce a String composed by the elements of [String] each enclosed in+-- double quotes.+showCommandLine :: [String] -> String+showCommandLine strings = showCommandLine' ['"'] strings+            where showCommandLine' x xs =+                        x ++ intercalate (x ++ " " ++ x) xs ++ x
src/Darcs/Util/Tree.hs view
@@ -2,7 +2,6 @@ -- --  BSD3 {-# LANGUAGE ScopedTypeVariables, MultiParamTypeClasses, FlexibleInstances, BangPatterns #-}-{-# LANGUAGE CPP #-}  -- | The abstract representation of a Tree and useful abstract utilities to -- handle those.@@ -32,13 +31,15 @@     , modifyTree, updateTree, partiallyUpdateTree, updateSubtrees, overlay     , addMissingHashes ) where +import Prelude ()+import Darcs.Prelude hiding ( filter )+ import Control.Exception( catch, IOException )-import Prelude hiding( lookup, filter, all, (<$>) ) import Darcs.Util.Path import Darcs.Util.Hash -import qualified Data.ByteString.Lazy.Char8 as BL-import qualified Data.ByteString.Char8 as BS+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString as B import qualified Data.Map as M  import Data.Maybe( catMaybes, isNothing )@@ -47,8 +48,6 @@ import Control.Monad( filterM ) import Control.Applicative( (<$>) ) -#include "impossible.h"- -------------------------------- -- Tree, Blob and friends --@@ -94,7 +93,7 @@ itemType (SubTree _) = TreeType itemType (Stub _ _) = TreeType -emptyTree :: (Monad m) => Tree m+emptyTree :: Tree m emptyTree = Tree { items = M.empty                  , treeHash = NoHash } @@ -104,14 +103,14 @@ makeBlob :: (Monad m) => BL.ByteString -> Blob m makeBlob str = Blob (return str) (sha256 str) -makeBlobBS :: (Monad m) => BS.ByteString -> Blob m+makeBlobBS :: (Monad m) => B.ByteString -> Blob m makeBlobBS s' = let s = BL.fromChunks [s'] in Blob (return s) (sha256 s) -makeTree :: (Monad m) => [(Name,TreeItem m)] -> Tree m+makeTree :: [(Name,TreeItem m)] -> Tree m makeTree l = Tree { items = M.fromList l                   , treeHash = NoHash } -makeTreeWithHash :: (Monad m) => [(Name,TreeItem m)] -> Hash -> Tree m+makeTreeWithHash :: [(Name,TreeItem m)] -> Hash -> Tree m makeTreeWithHash l h = Tree { items = M.fromList l                             , treeHash = h } @@ -255,7 +254,7 @@ -- | Given two Trees, a @guide@ and a @tree@, produces a new Tree that is a -- identical to @tree@, but only has those items that are present in both -- @tree@ and @guide@. The @guide@ Tree may not contain any stubs.-restrict :: (FilterTree t m, Monad n) => Tree n -> t m -> t m+restrict :: (FilterTree t m) => Tree n -> t m -> t m restrict guide tree = filter accept tree     where accept path item =               case (find guide path, item) of@@ -312,7 +311,7 @@ -- not share any identical subtrees. They are derived from the first and second -- parameters respectively and they are always fully expanded. It might be -- advantageous to feed the result into 'zipFiles' or 'zipTrees'.-diffTrees :: forall m. (Functor m, Monad m) => Tree m -> Tree m -> m (Tree m, Tree m)+diffTrees :: forall m. (Monad m) => Tree m -> Tree m -> m (Tree m, Tree m) diffTrees left right =             if treeHash left `match` treeHash right                then return (emptyTree, emptyTree)@@ -398,7 +397,7 @@             bug $ "descending in modifyTree, case = Nothing, path = " ++ show p_  countmap :: forall a k. M.Map k a -> Int-countmap = M.fold (\_ i -> i + 1) 0+countmap = M.foldr (\_ i -> i + 1) 0  updateSubtrees :: (Tree m -> Tree m) -> Tree m -> Tree m updateSubtrees fun t =@@ -409,11 +408,11 @@         update (_, Stub _ _) = bug "Stubs not supported in updateTreePostorder"  -- | Does /not/ expand the tree.-updateTree :: (Functor m, Monad m) => (TreeItem m -> m (TreeItem m)) -> Tree m -> m (Tree m)+updateTree :: (Monad m) => (TreeItem m -> m (TreeItem m)) -> Tree m -> m (Tree m) updateTree fun t = partiallyUpdateTree fun (\_ _ -> True) t  -- | Does /not/ expand the tree.-partiallyUpdateTree :: (Functor m, Monad m) => (TreeItem m -> m (TreeItem m))+partiallyUpdateTree :: (Monad m) => (TreeItem m -> m (TreeItem m))                        -> (AnchoredPath -> TreeItem m -> Bool) -> Tree m -> m (Tree m) partiallyUpdateTree fun predi t' = go (AnchoredPath []) t'   where go path t = do@@ -433,7 +432,7 @@ -- object, nor it is allowed for the overlay to add new objects to base.  This -- means that the overlay Tree should be a subset of the base Tree (although -- any extraneous items will be ignored by the implementation).-overlay :: (Functor m, Monad m) => Tree m -> Tree m -> Tree m+overlay :: (Monad m) => Tree m -> Tree m -> Tree m overlay base over = Tree { items = M.fromList immediate                          , treeHash = NoHash }     where immediate = [ (n, get n) | (n, _) <- listImmediate base ]@@ -448,7 +447,7 @@                     (Just x, _) -> x                     (_, _) -> bug $ "Unexpected case in overlay at get " ++ show n ++ "." -addMissingHashes :: (Monad m, Functor m) => (TreeItem m -> m Hash) -> Tree m -> m (Tree m)+addMissingHashes :: (Monad m) => (TreeItem m -> m Hash) -> Tree m -> m (Tree m) addMissingHashes make = updateTree update -- use partiallyUpdateTree here     where update (SubTree t) = make (SubTree t) >>= \x -> return $ SubTree (t { treeHash = x })           update (File blob@(Blob con NoHash)) =
src/Darcs/Util/Tree/Hashed.hs view
@@ -36,10 +36,10 @@ import Codec.Compression.GZip( decompress, compress ) import Control.Applicative( (<$>) ) -import qualified Data.ByteString.Char8 as BS8-import qualified Data.ByteString.Lazy.Char8 as BL8+import qualified Data.ByteString.Char8 as BC+import qualified Data.ByteString.Lazy.Char8 as BLC import qualified Data.ByteString.Lazy as BL-import qualified Data.ByteString as BS+import qualified Data.ByteString as B  import Data.List( sortBy ) import Data.Maybe( fromJust, isJust )@@ -48,6 +48,7 @@ import Darcs.Util.Path import Darcs.Util.ByteString ( FileSegment, readSegment ) import Darcs.Util.Hash+import Darcs.Util.Progress ( debugMessage ) import Darcs.Util.Tree import Darcs.Util.Tree.Monad @@ -55,18 +56,15 @@ -- Utilities for coping with the darcs directory format. -- -darcsEncodeWhiteBS :: BS8.ByteString -> BS8.ByteString-darcsEncodeWhiteBS = BS8.pack . encodeWhite . BS8.unpack--decodeDarcsHash :: BS8.ByteString -> Hash-decodeDarcsHash bs = case BS8.split '-' bs of-                       [s, h] | BS8.length s == 10 -> decodeBase16 h+decodeDarcsHash :: BC.ByteString -> Hash+decodeDarcsHash bs = case BC.split '-' bs of+                       [s, h] | BC.length s == 10 -> decodeBase16 h                        _ -> decodeBase16 bs -decodeDarcsSize :: BS8.ByteString -> Maybe Int-decodeDarcsSize bs = case BS8.split '-' bs of-                       [s, _] | BS8.length s == 10 ->-                                  case reads (BS8.unpack s) of+decodeDarcsSize :: BC.ByteString -> Maybe Int+decodeDarcsSize bs = case BC.split '-' bs of+                       [s, _] | BC.length s == 10 ->+                                  case reads (BC.unpack s) of                                     [(x, _)] -> Just x                                     _ -> Nothing                        _ -> Nothing@@ -78,41 +76,41 @@     where prefix Nothing = ""           prefix (Just s') = formatSize s' ++ "-"           formatSize s' = let n = show s' in replicate (10 - length n) '0' ++ n-          hash = BS8.unpack (encodeBase16 h)+          hash = BC.unpack (encodeBase16 h)  ---------------------------------------------- -- Darcs directory format. -- -darcsFormatDir :: Tree m -> Maybe BL8.ByteString-darcsFormatDir t = BL8.fromChunks . concat <$>+darcsFormatDir :: Tree m -> Maybe BLC.ByteString+darcsFormatDir t = BLC.fromChunks . concat <$>                        mapM string (sortBy cmp $ listImmediate t)-    where cmp (Name a, _) (Name b, _) = compare a b-          string (Name name, item) =+    where cmp (a, _) (b, _) = compare a b+          string (name, item) =               do header <- case item of-                             File _ -> Just $ BS8.pack "file:\n"-                             _ -> Just $ BS8.pack "directory:\n"+                             File _ -> Just $ BC.pack "file:\n"+                             _ -> Just $ BC.pack "directory:\n"                  hash <- case itemHash item of                            NoHash -> Nothing                            x -> Just $ encodeBase16 x                  return   [ header-                          , darcsEncodeWhiteBS name-                          , BS8.singleton '\n'-                          , hash, BS8.singleton '\n' ]+                          , encodeWhiteName name+                          , BC.singleton '\n'+                          , hash, BC.singleton '\n' ] -darcsParseDir :: BL8.ByteString -> [(ItemType, Name, Maybe Int, Hash)]-darcsParseDir content = parse (BL8.split '\n' content)+darcsParseDir :: BLC.ByteString -> [(ItemType, Name, Maybe Int, Hash)]+darcsParseDir content = parse (BLC.split '\n' content)     where       parse (t:n:h':r) = (header t,-                          Name $ BS8.pack $ decodeWhite (BL8.unpack n),+                          decodeWhiteName $ B.concat $ BL.toChunks n,                           decodeDarcsSize hash,                           decodeDarcsHash hash) : parse r-          where hash = BS8.concat $ BL8.toChunks h'+          where hash = BC.concat $ BLC.toChunks h'       parse _ = []       header x-          | x == BL8.pack "file:" = BlobType-          | x == BL8.pack "directory:" = TreeType-          | otherwise = error $ "Error parsing darcs hashed dir: " ++ BL8.unpack x+          | x == BLC.pack "file:" = BlobType+          | x == BLC.pack "directory:" = TreeType+          | otherwise = error $ "Error parsing darcs hashed dir: " ++ BLC.unpack x  ---------------------------------------- -- Utilities.@@ -130,7 +128,7 @@ darcsUpdateDirHashes = updateSubtrees update     where update t = t { treeHash = darcsTreeHash t } -darcsUpdateHashes :: (Monad m, Functor m) => Tree m -> m (Tree m)+darcsUpdateHashes :: (Monad m) => Tree m -> m (Tree m) darcsUpdateHashes = updateTree update     where update (SubTree t) = return . SubTree $ t { treeHash = darcsTreeHash t }           update (File blob@(Blob con _)) =@@ -138,12 +136,12 @@                  return $ File (Blob con hash)           update stub = return stub -darcsHash :: (Monad m, Functor m) => TreeItem m -> m Hash+darcsHash :: (Monad m) => TreeItem m -> m Hash darcsHash (SubTree t) = return $ darcsTreeHash t darcsHash (File blob) = sha256 <$> readBlob blob darcsHash _ = return NoHash -darcsAddMissingHashes :: (Monad m, Functor m) => Tree m -> m (Tree m)+darcsAddMissingHashes :: (Monad m) => Tree m -> m (Tree m) darcsAddMissingHashes = addMissingHashes darcsHash  -------------------------------------------@@ -154,11 +152,12 @@ -- and with a given @hash@. readDarcsHashedDir :: FilePath -> (Maybe Int, Hash) -> IO [(ItemType, Name, Maybe Int, Hash)] readDarcsHashedDir dir h = do+  debugMessage $ "readDarcsHashedDir: " ++ dir ++ " " ++ BC.unpack (encodeBase16 (snd h))   exist <- doesFileExist $ fst (darcsLocation dir h)   unless exist $ fail $ "error opening " ++ fst (darcsLocation dir h)   compressed <- readSegment $ darcsLocation dir h   let content = decompress compressed-  return $ if BL8.null compressed+  return $ if BLC.null compressed               then []               else darcsParseDir content @@ -201,7 +200,7 @@        _ <- mapM (dump . fromJust) dirs        return $ darcsTreeHash t     where dump bits =-              do let name = dir </> BS8.unpack (encodeBase16 $ sha256 bits)+              do let name = dir </> BC.unpack (encodeBase16 $ sha256 bits)                  exist <- doesFileExist name                  unless exist $ BL.writeFile name (compress bits) @@ -209,7 +208,7 @@ -- it is kept untouched and is assumed to have the right content. XXX Corrupt -- files should be probably renamed out of the way automatically or something -- (probably when they are being read though).-fsCreateHashedFile :: FilePath -> BL8.ByteString -> TreeIO ()+fsCreateHashedFile :: FilePath -> BLC.ByteString -> TreeIO () fsCreateHashedFile fn content =     liftIO $ do       exist <- doesFileExist fn@@ -230,16 +229,16 @@            updateFile b@(Blob _ !h) = do             content <- liftIO $ readBlob b-            let fn = dir </> BS8.unpack (encodeBase16 h)+            let fn = dir </> BC.unpack (encodeBase16 h)                 nblob = Blob (decompress <$> rblob) h-                rblob = BL.fromChunks . return <$> BS.readFile fn+                rblob = BL.fromChunks . return <$> B.readFile fn                 newcontent = compress content             fsCreateHashedFile fn newcontent             return nblob           updateSub s = do             let !hash = treeHash s                 Just dirdata = darcsFormatDir s-                fn = dir </> BS8.unpack (encodeBase16 hash)+                fn = dir </> BC.unpack (encodeBase16 hash)             fsCreateHashedFile fn (compress dirdata)             return s 
src/Darcs/Util/Tree/Monad.hs view
@@ -1,7 +1,7 @@ --  Copyright (C) 2009-2011 Petr Rockai -- --  BSD3-{-# LANGUAGE ScopedTypeVariables, TypeSynonymInstances, UndecidableInstances, FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables, TypeSynonymInstances, UndecidableInstances #-}  -- | An experimental monadic interface to Tree mutation. The main idea is to -- simulate IO-ish manipulation of real filesystem (that's the state part of@@ -32,7 +32,7 @@ import Data.Int( Int64 ) import Data.Maybe( isNothing, isJust ) -import qualified Data.ByteString.Lazy.Char8 as BL+import qualified Data.ByteString.Lazy as BL import Control.Monad.RWS.Strict import qualified Data.Map as M @@ -88,18 +88,18 @@                                 , maxage = 0                                 , update = u } -flush :: (Functor m, Monad m) => TreeMonad m ()+flush :: (Monad m) => TreeMonad m () flush = do changed' <- map fst . M.toList <$> gets changed            dirs' <- gets tree >>= \t -> return [ path | (path, SubTree _) <- list t ]            modify $ \st -> st { changed = M.empty, changesize = 0 }            forM_ (changed' ++ dirs' ++ [AnchoredPath []]) flushItem -runTreeMonad' :: (Functor m, Monad m) => TreeMonad m a -> TreeState m -> m (a, Tree m)+runTreeMonad' :: (Monad m) => TreeMonad m a -> TreeState m -> m (a, Tree m) runTreeMonad' action initial = do   (out, final, _) <- runRWST action (AnchoredPath []) initial   return (out, tree final) -runTreeMonad :: (Functor m, Monad m) => TreeMonad m a -> TreeState m -> m (a, Tree m)+runTreeMonad :: (Monad m) => TreeMonad m a -> TreeState m -> m (a, Tree m) runTreeMonad action initial = do   let action' = do x <- action                    flush@@ -111,7 +111,7 @@ -- to their effect of writing a modified tree to disk). The actions can do both -- read and write -- reads are passed through to the actual filesystem, but the -- writes are held in memory in a form of modified Tree.-virtualTreeMonad :: (Functor m, Monad m) => TreeMonad m a -> Tree m -> m (a, Tree m)+virtualTreeMonad :: (Monad m) => TreeMonad m a -> Tree m -> m (a, Tree m) virtualTreeMonad action t = runTreeMonad' action $                                initialState t (\_ -> return NoHash) (\_ x -> return x) @@ -121,7 +121,7 @@ -- | Modifies an item in the current Tree. This action keeps an account of the -- modified data, in changed and changesize, for subsequent flush -- operations. Any modifications (as in "modifyTree") are allowed.-modifyItem :: (Functor m, Monad m)+modifyItem :: (Monad m)             => AnchoredPath -> Maybe (TreeItem m) -> TreeMonad m () modifyItem path item = do   path' <- (`catPaths` path) `fmap` currentDirectory@@ -139,7 +139,7 @@                      , maxage = age + 1                      , changesize = changesize st + change } -renameChanged :: (Functor m, Monad m)+renameChanged :: (Monad m)                => AnchoredPath -> AnchoredPath -> TreeMonad m () renameChanged from to = modify $ \st -> st { changed = rename' $ changed st }   where rename' = M.fromList . map renameone . M.toList@@ -152,13 +152,13 @@ -- 'sync' implementation for a particular storage format. The presumed use-case -- is that an existing in-memory Blob is replaced with a one referring to an -- on-disk file.-replaceItem :: (Functor m, Monad m)+replaceItem :: (Monad m)             => AnchoredPath -> Maybe (TreeItem m) -> TreeMonad m () replaceItem path item = do   path' <- (`catPaths` path) `fmap` currentDirectory   modify $ \st -> st { tree = modifyTree (tree st) path' item } -flushItem :: forall m. (Monad m, Functor m) => AnchoredPath -> TreeMonad m ()+flushItem :: forall m. (Monad m) => AnchoredPath -> TreeMonad m () flushItem path =   do current <- gets tree      case find current path of@@ -176,7 +176,7 @@   -- | If buffers are becoming large, sync, otherwise do nothing.-flushSome :: (Monad m, Functor m) => TreeMonad m ()+flushSome :: (Monad m) => TreeMonad m () flushSome = do x <- gets changesize                when (x > megs 100) $ do                  remaining <- go =<< sortBy age . M.toList <$> gets changed@@ -191,7 +191,7 @@         megs = (* (1024 * 1024))         age (_, (_, a)) (_, (_, b)) = compare a b -instance (Functor m, Monad m) => TreeRO (TreeMonad m) where+instance (Monad m) => TreeRO (TreeMonad m) where     expandTo p =         do t <- gets tree            p' <- (`catPaths` p) `fmap` ask@@ -224,7 +224,7 @@       dir' <- expandTo dir       local (const dir') act -instance (Functor m, Monad m) => TreeRW (TreeMonad m) where+instance (Monad m) => TreeRW (TreeMonad m) where     writeFile p con =         do _ <- expandTo p            modifyItem p (Just blob)@@ -264,17 +264,17 @@            let item = find tr from'            unless (isNothing item) $ modifyItem to item -findM' :: forall m a. (Monad m, Functor m)+findM' :: forall m a . (Monad m)        => (Tree m -> AnchoredPath -> a) -> Tree m -> AnchoredPath -> m a findM' what t path = fst <$> virtualTreeMonad (look path) t   where look :: AnchoredPath -> TreeMonad m a         look = expandTo >=> \p' -> flip what p' <$> gets tree -findM :: (Monad m, Functor m) => Tree m -> AnchoredPath -> m (Maybe (TreeItem m))+findM :: (Monad m) => Tree m -> AnchoredPath -> m (Maybe (TreeItem m)) findM = findM' find -findTreeM :: (Monad m, Functor m) => Tree m -> AnchoredPath -> m (Maybe (Tree m))+findTreeM :: (Monad m) => Tree m -> AnchoredPath -> m (Maybe (Tree m)) findTreeM = findM' findTree -findFileM :: (Monad m, Functor m) => Tree m -> AnchoredPath -> m (Maybe (Blob m))+findFileM :: (Monad m) => Tree m -> AnchoredPath -> m (Maybe (Blob m)) findFileM = findM' findFile
src/Darcs/Util/Tree/Plain.hs view
@@ -26,12 +26,12 @@     ) where  import Data.Maybe( catMaybes )-import qualified Data.ByteString.Char8 as BS8 import qualified Data.ByteString.Lazy as BL import System.FilePath( (</>) ) import System.Directory( getDirectoryContents                        , createDirectoryIfMissing )-import Bundled.Posix( getFileStatus, isDirectory, isRegularFile, FileStatus )+import System.Posix.Files+    ( getSymbolicLinkStatus, isDirectory, isRegularFile, FileStatus )  import Darcs.Util.Path import Darcs.Util.File ( withCurrentDirectory )@@ -45,7 +45,7 @@ readPlainDir dir =     withCurrentDirectory dir $ do       items <- getDirectoryContents "."-      sequence [ do st <- getFileStatus s+      sequence [ do st <- getSymbolicLinkStatus s                     return (s, st)                  | s <- items, s `notElem` [ ".", ".." ] ] @@ -53,14 +53,14 @@ readPlainTree dir = do   items <- readPlainDir dir   let subs = catMaybes [-       let name = Name (BS8.pack name')+       let name = makeName name'         in case status of              _ | isDirectory status -> Just (name, Stub (readPlainTree (dir </> name')) NoHash)-             _ | isRegularFile status -> Just (name, File $ Blob (readBlob' name) NoHash)+             _ | isRegularFile status -> Just (name, File $ Blob (readBlob' name') NoHash)              _ -> Nothing             | (name', status) <- items ]   return $ makeTree subs-    where readBlob' (Name name) = readSegment (dir </> BS8.unpack name, Nothing)+    where readBlob' name = readSegment (dir </> name, Nothing)  -- | Write out /full/ tree to a plain directory structure. If you instead want -- to make incremental updates, refer to "Darcs.Util.Tree.Monad".
src/Darcs/Util/URL.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE CPP #-}- {- Copyright (C) 2004 David Roundy @@ -63,8 +61,6 @@ import Data.Char ( isSpace ) import qualified System.FilePath as FP ( isRelative, isAbsolute, isValid ) import System.FilePath ( (</>) )--#include "impossible.h"  isRelative :: String -> Bool isRelative "" = bug "Empty filename in isRelative"
− src/fpstring.c
@@ -1,69 +0,0 @@-/*- * Copyright (C) 2003 David Roundy- * Most of the UTF code is Copyright (C) 1999-2001 Free Software Foundation, Inc.- * This file is part of darcs.- *- * Darcs is free software; you can redistribute it and/or modify it under- * the terms of the GNU Library General Public License as published by the- * Free Software Foundation; either version 2 of the License, or (at your- * option) any later version.- *- * You should have received a copy of the GNU Library General Public- * License along with the GNU LIBICONV Library; see the file COPYING.LIB.- * If not, write to the Free Software Foundation, Inc., 51 Franklin Street,- * Fifth Floor, Boston, MA 02110-1301, USA.- *- */-#include "fpstring.h"--#include <stdlib.h>-#include <string.h>-#include <stdio.h>---#ifdef _WIN32-#include <windows.h>-#else-#include <sys/mman.h>-#endif--int has_funky_char(const char *s, int len)-{-  // We check first for the more likely \0 so we can break out of-  // memchr that much sooner.-  return !!(memchr(s, 0, len) || memchr(s, 26, len));--}--/* Conversion to and from hex */--void conv_to_hex(unsigned char *dest, unsigned char *from, int num_chars)-{-    static char hex[] = "0123456789abcdef";-    unsigned char *end;--    for (end = from + num_chars; from < end; from++) {-        *dest++ = hex[*from >> 4];-        *dest++ = hex[*from & 0xf];-    }--    return;-}--#define NYBBLE_TO_INT(c) \-    ((c) - ((c) >= 'a' ? 'a' - 10 : '0'))--void conv_from_hex(unsigned char *dest, unsigned char *from, int num_chars)-{-    unsigned char *end;-    unsigned char c;--    end = dest + num_chars;-    while (dest < end) {-        c = NYBBLE_TO_INT(*from) << 4, from++;-        *dest++ = c | NYBBLE_TO_INT(*from), from++;-    }--    return;-}-
− src/fpstring.h
@@ -1,7 +0,0 @@-#include <HsFFI.h>-#include <sys/types.h>--int has_funky_char(const char *s, int len);--void conv_to_hex(unsigned char *dest, unsigned char *from, int num_chars);-void conv_from_hex(unsigned char *dest, unsigned char *from, int num_chars);
− src/h_iconv.c
@@ -1,18 +0,0 @@-#include "h_iconv.h"--// Wrapper functions, since iconv_open et al are macros in libiconv.-iconv_t darcs_iconv_open(const char *tocode, const char *fromcode) {-    return iconv_open(tocode, fromcode);-}--void darcs_iconv_close(iconv_t cd) {-    iconv_close(cd);-}--size_t darcs_iconv(iconv_t cd, char **inbuf, size_t *inbytesleft,-                char **outbuf, size_t *outbytesleft) {-    // Cast inbuf to (void*) so that it works both on Solaris, which expects-    // a (const char**), and on other platforms (e.g. Linux), which expect-    // a (char **).-    return iconv(cd, (void*)inbuf, inbytesleft, outbuf, outbytesleft);-}
− src/h_iconv.h
@@ -1,9 +0,0 @@-#include <iconv.h>--iconv_t darcs_iconv_open(const char *tocode, const char *fromcode);--void darcs_iconv_close(iconv_t cd);--size_t darcs_iconv(iconv_t cd, char **inbuf, size_t *inbytesleft,-                char **outbuf, size_t *outbytesleft);-
− src/impossible.h
@@ -1,8 +0,0 @@-import qualified Darcs.Util.Bug as Bug_--#define darcsBug (\imp_funny_name -> imp_funny_name (__FILE__,__LINE__,__TIME__,__DATE__))--#define bug        (darcsBug Bug_._bug)-#define impossible (darcsBug Bug_._impossible)-#define fromJust   (darcsBug Bug_._fromJust)-#define bugDoc     (darcsBug Bug_._bugDoc)
src/win32/System/Posix/Files.hsc view
@@ -1,15 +1,18 @@ {-# LANGUAGE CPP, ForeignFunctionInterface #-}-module System.Posix.Files( isNamedPipe, isDirectory, isRegularFile, isSymbolicLink-                               , getFdStatus, getFileStatus, getSymbolicLinkStatus-                               , modificationTime, setFileMode, fileSize, fileMode-                               , stdFileMode, linkCount, createLink-                               , FileStatus-                         ) where+module System.Posix.Files+    ( isNamedPipe, isDirectory, isRegularFile, isSymbolicLink+    , getFdStatus, getFileStatus, getSymbolicLinkStatus+    , modificationTime, setFileMode, fileSize, fileMode+    , stdFileMode, FileStatus, fileID+    , linkCount, createLink+    ) where -import System.PosixCompat.Files( isNamedPipe, isDirectory, isRegularFile, isSymbolicLink-                               , getFdStatus, getFileStatus, getSymbolicLinkStatus-                               , modificationTime, setFileMode, fileSize, fileMode-                               , stdFileMode, FileStatus )+import System.PosixCompat.Files+    ( isNamedPipe, isDirectory, isRegularFile, isSymbolicLink+    , getFdStatus, getFileStatus, getSymbolicLinkStatus+    , modificationTime, setFileMode, fileSize, fileMode+    , stdFileMode, FileStatus, fileID+    )  import Foreign.C.String( CWString, withCWString ) import Foreign.C.Error( throwErrnoPathIf_ )
src/win32/System/Posix/IO.hsc view
@@ -1,7 +1,7 @@ {-# LANGUAGE ForeignFunctionInterface #-} module System.Posix.IO where -#if mingw32_HOST_OS && __GLASGOW_HASKELL__ >= 612+#if mingw32_HOST_OS import Foreign.C.String( withCWString ) #else import Foreign.C.String ( withCString )
tests/add.sh view
@@ -2,9 +2,8 @@ . ./lib  rm -rf temp1-mkdir temp1+darcs init temp1 cd temp1-darcs init touch foo bar darcs add foo bar @@ -38,6 +37,17 @@ darcs record -a -m add_foo -A x darcs remove foo darcs record -a -m del_foo -A x+cd ..+rm -rf temp1++# issue1162: add nonexistent slash++rm -rf temp1+darcs init temp1+cd temp1+not darcs add a/ 2> err+cat err+grep 'File a does not exist!' err cd .. rm -rf temp1 
tests/apply-hunks.sh view
@@ -3,10 +3,9 @@   # issue701-rm -rf temp0 temp1 temp2  # step 1-darcs init temp0 --darcs-2+darcs init temp0 cd temp0 echo m1 > foo darcs record -lam m1@@ -59,5 +58,3 @@ echo m2-a1-m4 > foo echo y | darcs mark-conflicts cd ..--rm -rf temp0 temp1 temp2
tests/apply.sh view
@@ -198,7 +198,6 @@ not grep '^  \* d' log # does not complain about an unrelated patch     grep '^  \* y' log # complains about the offending one instead -cd .. rm -rf R S  ## Test that apply --skip-conflicts filters the conflicts
tests/clone.sh view
@@ -2,7 +2,6 @@  . lib -rm -rf temp1 darcs init temp1 cd temp1 touch t.t@@ -11,11 +10,10 @@ DIR=`pwd` abs_to_context="${DIR}/my_context" cd ..-rm -rf temp2+ darcs clone temp1 --context="${abs_to_context}" temp2 darcs log --context --repo temp2 > repo2_context diff -u "${abs_to_context}" repo2_context-cd .. rm -rf temp1 temp2  # issue1865: cover interaction of clone --context with tags@@ -30,6 +28,7 @@ darcs log --context > my_context abs_to_context="$(pwd)/my_context" cd ..+ darcs clone temp1 --context="${abs_to_context}" temp2 darcs log --context --repo temp2 > repo2_context diff -u "${abs_to_context}" repo2_context@@ -69,8 +68,8 @@ cd temp3 darcs log | not grep wobble cd ..-rm -rf temp1 temp2 temp3 +rm -rf temp1 temp2 temp3  # issue885: darcs clone --to-match @@ -81,20 +80,18 @@ firsthash=`darcs log --xml | grep 'hash=' | sed -e "s/.*hash='//" -e "s/'>//"` echo second > b darcs record -lam 'second'- cd ..-darcs init temp2-cd temp2-darcs pull -a --match "hash $firsthash" ../temp1-     # pulling that patch works ok-cd ..-darcs clone --to-match "hash $firsthash" temp1 temp3-     # cloning up to that patch does not++darcs clone --to-match "hash $firsthash" temp1 temp2+test $(darcs log --count --repodir temp2) -eq 1++darcs clone --to-hash $firsthash temp1 temp3+test $(darcs log --count --repodir temp3) -eq 1+ rm -rf temp1 temp2 temp3  # various tests for clone --tag -rm -rf temp1 temp2 darcs init temp1 cd temp1 echo ALL ignore-times >> _darcs/prefs/defaults@@ -112,8 +109,8 @@ darcs record -am EE echo F > foo darcs record -am FF- cd ..+ darcs clone --tag 1.0 --repo-name temp2 temp1 cmp temp2/foo temp1/foo_version_1.0 rm -rf temp1 temp2 temp3@@ -141,16 +138,19 @@ EOF darcs rec -alm 'Remove line 3' cd ..+ darcs init temp2 cd temp2 echo ynyy | darcs pull ../temp1 darcs tag -m Tag darcs push -a ../temp1 cd ..+ darcs clone --tag=Tag temp1 temp3 cd temp3 darcs check cd ..+ rm -rf temp1 temp2 temp3  # clone --tag : check that pending looks ok@@ -163,6 +163,7 @@ rmdir d darcs rec -am 'rm d' cd ..+ darcs clone --tag t temp1 temp2 cd temp2 if [ -f _darcs/patches/pending ]; then@@ -172,8 +173,8 @@ 	fi fi cd ..-rm -rf temp1 temp2 +rm -rf temp1 temp2  # issue2230 - darcs clone --context checks the validity of the context # file too late.
tests/conflict-doppleganger.sh view
@@ -1,7 +1,5 @@ #!/usr/bin/env bash -#pragma repo-format darcs-1,darcs-2- . lib  # Tests for the doppleganger conflict bug.
tests/conflict-fight.sh view
@@ -2,12 +2,10 @@  . ./lib -rm -rf temp0 temp1 temp2- # step 1 mkdir temp0 cd temp0-darcs init --darcs-2+darcs init echo temp0 > _darcs/prefs/author echo m1 > foo darcs add foo@@ -73,6 +71,3 @@ cd temp1 darcs pull -av ../temp2 cd ..--rm -rf temp0 temp1 temp2-
tests/conflict-reporting.sh view
@@ -27,11 +27,8 @@ ## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. -#pragma repo-format darcs-1,darcs-2- . lib -rm -rf R1 R2 mkdir R1 cd R1 darcs init
+ tests/convert-darcs2.sh view
@@ -0,0 +1,64 @@+#!/usr/bin/env bash++## Tests for convert command based on previously checked results+## to generate new test material for this test,+## see bin/convert-writer.sh+##+## Copyright (C) 2009 Ganesh Sittampalam+##+## Permission is hereby granted, free of charge, to any person+## obtaining a copy of this software and associated documentation+## files (the "Software"), to deal in the Software without+## restriction, including without limitation the rights to use, copy,+## modify, merge, publish, distribute, sublicense, and/or sell copies+## of the Software, and to permit persons to whom the Software is+## furnished to do so, subject to the following conditions:+##+## The above copyright notice and this permission notice shall be+## included in all copies or substantial portions of the Software.+##+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS+## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+## SOFTWARE.++. lib++skip-formats darcs-1++runtest() {+    opt=$1+    name=$2+    rm -rf temp+    mkdir temp+    cd temp++    mkdir repo+    cd repo+    darcs init --darcs-1+    darcs apply --allow-conflicts $TESTDATA/convert/darcs1/$name.dpatch+    cd ..+    echo 'I understand the consequences of my action' | darcs convert darcs-2 repo repo2 $opt+    mkdir empty-darcs2+    cd empty-darcs2+    darcs init --darcs-2+    cd ..+    cd repo2+    darcs send --no-minimize -a -o ../$name-darcs2.dpatch ../empty-darcs2+    cd ..+    diff -I'1 patch for repository ' -I'patches for repository ' -I'Oct 1' -u $TESTDATA/convert/darcs2/$name.dpatch $name-darcs2.dpatch+}++for opt in --no-working-dir --with-working-dir; do+    runtest $opt simple+    runtest $opt twowayconflict+    runtest $opt threewayconflict+    runtest $opt threewayanddep+    runtest $opt threewayandmultideps+    runtest $opt resolution+    runtest $opt tworesolutions+done
− tests/convert.sh
@@ -1,62 +0,0 @@-#!/usr/bin/env bash--#pragma repo-format darcs-1--## Tests for convert command based on previously checked results-## to generate new test material for this test,-## see bin/convert-writer.sh-##-## Copyright (C) 2009 Ganesh Sittampalam-##-## Permission is hereby granted, free of charge, to any person-## obtaining a copy of this software and associated documentation-## files (the "Software"), to deal in the Software without-## restriction, including without limitation the rights to use, copy,-## modify, merge, publish, distribute, sublicense, and/or sell copies-## of the Software, and to permit persons to whom the Software is-## furnished to do so, subject to the following conditions:-##-## The above copyright notice and this permission notice shall be-## included in all copies or substantial portions of the Software.-##-## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,-## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF-## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND-## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS-## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN-## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN-## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-## SOFTWARE.--. lib--grep darcs-1 $HOME/.darcs/defaults || exit 200--runtest() {-    rm -rf temp-    mkdir temp-    cd temp--    mkdir repo-    cd repo-    darcs init --darcs-1-    darcs apply --allow-conflicts $TESTDATA/convert/darcs1/$1.dpatch-    cd ..-    echo 'I understand the consequences of my action' | darcs convert darcs-2 repo repo2-    mkdir empty-darcs2-    cd empty-darcs2-    darcs init --darcs-2-    cd ..-    cd repo2-    darcs send --no-minimize -a -o ../$1-darcs2.dpatch ../empty-darcs2-    cd ..-    diff -I'1 patch for repository ' -I'patches for repository ' -I'Oct 1' -u $TESTDATA/convert/darcs2/$1.dpatch $1-darcs2.dpatch-}--runtest simple-runtest twowayconflict-runtest threewayconflict-runtest threewayanddep-runtest threewayandmultideps-runtest resolution-runtest tworesolutions
tests/convert_export.sh view
@@ -34,6 +34,12 @@ echo 'Example content.' > d/f darcs record -lam 'Add d/f and e.' +# one more change, this time with non-ASCII file name, comment, and content+# as well as a space in the file name+# see http://bugs.darcs.net/issue2359+echo 'Liebe Grüße' > e/'Liebe Grüße'+darcs record -lam 'Add file e/"Liebe Grüße"'+ git init gitmirror  darcs convert export --write-marks darcs-to-git.marks > fex@@ -49,3 +55,4 @@ git clone gitmirror gitmirror-clone  diff e/f gitmirror-clone/e/f+diff e/"Liebe Grüße" gitmirror-clone/e/"Liebe Grüße"
− tests/data/many-files--darcs-2.tgz

binary file changed (250790 → absent bytes)

− tests/data/many-files--hashed.tgz

binary file changed (169112 → absent bytes)

tests/diff.sh view
@@ -1,6 +1,9 @@ #!/usr/bin/env bash . ./lib +export DARCS_TMPDIR=`pwd`/tmp+mkdir tmp+ rm -rf temp1 darcs init temp1 cd temp1
− tests/directory_confusion.sh
@@ -1,23 +0,0 @@-#!/usr/bin/env bash-. ./lib--T=temp-rm -rf "$T"-mkdir "$T"-echo "$T"-cd "$T"--darcs initialize-echo text > afile.txt-darcs add afile.txt-darcs record --author me --all --no-test --name init-mkdir d-darcs add d-mkdir d/e-darcs add d/e-darcs mv afile.txt d/e/afile.txt-echo altered_text > d/e/afile.txt-darcs record --author me --all --no-test --name confusion-test ! -f _darcs/pristine/afile.txt-echo y/d/y | tr / \\012 | darcs unrecord-rm -rf "$T"
tests/disable.sh view
@@ -13,7 +13,7 @@   grep disable log   rm log   # --disable works from defaults-  sub_commands="$(darcs $cmd --list-options | grep -v -- -- || true)"+  sub_commands="$(darcs $cmd --list-options | grep -v -- -- | cut -f ';' -f 1 || true)"   # disabling super commands in the defaults file is broken   if test -z "$sub_commands"; then     echo "$cmd --disable" > _darcs/prefs/defaults
tests/failing-issue1014_identical_patches.sh view
@@ -4,7 +4,7 @@ # Set up a base repo. Our experiment will start from this point mkdir base cd base-darcs init --darcs-2+darcs init printf "Line1\nLine2\nLine3\n" > foo darcs rec -alm Base cd ..
− tests/failing-issue1363-mark-conflicts.sh
@@ -1,62 +0,0 @@-#!/usr/bin/env bash-## Test for issue1363 - mark-conflicts should report that there is a-## conflict to mark if apply/push say there are-##-## Copyright (C) 2010 Eric Kow-## Copyright (C) 2009 Thorkil Naur-##-## Permission is hereby granted, free of charge, to any person-## obtaining a copy of this software and associated documentation-## files (the "Software"), to deal in the Software without-## restriction, including without limitation the rights to use, copy,-## modify, merge, publish, distribute, sublicense, and/or sell copies-## of the Software, and to permit persons to whom the Software is-## furnished to do so, subject to the following conditions:-##-## The above copyright notice and this permission notice shall be-## included in all copies or substantial portions of the Software.-##-## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,-## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF-## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND-## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS-## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN-## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN-## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-## SOFTWARE.--. lib                           # Load some portability helpers.-rm -rf R S T                    # Another script may have left a mess.-darcs init      --repo R        # Create our test repos.-darcs init      --repo S-darcs init      --repo T--cd R- touch f.txt- darcs add f.txt- darcs record -am "Empty f.txt"- echo f.txt contents >> f.txt- darcs record -am "Contents of f.txt"-cd ..--cd S- echo yn | darcs pull ../R- rm f.txt- darcs record -am 'Remove f.txt in S'-cd ..--cd T- echo ynn | darcs pull ../R- rm f.txt- darcs record -am 'Remove f.txt in T'- not darcs push -a ../R > log # should fail because of conflict- grep "There are conflicts" log-cd ..--cd R-  darcs pull -a ../S-  darcs revert -a-  darcs pull -a ../T-  echo y | darcs mark-conflicts > log-  not grep "No conflicts" log-cd ..
tests/failing-issue1401_bug_in_get_extra.sh view
@@ -25,14 +25,8 @@ ## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. -#pragma repo-format darcs-2- . lib -## This bug only affects darcs-2 repositories.-fgrep darcs-2 ~/.darcs/defaults &>/dev/null || exit 200--rm -rf d e                      # Another script may have left a mess. darcs initialize --repodir d/ darcs initialize --repodir e/ touch d/f d/g e/f@@ -40,7 +34,6 @@ darcs record     --repodir e/ -lam 'Add f' echo >d/f darcs record     --repodir d/ -am 'Change f'-darcs pull       --repodir e/ -a d/-darcs obliterate --repodir e/ -ap 'Add f and g'+darcs pull       --repodir e/ -a d/ --allow-conflicts #no conflict mark-up+echo y | darcs obliterate --repodir e/ -ap 'Add f and g' darcs pull       --repodir e/ -a d/-rm -rf d/ e/                    # Clean up after ourselves.
tests/failing-issue1610_get_extra.sh view
@@ -25,12 +25,9 @@ ## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. -#pragma repo-format darcs-1- . lib                  # Load some portability helpers. -# this test is not relevant for darcs 2 repositories-(not grep darcs-2 $HOME/.darcs/defaults) || exit 200+# this test fails only for darcs 2 repositories  rm -rf S1  S2  S3               # Another script may have left a mess. darcs init      --repo S1       # Create our test repos.
+ tests/failing-issue2138-whatsnew-s.sh view
@@ -0,0 +1,59 @@+#!/usr/bin/env bash+## Test for issue2138 - whatsnew --summary does not show conflicts+##+## Copyright (C) 2012 Lele Gaifax+##+## Permission is hereby granted, free of charge, to any person+## obtaining a copy of this software and associated documentation+## files (the "Software"), to deal in the Software without+## restriction, including without limitation the rights to use, copy,+## modify, merge, publish, distribute, sublicense, and/or sell copies+## of the Software, and to permit persons to whom the Software is+## furnished to do so, subject to the following conditions:+##+## The above copyright notice and this permission notice shall be+## included in all copies or substantial portions of the Software.+##+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS+## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+## SOFTWARE.++. lib                           # Load some portability helpers.++rm -rf R S++darcs init --repo R++cd R+echo 'Example content.' > f+darcs record -lam 'Add f'+cd ..++darcs get R S++# Create a deliberate conflict+cd R+echo "Conflict on side R" >> f+darcs record -am 'CR'++cd ../S+echo "Conflict on side S" >> f+darcs record -am 'CS'++darcs pull -a ../R++darcs whatsnew > out+cat out+grep "side R" out | wc -l | grep 1+grep "side S" out | wc -l | grep 1++darcs whatsnew --summary > out+grep "^M!" out | wc -l | grep 1++cd ..+rm -rf R S
− tests/failing-issue2208-replace-fails-with-resolving-unrecorded-change.sh
@@ -1,53 +0,0 @@-#!/usr/bin/env bash-## Test for issue2208 - darcs shouldn't fail to replace if unrecorded changes-## would make the replace succeed-##-## Copyright (C) 2012 Owen Stephens-##-## Permission is hereby granted, free of charge, to any person-## obtaining a copy of this software and associated documentation-## files (the "Software"), to deal in the Software without-## restriction, including without limitation the rights to use, copy,-## modify, merge, publish, distribute, sublicense, and/or sell copies-## of the Software, and to permit persons to whom the Software is-## furnished to do so, subject to the following conditions:-##-## The above copyright notice and this permission notice shall be-## included in all copies or substantial portions of the Software.-##-## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,-## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF-## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND-## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS-## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN-## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN-## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-## SOFTWARE.--. lib--rm -rf R--darcs init --repo R--cd R--echo -e 'foo\nbar' > testing--darcs rec -alm 'Add testing file'--echo -e 'baz\nbar' > testing--# Darcs will complain here, since we've not recorded the fact that we've-# removed the occurrence of foo-darcs replace bar foo testing | not grep Skipping--# We can get around this by recording, then replacing and amending the patch...-darcs rec -am "I don't want to have to record this!"--darcs replace bar foo testing--echo y | darcs amend -a--# Check the workaround succeeded.-darcs changes --last 1 -v | grep 'replace.*bar.*foo'
− tests/failing-issue2243-unknown-patch-annotating-empty-first-line.sh
@@ -1,37 +0,0 @@-#!/usr/bin/env bash-## Test for issue2243 - annotating a file with a blank first gives an "unknown"-## patch.-##-## Copyright (C) 2012 Owen Stephens-##-## Permission is hereby granted, free of charge, to any person-## obtaining a copy of this software and associated documentation-## files (the "Software"), to deal in the Software without-## restriction, including without limitation the rights to use, copy,-## modify, merge, publish, distribute, sublicense, and/or sell copies-## of the Software, and to permit persons to whom the Software is-## furnished to do so, subject to the following conditions:-##-## The above copyright notice and this permission notice shall be-## included in all copies or substantial portions of the Software.-##-## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,-## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF-## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND-## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS-## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN-## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN-## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-## SOFTWARE.--. lib --darcs init --repo R--cd R--echo -e "\nline2" > file--darcs rec -alm 'Add file'--darcs annotate file | not grep unknown
+ tests/failing-issue2275_follows-symlinks.sh view
@@ -0,0 +1,45 @@+#!/usr/bin/env bash+## Test for issue2275 - darcs follows symbolic links instead of properly+## ignoring them.+## When substituting a recorded file with a symbolic link, darcs becomes+## confused and associates the filename label to the content of the file+## pointed by the link.+##+## Copyright (C) 2017 Gian Piero Carrubba+##+## Permission is hereby granted, free of charge, to any person+## obtaining a copy of this software and associated documentation+## files (the "Software"), to deal in the Software without+## restriction, including without limitation the rights to use, copy,+## modify, merge, publish, distribute, sublicense, and/or sell copies+## of the Software, and to permit persons to whom the Software is+## furnished to do so, subject to the following conditions:+##+## The above copyright notice and this permission notice shall be+## included in all copies or substantial portions of the Software.+##+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS+## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+## SOFTWARE.++. lib                           # Load some portability helpers.+abort_windows                   # Skip test on Windows++darcs init      --repo R        # Create the test repo.+cd R++touch g                         # Change the working tree.+echo 'This line should not appear in g.' > f+darcs record -lam 'Add f and g.'++rm -f g                         # Remove g and create a link with the+ln -s f g                       # same name ponting to f++darcs diff g | not grep -F '+This line should not appear in g.'++cd ..
+ tests/failing-issue2443-timestamp_index_keeps_unrecorded_addfile.sh view
@@ -0,0 +1,35 @@+#!/usr/bin/env bash+## Test for issue2443 -  timestamp index keeps information about files+## added by unrecorded patches+##+## Copyright (C) 2017 Guillaume Hoffmann+##+## Permission is hereby granted, free of charge, to any person+## obtaining a copy of this software and associated documentation+## files (the "Software"), to deal in the Software without+## restriction, including without limitation the rights to use, copy,+## modify, merge, publish, distribute, sublicense, and/or sell copies+## of the Software, and to permit persons to whom the Software is+## furnished to do so, subject to the following conditions:+##+## The above copyright notice and this permission notice shall be+## included in all copies or substantial portions of the Software.+##+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS+## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+## SOFTWARE.++. lib                           # Load some portability helpers.+darcs init R                    # Create our test repos.+cd R+touch a b c                   # add some files+darcs record -lam "Add a b c"+touch d+darcs record -lam "Add d"     # add another file+echo yd | darcs unrecord+not darcs whatsnew            # d is not supposed to be tracked
− tests/failing-issue2480-display-unicode-in-patch-content.sh
@@ -1,9 +0,0 @@-#!/usr/bin/env bash--. lib-darcs init R-cd R-touch äöüßÄÖÜ-darcs record -lam'added äöüßÄÖÜ'-#darcs log -s | grep './äöüßÄÖÜ'-DARCS_DONT_ESCAPE_8BIT=1 darcs log -s | grep './äöüßÄÖÜ'
+ tests/failing-issue2548-inconsistent-pending-after-merge.sh view
@@ -0,0 +1,43 @@+. lib++darcs init r1+cd r1+touch f+darcs record -lam 'added f as file'+cd ..++darcs init r2+cd r2+mkdir f+darcs record -lam 'added f as dir'++darcs pull -a ../r1++# darcs-1 and darcs-2 resolve the conflict+# differently, we allow both+if cd f && cd ..; then+  rmdir f+else+  rm f+fi+mv f.\~0\~ f+# darcs whatsnew at this point reports nothing+not grep . ../whatsnew+# so revert should do nothing+darcs revert -a++# at this point pending should definitely be empty+# and the following should fail (nothing to record)+if not darcs record -lam 'resolve conflict'; then+  exit 0;+else+  # check that what we record is at least consistent+  # i.e. we have either addfile or adddir for f, but not both+  darcs log -v --last=1 > ../log+  if grep 'addfile ./f' ../log; then+    not grep 'adddir ./f' ../log+  fi+  if grep 'adddir ./f' ../log; then+    not grep 'addfile ./f' ../log+  fi+fi
tests/failing-look_for_replaces1.sh view
@@ -43,7 +43,7 @@ bar bar EOF-echo yyy | darcs amend-record --look-for-replaces+echo y | darcs amend-record --look-for-replaces -a cd .. rm -rf R 
− tests/failing-look_for_replaces2.sh
@@ -1,44 +0,0 @@-#!/usr/bin/env bash-## Failing test for --look-for-replaces combined with --look-for-moves-##-## Copyright (C) 2014 Guillaume Hoffmann-##-## Permission is hereby granted, free of charge, to any person-## obtaining a copy of this software and associated documentation-## files (the "Software"), to deal in the Software without-## restriction, including without limitation the rights to use, copy,-## modify, merge, publish, distribute, sublicense, and/or sell copies-## of the Software, and to permit persons to whom the Software is-## furnished to do so, subject to the following conditions:-##-## The above copyright notice and this permission notice shall be-## included in all copies or substantial portions of the Software.-##-## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,-## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF-## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND-## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS-## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN-## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN-## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-## SOFTWARE.--. lib--rm -rf R-mkdir R-cd R--darcs init-cat > file <<EOF-foo-EOF-darcs record -lam file-cat > file <<EOF-bar-EOF-mv file newfile-darcs whatsnew --look-for-moves --look-for-replaces | grep replace-cd ..-rm -rf R-
+ tests/filename_with_spaces.sh view
@@ -0,0 +1,10 @@+. lib++darcs init R+cd R++filename="file with spaces in its name"+echo xxx > "$filename"+darcs record -lam "comment"+darcs log -s | grep -c "$filename" | grep -w 1+darcs log -v | grep -c "$filename" | grep -w 2
tests/hashed_inventory.sh view
@@ -31,7 +31,7 @@  mkdir temp1 cd temp1-darcs init --darcs-1+darcs init touch foo darcs add foo darcs rec -m t1 -a -A tester
tests/hidden_conflict.sh view
@@ -2,10 +2,12 @@  . ./lib -rm -rf temp1 temp2+# this test fails for darcs-1 repos+skip-formats darcs-1+ mkdir temp1 cd temp1-darcs init --darcs-2+darcs init echo first > a darcs add a darcs record -am 'first'@@ -28,5 +30,3 @@ darcs pull -a ../temp2 | grep conflict grep third a cd ..--rm -rf temp1 temp2
− tests/issue1162_add_nonexistent_slash.sh
@@ -1,16 +0,0 @@-#!/bin/sh--. ./lib--not () { "$@" && exit 1 || :; }--rm -rf temp-mkdir temp-cd temp-darcs init-not darcs add a/ 2> err-cat err-grep 'File a does not exist!' err-cd ..--rm -rf temp
tests/issue1344_abort_early_cant_send.sh view
@@ -58,14 +58,14 @@ darcs add foo bar darcs record -a -m add_foo_bar -A x -# If --sendmail-command is provided, no warning-darcs send --author=me -a --to=random@random --sendmail-command='true' ../temp2-# If --dry-run is provided, no warning-darcs send --author=me -a --to=random@random --dry-run ../temp2-# If -o or -O is provided, no warning+# If --mail and --sendmail-command is provided, no warning+darcs send --mail --author=me -a --to=random@random --sendmail-command='true' ../temp2+# If --mail and --dry-run is provided, no warning+darcs send --mail --author=me -a --to=random@random --dry-run ../temp2+# If --mail is not provided, no warning darcs send --author=me -a --to=random@random -O ../temp2 darcs send --author=me -a --to=random@random -o test.patch ../temp2 # Otherwise, fail early-(darcs send --author=me -a --to=random@random ../temp2 || true) | grep "No working sendmail"+(darcs send --mail --author=me -a --to=random@random ../temp2 || true) | grep "No working sendmail"  cd ..
tests/issue1739-escape-multibyte-chars-correctly.sh view
@@ -50,7 +50,8 @@  # we want escaping, otherwise output of non-ASCII characters is unreliable export DARCS_DONT_ESCAPE_ANYTHING=0-export DARCS_DONT_ESCAPE_8BIT=0+# note default changed, DARCS_DONT_ESCAPE_8BIT is no longer recognized+export DARCS_ESCAPE_8BIT=1 export DARCS_DONT_ESCAPE_ISPRINT=0  rm -rf R@@ -61,7 +62,7 @@ echo garbelbolf > aargh darcs add aargh echo -e '\xe2\x80\x9e\x54\x61\x20\x4d\xc3\xa8\x72\x65\xe2\x80\x9d' > message.txt-darcs record --logfile=message.txt -A 'Petra Testa van der Test <test@example.com>' -a > rec.txt+darcs record --logfile=message.txt -a > rec.txt darcs changes > log.txt cat log.txt grep '<U+201E>' log.txt
tests/issue1978.sh view
@@ -1,7 +1,5 @@ #!/usr/bin/env bash -#pragma repo-format darcs-2- . lib  mkdir future@@ -17,10 +15,6 @@ cat _darcs/format cd .. -if grep darcs-1 .darcs/defaults; then-    exit 200-fi- # get future repo: should be ok darcs get future temp1 cd temp1@@ -29,5 +23,3 @@ darcs add toto darcs record -am 'blah' cd ..-rm -rf temp1 future-
− tests/issue2138-whatsnew-s.sh
@@ -1,59 +0,0 @@-#!/usr/bin/env bash-## Test for issue2138 - whatsnew --summary does not show conflicts-##-## Copyright (C) 2012 Lele Gaifax-##-## Permission is hereby granted, free of charge, to any person-## obtaining a copy of this software and associated documentation-## files (the "Software"), to deal in the Software without-## restriction, including without limitation the rights to use, copy,-## modify, merge, publish, distribute, sublicense, and/or sell copies-## of the Software, and to permit persons to whom the Software is-## furnished to do so, subject to the following conditions:-##-## The above copyright notice and this permission notice shall be-## included in all copies or substantial portions of the Software.-##-## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,-## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF-## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND-## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS-## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN-## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN-## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-## SOFTWARE.--. lib                           # Load some portability helpers.--rm -rf R S--darcs init --repo R--cd R-echo 'Example content.' > f-darcs record -lam 'Add f'-cd ..--darcs get R S--# Create a deliberate conflict-cd R-echo "Conflict on side R" >> f-darcs record -am 'CR'--cd ../S-echo "Conflict on side S" >> f-darcs record -am 'CS'--darcs pull -a ../R--darcs whatsnew > out-cat out-grep "side R" out | wc -l | grep 1-grep "side S" out | wc -l | grep 1--darcs whatsnew --summary > out-grep "^M!" out | wc -l | grep 1--cd ..-rm -rf R S
+ tests/issue2160_wrong_line_number_when_appending_empty_line.sh view
@@ -0,0 +1,19 @@+# Off-by-one error when reporting patches that append an empty line to a file.+# An affected darcs would report 'hunk ./f 3' in the provided tests.+. lib++darcs init R+cd R+echo 'first line' > f+darcs record -lam 'first line'+echo '' >> f+darcs whatsnew > wh+darcs record -am 'appended empty line'+darcs log -v --last=1 > log+darcs annotate f > ann++# these currently all fail:+grep 'hunk ./f 2' wh+grep 'hunk ./f 2' log+not grep unknown ann+grep '#2' ann
+ tests/issue2208-replace-fails-with-resolving-unrecorded-change.sh view
@@ -0,0 +1,56 @@+#!/usr/bin/env bash+## Test for issue2208 - darcs shouldn't fail to replace if unrecorded changes+## would make the replace succeed+##+## Copyright (C) 2012 Owen Stephens+##+## Permission is hereby granted, free of charge, to any person+## obtaining a copy of this software and associated documentation+## files (the "Software"), to deal in the Software without+## restriction, including without limitation the rights to use, copy,+## modify, merge, publish, distribute, sublicense, and/or sell copies+## of the Software, and to permit persons to whom the Software is+## furnished to do so, subject to the following conditions:+##+## The above copyright notice and this permission notice shall be+## included in all copies or substantial portions of the Software.+##+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS+## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+## SOFTWARE.++. lib++rm -rf R++darcs init --repo R++cd R++echo -e 'foo\nbar' > testing++darcs rec -alm 'Add testing file'++echo -e 'baz\nbar' > testing++# Darcs will complain here, since we've not recorded the fact that we've+# removed the occurrence of foo+darcs replace bar foo testing | not grep Skipping++cat <<EOF > ../expected+hunk ./testing 1+-foo++baz+replace ./testing [A-Za-z_0-9] bar foo+EOF++darcs whatsnew > ../actual++cd ..++diff actual expected
+ tests/issue2243-unknown-patch-annotating-empty-first-line.sh view
@@ -0,0 +1,37 @@+#!/usr/bin/env bash+## Test for issue2243 - annotating a file with a blank first gives an "unknown"+## patch.+##+## Copyright (C) 2012 Owen Stephens+##+## Permission is hereby granted, free of charge, to any person+## obtaining a copy of this software and associated documentation+## files (the "Software"), to deal in the Software without+## restriction, including without limitation the rights to use, copy,+## modify, merge, publish, distribute, sublicense, and/or sell copies+## of the Software, and to permit persons to whom the Software is+## furnished to do so, subject to the following conditions:+##+## The above copyright notice and this permission notice shall be+## included in all copies or substantial portions of the Software.+##+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS+## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+## SOFTWARE.++. lib ++darcs init --repo R++cd R++echo -e "\nline2" > file++darcs rec -alm 'Add file'++darcs annotate file | not grep unknown
+ tests/issue2262-display_of_meta_data.sh view
@@ -0,0 +1,7 @@+#!/usr/bin/env bash++. lib+darcs init R+cd R+touch äöüßÄÖÜ+darcs whatsnew -l | grep './äöüßÄÖÜ'
tests/issue2286-metadata-encoding.sh view
@@ -26,9 +26,22 @@  . lib +gunzip -c $TESTDATA/metadata-encoding.tgz | tar xf -+cd metadata-encoding++darcs log -v+ switch_to_utf8_locale+darcs log -v+darcs clone . ../utf8-clone+darcs log -v --repodir ../utf8-clone -gunzip -c $TESTDATA/metadata-encoding.tgz | tar xf -+switch_to_latin9_locale+darcs log -v+darcs clone . ../latin-clone+darcs log -v --repodir ../latin-clone -cd metadata-encoding-darcs changes+LC_ALL=C+darcs log -v+darcs clone . ../c-clone+darcs log -v --repodir ../c-clone
tests/issue2382-mv-dir-to-file-confuses-darcs.sh view
@@ -27,7 +27,7 @@ function getRecordedChanges () { darcs rec -am 1 # Ignore patch details and unindent - we should have the same contents as wh-darcs changes --last 1 -v | tail -n+5 | sed -e 's/^\s\+//' > $1+darcs changes --last 1 -v | tail -n+5 | sed -e 's/^\s\+//' | grep -v '^[{}]$' > $1 darcs unrecord --last 1 -a } 
+ tests/issue2480-display-unicode-in-patch-content.sh view
@@ -0,0 +1,9 @@+#!/usr/bin/env bash++. lib+darcs init R+cd R+echo 'äöüßÄÖÜ' > file+darcs whatsnew -l --no-summary | grep '+äöüßÄÖÜ'+darcs record -lam'added file'+darcs log -v | grep '+äöüßÄÖÜ'
+ tests/issue2512-multiple-authors-clobbered-in-global-conf.sh view
@@ -0,0 +1,47 @@+#!/usr/bin/env bash+## Test for issue2512 - Multiple authors in global config get overwritten++. lib+abort_windows  # different directory names on Windows++# helper+function fail {+	echo "ERROR: $1"+	exit 1+}++# add multiple author IDs to global preferences+cat >"$HOME/.darcs/author" <<-EOF+	AUTHOR_1, this one will be chosen when prompted for an author+	AUTHOR_2, this one should still be there in the end+EOF++# create a repo+rm -rf repo+mkdir repo+cd repo+darcs init++# make a change so that we have something to commit+touch changed+darcs add changed++# darcs will find multiple authors in global preferences,+# so darcs will ask for the author and we pick the first one+darcs record -am 'testing' <<-EOF+	1+EOF+echo++# check the configuration after the commit (primary test for this issue)+if ! grep -q 'AUTHOR_2' "$HOME/.darcs/author"; then+	fail "'\$HOME/.darcs/author' with multiple authors was clobbered."+fi++# in addition, confirm that the author was properly added to the repository+if ! [[ -f _darcs/prefs/author ]]; then+	fail "The author was not recorded in the repository."+fi+if ! grep -q 'AUTHOR_1' _darcs/prefs/author; then+	fail "An 'author' file was created in the repository, but does not contain the chosen author."+fi
+ tests/issue2526-whatsnew-boring.sh view
@@ -0,0 +1,19 @@+#!/usr/bin/env bash++. lib++# test that 'whatsnew -l --boring' actually lists boring files++rm -rf R+darcs init R+cd R++echo xxx > boring+darcs setpref boringfile boring+darcs record -lam'added boring and set as boringile'+touch xxx+darcs whatsnew -l --boring | grep xxx+darcs whatsnew -l --boring | grep -v 'No changes'++cd ..+rm -rf R
+ tests/issue2545_command-execution-via-ssh-uri.sh view
@@ -0,0 +1,49 @@+#!/usr/bin/env bash+## Test for issue2545 - Argument smuggling in SSH repository URLs+## Darcs allows (almost) arbitrary command execution via a crafted ssh URI.+##+## Copyright (C) 2017  Gian Piero Carrubba+##+## Permission is hereby granted, free of charge, to any person+## obtaining a copy of this software and associated documentation+## files (the "Software"), to deal in the Software without+## restriction, including without limitation the rights to use, copy,+## modify, merge, publish, distribute, sublicense, and/or sell copies+## of the Software, and to permit persons to whom the Software is+## furnished to do so, subject to the following conditions:+##+## The above copyright notice and this permission notice shall be+## included in all copies or substantial portions of the Software.+##+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS+## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+## SOFTWARE.++. lib                           # Load some portability helpers.+darcs init      --repo R        # Create our test repos.+cd R++DARCS_SCP=sftp darcs pull -a ssh://-oProxyCommand='touch FAIL' \+    2>/dev/null || true+not ls FAIL >/dev/null++DARCS_SCP=sftp darcs pull -a -- -oProxyCommand='touch FAIL':dir \+    2>/dev/null || true+not ls FAIL >/dev/null++# Executing the same tests with `clone' instead of `pull'. The results shoud+# be the same, but better safe than sorry.+DARCS_SCP=sftp darcs clone ssh://-oProxyCommand='touch FAIL' S \+    2>/dev/null || true+not ls FAIL >/dev/null++DARCS_SCP=sftp darcs clone -- -oProxyCommand='touch FAIL':dir T \+    2>/dev/null || true+not ls FAIL >/dev/null++cd ..
+ tests/issue2567-darcs-whatsnew-unified.sh view
@@ -0,0 +1,41 @@+#!/usr/bin/env bash++# check that darcs whatsnew --unified outputs correct context lines++. lib++cat > before << EOF+1+2+3+4+5+EOF++cat > after << EOF+1+3+4a+4b+5+EOF++cat > exp << EOF+hunk ./file 2+ 1+-2+ 3+hunk ./file 3+-4++4a++4b+ 5+EOF++darcs init R+cd R+cp ../before file+darcs record -lam 'add file'+cp ../after file+darcs whatsnew --unified > ../got+diff ../exp ../got
+ tests/issue2575-revert_during_rebase.sh view
@@ -0,0 +1,11 @@+. lib++darcs init R+cd R+touch f+darcs record -l f -am'add f'+darcs rebase suspend -a --last 1+echo bla > g+darcs add g+darcs revert -a+not grep 'DO NOT TOUCH' _darcs/patches/unrevert
+ tests/issue2581-rebase_pull_reorder_updates_format.sh view
@@ -0,0 +1,16 @@+. lib++darcs init R+cd R+touch f+darcs record -l f -am "add f in R"+cd ..++darcs init S+cd S+touch f+darcs record -l f -am "add f in S"++# first y is for the "repos are unrelated" prompt+echo yaa | darcs rebase pull ../R --reorder-patches+darcs rebase log
tests/issue279_get_extra.sh view
@@ -5,10 +5,12 @@  . lib -rm -rf temp1 temp_a temp_b temp_c temp_d+# this test fails for darcs-1 repos+skip-formats darcs-1+ mkdir temp1 cd temp1-darcs init --darcs-2+darcs init echo 0 > f darcs add f darcs record -am 00@@ -38,5 +40,3 @@ not grep -i "no remote" log not grep -i get_extra log cd ..--rm -rf temp1 temp_a temp_b temp_c temp_d log
tests/issue436.sh view
@@ -1,14 +1,13 @@ #!/usr/bin/env bash -#pragma repo-format darcs-2- . ./lib -rm -rf temp1 temp2+# this test fails in the darcs 1 format+skip-formats darcs-1+ mkdir temp1 cd temp1-# this test fails in the darcs 1 format-darcs init --darcs-2+darcs init echo A > f darcs add f darcs record --ignore-times -a -m A@@ -29,5 +28,3 @@ (darcs push -a || :) 2> push-result grep "Refusing to apply" push-result cd ..--rm -rf temp1 temp2
tests/lazy-optimize-reorder.sh view
@@ -8,7 +8,7 @@ darcs init --no-patch-index  # this test only applies to hashed formats-if cat _darcs/inventory; then exit 0; fi+if cat _darcs/inventory; then exit 200; fi  date > f1 darcs add f1
tests/log-duplicate.sh view
@@ -21,12 +21,11 @@ ## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. -#pragma repo-format darcs-2- . lib-grep darcs-2 $HOME/.darcs/defaults || exit 200 -rm -rf R S+# this test fails for darcs-1 repos+skip-formats darcs-1+ darcs init --repo R darcs init --repo S 
tests/log.sh view
@@ -58,13 +58,12 @@ grep 'num 1' out  cd ..-rm -rf temp1   # Some tests for the output of log when combined with move. -darcs init temp1-cd temp1+darcs init temp2+cd temp2 date > foo darcs record -lam 'add foo' mkdir d@@ -91,27 +90,25 @@ grep "mv foo then add new foo" log not grep "unknown" log cd ..-rm -rf temp1  # Issue244 # darcs changes should be able to pull up the history for a file #   using its moved and not-yet recorded new name -darcs init temp1-cd temp1+darcs init temp3+cd temp3 touch b darcs record -lam 11 darcs mv b c darcs log c | grep 11 cd ..-rm -rf temp1  ## issue1337 - darcs log shows unrelated patches ## Asking "darcs log" about an unrecorded file d/f will list the ## patch that creates the parent directory d/ (instead of no patches). -darcs init temp1-cd temp1+darcs init temp4+cd temp4 mkdir d darcs record -lam d d # We use --match 'touch d/f' instead of simply d/f because the latter@@ -119,13 +116,12 @@ test 0 -eq "$(darcs log --count --match 'touch d/f')"  cd ..-rm -rf temp1  ## issue1632 - 'darcs changes d/f' should not list any changes, ## where d is part of the repo and f is a non-existent file. -darcs init temp1-cd temp1+darcs init temp5+cd temp5  mkdir d darcs record -lam 'added directory d'@@ -136,13 +132,12 @@ darcs changes d/non-existent-file > log not grep 'added directory d' log cd ..-rm -rf temp1  ## issue1888 - changes --context is broken when topmost patch ## is a clean tag. -darcs init temp1-cd temp1+darcs init temp6+cd temp6  echo a > a ; darcs rec -lam "patch_a" darcs log --context | grep patch_a@@ -156,6 +151,5 @@ darcs log --context | grep tag_a darcs log --context | grep patch_b cd ..-rm -rf temp1  
+ tests/look_for_moves_and_replaces.sh view
@@ -0,0 +1,70 @@+#!/usr/bin/env bash++. ./lib++# detect move of a file and then a replace in that file++test_setup() {+  num=$1+  shift+  paths=$@++  darcs init R$num+  cd R$num++  echo foo > old+  echo foo >> old+  echo bar >> old++  darcs record -lam 'added old'+  mv old new++  echo bar > new +  echo bar >> new+  echo bar >> new++  darcs whatsnew --look-for-moves --look-for-replaces $paths > ../out.actual+  cd ..+}++cat <<EOF > out.expected+move ./old ./new+hunk ./new 3+-bar++foo+replace ./new [A-Za-z_0-9] foo bar+EOF++test_setup 1 ""+diff out.actual out.expected++# same but only for old++test_setup 2 old+# remove the line about What's new in: old+sed -i '1d' out.actual+diff out.actual out.expected++# same but only for new++test_setup 3 new+# remove the line about What's new in: new+sed -i '1d' out.actual+# NOTE: the move is NOT detected in this case+# We might want to change that...+sed '1d' out.expected | sed 's/new/old/' > out.expected3+diff out.actual out.expected3++# same but only for old and new++test_setup 4 old new+# remove the line about What's new in: old new+sed -i '1d' out.actual+diff out.actual out.expected++# same but only for old and new and non-existing++test_setup 5 old new non-existing+# remove the line about What's new in: old new, and the one that reports non-existing+sed -i '1,2d' out.actual+diff out.actual out.expected
+ tests/look_for_moves_with_args.sh view
@@ -0,0 +1,50 @@+#!/usr/bin/env bash++# test that --look-for-moves properly handles file arguments++. ./lib++darcs init R+cd R++touch old1+touch old2+touch old3+darcs record -lam 'added files'+mv old1 new1+mv old2 new2+cd ..++runtest () {+  darcs whatsnew --repodir R --look-for-moves $* | grep move > out+}++num_lines () {+  test "$(cat $2 | wc -l)" = "$1"+}++move1='move \./old1 \./new1'+move2='move \./old2 \./new2'++runtest ""+grep "$move1" out+grep "$move2" out+num_lines 2 out++runtest old1+# we expect to see only move1+grep "$move1" out+not grep "$move2" out+num_lines 1 out++runtest old1 old2+# we expect to see both moves+grep "$move1" out+grep "$move2" out+num_lines 2 out++runtest old2 old3+# we expect to see only move2+grep "$move2" out+not grep "$move1" out+num_lines 1 out
tests/merging_newlines.sh view
@@ -5,35 +5,23 @@  # A test for darcs detecting a conflict, inspired by bug #152 in RT -rm -rf temp1 temp2- # set up the repository-mkdir temp1-cd temp1-darcs init-cd ..+darcs init temp1  cd temp1 echo "apply allow-conflicts" > _darcs/prefs/defaults-# note: to make this pass, change echo to echo -n-# is that right? echo "from temp1" > one.txt darcs add one.txt-darcs record -A bar -am "add one.txt"+darcs record -am "add one.txt" echo >> one.txt darcs wh -u cd ..  darcs get temp1 temp2 cd temp2-# reality check-darcs show files | grep one.txt-echo "in tmp2" >> one.txt+echo "from temp2" >> one.txt darcs whatsnew -s | grep M-darcs record -A bar -am "add extra line"+darcs record -am "append non-empty line" darcs push -av > log-cat log-not grep -i conflicts log+grep -i conflicts log cd ..--rm -rf temp1 temp2
tests/network/clone-http-packed-detect.sh view
@@ -4,21 +4,13 @@ # Tests that darcs clone --verbose reports getting a pack when there is one, # and does not report when there is none or when --no-packs is passed. -#pragma repo-format darcs-1,darcs-2- . lib -rm -rf S--if grep darcs-1 .darcs/defaults; then-format=hashed-elif grep darcs-2 .darcs/defaults; then-format=darcs-2-else format=ERROR; fi+skip-formats darcs-1 # compressed repo is darcs-2 -gunzip -c $TESTDATA/many-files--${format}.tgz | tar xf -+gunzip -c $TESTDATA/laziness-complete.tgz | tar xf - -cd many*+cd repo  darcs optimize http test -e _darcs/packs/basic.tar.gz@@ -28,13 +20,13 @@ serve_http # sets baseurl  # check that default behaviour is to get packs-darcs clone $baseurl/many-files--${format} S --verbose |grep "Cloning packed basic repository"+darcs clone $baseurl/laziness-complete S --verbose |grep "Cloning packed basic repository"  # check that it does really not get packs when --no-packs is passed rm -rf S-darcs clone $baseurl/many-files--${format} S --no-packs --verbose  |not grep "Cloning packed basic repository"+darcs clone $baseurl/laziness-complete S --no-packs --verbose  |not grep "Cloning packed basic repository"  # check that it does not clam getting packs when there are not rm -rf S-rm -rf many-files--${format}/_darcs/packs/-darcs clone $baseurl/many-files--${format} S --verbose |not grep "Cloning packed basic repository"+rm -rf laziness-complete/_darcs/packs/+darcs clone $baseurl/laziness-complete S --verbose |not grep "Cloning packed basic repository"
tests/network/clone-http-packed.sh view
@@ -1,21 +1,13 @@ #!/usr/bin/env bash # Written in 2010 by Petr Rockai, placed in public domain -#pragma repo-format darcs-1,darcs-2- . lib -rm -rf S--if grep darcs-1 .darcs/defaults; then-format=hashed-elif grep darcs-2 .darcs/defaults; then-format=darcs-2-else format=ERROR; fi+skip-formats darcs-1 # compressed repo is darcs-2 -gunzip -c $TESTDATA/many-files--${format}.tgz | tar xf -+gunzip -c $TESTDATA/laziness-complete.tgz | tar xf - -cd many*+cd repo  darcs optimize http test -e _darcs/packs/basic.tar.gz@@ -23,7 +15,7 @@ cd ..  serve_http # sets baseurl-darcs clone --packs $baseurl/many-files--${format} S+darcs clone --packs $baseurl/laziness-complete S cd S rm _darcs/prefs/sources # avoid any further contact with the original repository darcs check
+ tests/network/failing-issue1599-automatically-expire-unused-caches.sh view
@@ -0,0 +1,55 @@+#!/usr/bin/env bash+## Test for issue1599 - 'Automatically expire unused caches'+##+## Copyright (C) 2010  Adolfo Builes+##+## Permission is hereby granted, free of charge, to any person+## obtaining a copy of this software and associated documentation+## files (the "Software"), to deal in the Software without+## restriction, including without limitation the rights to use, copy,+## modify, merge, publish, distribute, sublicense, and/or sell copies+## of the Software, and to permit persons to whom the Software is+## furnished to do so, subject to the following conditions:+##+## The above copyright notice and this permission notice shall be+## included in all copies or substantial portions of the Software.+##+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS+## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+## SOFTWARE.+. lib++rm -rf R S log && mkdir R+cd R+darcs init+echo a > a+darcs rec -lam a+echo b > b+darcs rec -lam b+echo c > c+darcs rec -lam c+cd ..++serve_http # sets baseurl+darcs clone --lazy $baseurl/R S+rm S/_darcs/prefs/sources+if [ -z "$http_proxy" ]; then+  echo "repo:http://10.1.2.3/S" >> S/_darcs/prefs/sources+fi+echo "repo:$baseurl/dummyRepo" >> S/_darcs/prefs/sources+echo "repo:~/test1599/S" >> S/_darcs/prefs/sources+echo "repo:$baseurl/R" >> S/_darcs/prefs/sources+export DARCS_CONNECTION_TIMEOUT=1 && darcs log --repo S --debug --verbose --no-cache 2>&1 | tee log+if [ -z "$http_proxy" ]; then+  c=`grep -c "URL.waitUrl http://10.1.2.3/S" log`+  [ $c  -eq 1 ]+fi+c1=`grep -c "URL.waitUrl $baseurl/dummyRepo" log`+[ $c1 -eq 2 ]+c2=`grep -c "~/test1599/S" log`+[ $c2 -eq 1 ]
− tests/network/issue1599-automatically-expire-unused-caches.sh
@@ -1,55 +0,0 @@-#!/usr/bin/env bash-## Test for issue1599 - 'Automatically expire unused caches'-##-## Copyright (C) 2010  Adolfo Builes-##-## Permission is hereby granted, free of charge, to any person-## obtaining a copy of this software and associated documentation-## files (the "Software"), to deal in the Software without-## restriction, including without limitation the rights to use, copy,-## modify, merge, publish, distribute, sublicense, and/or sell copies-## of the Software, and to permit persons to whom the Software is-## furnished to do so, subject to the following conditions:-##-## The above copyright notice and this permission notice shall be-## included in all copies or substantial portions of the Software.-##-## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,-## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF-## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND-## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS-## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN-## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN-## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE-## SOFTWARE.-. lib--rm -rf R S log && mkdir R-cd R-darcs init-echo a > a-darcs rec -lam a-echo b > b-darcs rec -lam b-echo c > c-darcs rec -lam c-cd ..--serve_http # sets baseurl-darcs clone --lazy $baseurl/R S-rm S/_darcs/prefs/sources-if [ -z "$http_proxy" ]; then-  echo "repo:http://10.1.2.3/S" >> S/_darcs/prefs/sources-fi-echo "repo:$baseurl/dummyRepo" >> S/_darcs/prefs/sources-echo "repo:~/test1599/S" >> S/_darcs/prefs/sources-echo "repo:$baseurl/R" >> S/_darcs/prefs/sources-export DARCS_CONNECTION_TIMEOUT=1 && darcs log --repo S --debug --verbose --no-cache 2>&1 | tee log-if [ -z "$http_proxy" ]; then-  c=`grep -c "URL.waitUrl http://10.1.2.3/S" log`-  [ $c  -eq 1 ]-fi-c1=`grep -c "URL.waitUrl $baseurl/dummyRepo" log`-[ $c1 -eq 2 ]-c2=`grep -c "~/test1599/S" log`-[ $c2 -eq 1 ]
tests/network/issue1932-remote.sh view
@@ -36,7 +36,7 @@ [ -n "$(fgrep  'ssh: Could not resolve hostname invalid: Name or service not known' log)" ]  # HTTP repo-( darcs clone http://www.bogus.domain.so.it.will.surely.fail.com || true ) 2>&1 | tee log+( http_proxy= darcs clone http://www.bogus.domain.so.it.will.surely.fail.com || true ) 2>&1 | tee log egrep 'CouldNotResolveHost|host lookup failure' log  # local repos are tested by tests/issue1932-colon-breaks-add.sh
tests/network/issue2090-transfer-mode.sh view
@@ -47,7 +47,6 @@ cd ..  darcs clone $REMOTE:$REMOTE_DIR/R S --debug > log 2>&1-COUNT=$(grep -c 'darcs transfer-mode' log)+COUNT=$(grep -c '^Exec.*darcs.*transfer-mode' log) # with issue2090, this was 6! test $COUNT -eq 1-cleanup
+ tests/network/issue2545_command-execution-via-ssh-uri.sh view
@@ -0,0 +1,45 @@+#!/usr/bin/env bash+## Test for issue2545 - Argument smuggling in SSH repository URLs+##+## Darcs allows (almost) arbitrary command execution via a crafted ssh+## URI.+## When pushing to a remote repo, darcs is invoked on the remote server+## via ssh. This use of ssh is different from the ones tested by the+## not-networked test. Also, I'm not sure how (if) it can be exploited,+## so I'm just checking for the debug message. Pretty lame test, I know.+##+## Copyright (C) 2017  Gian Piero Carrubba+##+## Permission is hereby granted, free of charge, to any person+## obtaining a copy of this software and associated documentation+## files (the "Software"), to deal in the Software without+## restriction, including without limitation the rights to use, copy,+## modify, merge, publish, distribute, sublicense, and/or sell copies+## of the Software, and to permit persons to whom the Software is+## furnished to do so, subject to the following conditions:+##+## The above copyright notice and this permission notice shall be+## included in all copies or substantial portions of the Software.+##+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS+## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+## SOFTWARE.++. lib                           # Load some portability helpers.+. sshlib                        # Load ssh helpers.++init_remote_repo R              # Create our test repos.+darcs init      --repo R        #+cd R++echo "text" > file              # Modify the working dir+darcs record -lam "First Patch" # Record the changes++check="\"${SSH}\" \"--\" \"${REMOTE}\" \"darcs apply --all --debug --repodir '${REMOTE_DIR}/R'\""+darcs push -a --debug "${REMOTE}":"${REMOTE_DIR}"/R 2>&1 >/dev/null | \+    fgrep "$check"
tests/network/ssh.sh view
@@ -103,4 +103,3 @@ grep -q 'conflicts options to apply' log  cd ..-cleanup
tests/network/sshlib view
@@ -1,5 +1,5 @@ if [ x${REMOTE_DIR} = x ]; then-  REMOTE_DIR=/tmp/darcs-ssh-test+  REMOTE_DIR=/tmp/darcs-ssh-test$$ fi  if [ x"${USE_PUTTY}" != x ]; then@@ -22,20 +22,19 @@   SSH=${DARCS_SSH} fi -rm -rf tempssh-mkdir tempssh-cd tempssh--cleanup () {-  cd ..-  rm -rf tempssh-}- if [ x${REMOTE} = x ]; then   REMOTE=$(whoami)@localhost fi -# vim: syntax=sh:+init_remote_repo() {+    repodir="${1:-R}" +    ${SSH} ${REMOTE} \+        "rm -rf '${REMOTE_DIR}' && mkdir '${REMOTE_DIR}' && \+            cd '${REMOTE_DIR}' && darcs init --repo '$repodir' --$format"+}+ # test if we can connect via ssh, otherwise skip test-${SSH} ${REMOTE} true || exit 200+${SSH} -x -o=NumberofPasswordPrompts=0 ${REMOTE} true || exit 200++# vim: syntax=sh:
tests/oldfashioned.sh view
@@ -76,7 +76,7 @@  cd .. -# issue2253 - darcs log FILE should build patch index in an OF repo+# issue2253 - darcs log FILE should not build patch index in an OF repo cd old darcs log x 
tests/printer.sh view
@@ -4,7 +4,6 @@  . lib -rm -rf temp1 mkdir temp1 cd temp1 darcs init@@ -15,7 +14,7 @@ env # clear all output formating environment variables for e in DARCS_DONT_ESCAPE_ISPRINT DARCS_USE_ISPRINT\-         DARCS_DONT_ESCAPE_8BIT\+         DARCS_ESCAPE_8BIT\          DARCS_DONT_ESCAPE_EXTRA DARCS_ESCAPE_EXTRA\          DARCS_DONT_ESCAPE_TRAILING_SPACES\          DARCS_DONT_COLOR DARCS_ALWAYS_COLOR DARCS_ALTERNATIVE_COLOR\@@ -30,7 +29,7 @@ test_line () {     rm -f a     echo $1 > a-    darcs whatsnew | fgrep $2+    darcs whatsnew | grep -F $2 }  @@ -62,6 +61,11 @@ test_line $(printf '\x1D') '[_^]_]' test_line $(printf '\x1E') '[_^^_]' test_line $(printf '\x1F') '[_^__]'++# everything up to here is escaped by default;+# for the rest we must explicitly set it:+export DARCS_ESCAPE_8BIT=1+ test_line $(printf '\x7F') '[_^?_]' # other chars are escaped with <U+XXXX> test_line $(printf '\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F')\@@ -80,4 +84,3 @@           '[_<U+00E0>_][_<U+00E1>_][_<U+00E2>_][_<U+00E3>_][_<U+00E4>_][_<U+00E5>_][_<U+00E6>_][_<U+00E7>_][_<U+00E8>_][_<U+00E9>_][_<U+00EA>_][_<U+00EB>_][_<U+00EC>_][_<U+00ED>_][_<U+00EE>_][_<U+00EF>_]' test_line $(printf '\xF0\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF')\           '[_<U+00F0>_][_<U+00F1>_][_<U+00F2>_][_<U+00F3>_][_<U+00F4>_][_<U+00F5>_][_<U+00F6>_][_<U+00F7>_][_<U+00F8>_][_<U+00F9>_][_<U+00FA>_][_<U+00FB>_][_<U+00FC>_][_<U+00FD>_][_<U+00FE>_][_<U+00FF>_]'-rm -rf temp1
tests/pull.sh view
@@ -320,3 +320,22 @@  rm -rf temp1 temp2 +# pull --matches+darcs init temp1+cd temp1+echo first > a+darcs record -lam 'first'+firsthash=`darcs log --xml | grep 'hash=' | sed -e "s/.*hash='//" -e "s/'>//"`+echo second > b+darcs record -lam 'second'+cd ..++darcs init temp2+darcs pull --repodir temp2 -a --match "hash $firsthash" temp1+test $(darcs log --count --repodir temp2) -eq 1++darcs init temp3+darcs pull --repodir temp3 -a --hash $firsthash temp1+test $(darcs log --count --repodir temp3) -eq 1++rm -rf temp1 temp2 temp3
− tests/pull_many_files.sh
@@ -1,29 +0,0 @@-#!/usr/bin/env bash-. lib--#pragma repo-format darcs-1,darcs-2--rm -rf temp1 temp2--if grep darcs-1 .darcs/defaults; then-format=hashed-elif grep darcs-2 .darcs/defaults; then-format=darcs-2-else format=ERROR; fi--mkdir temp2-cd temp2-gunzip -c $TESTDATA/many-files--${format}.tgz | tar xf --cd ..--mkdir temp1-cd temp1-darcs init-darcs pull -a ../temp2/many-files--${format} > log-grep -i 'finished pulling' log-cd ..-rm -rf temp1--# put things back how we found them.--rm -rf temp1 temp2
tests/push.sh view
@@ -27,7 +27,7 @@ # push without a repo gives an error cd temp1 not darcs push -p 123 2> log-grep -i 'missing argument' log+grep -i 'No default repository to push to' log cd ..  mkdir -p temp2/one/two
tests/rebase-apply.sh view
@@ -53,7 +53,7 @@ # (should it answer 'yes' to both pulling and suspending? echo yyy | darcs rebase apply -a ../R2/2.dpatch -darcs changes --count | grep "Rebase in progress: 2 suspended patches"+darcs changes --count 2>&1 | grep "Rebase in progress: 2 suspended patches" echo yny | darcs rebase unsuspend | grep "We have conflicts" cat > expected <<EOF v v v v v v v
tests/rebase-basic.sh view
@@ -33,7 +33,7 @@ echo 'wibble' > wibble darcs rec -lam "add wibble" -echo 'yy' | darcs rebase suspend | grep-once "Rebase in progress: 1 suspended patch"+echo 'yy' | darcs rebase suspend 2>&1 | grep-once "Rebase in progress: 1 suspended patch" not test -f wibble echo 'yy' | darcs rebase unsuspend | grep-once "Rebase finished" test -f wibble
tests/rebase-nochanges.sh view
@@ -54,10 +54,9 @@   * add wobble  Making no changes: this is a dry run.-Rebase in progress: 1 suspended patches EOF darcs unpull --dry-run | tail -n+5 | grep -v tester | diff -u expected -  -echo 'yy' | darcs rebase unsuspend | grep "Rebase finished"+echo 'yy' | darcs rebase unsuspend 2>&1 | grep "Rebase finished" test -f wibble
tests/rebase-pull.sh view
@@ -52,7 +52,7 @@ # (should it answer 'yes' to both pulling and suspending? echo yyy | darcs rebase pull -a ../R2 -darcs changes --count | grep "Rebase in progress: 2 suspended patches"+darcs changes --count 2>&1 | grep "Rebase in progress: 2 suspended patches" echo yny | darcs rebase unsuspend | grep "We have conflicts" cat > expected <<EOF v v v v v v v
tests/repoformat.sh view
@@ -1,7 +1,5 @@ #!/usr/bin/env bash -#pragma repo-format darcs-1,darcs-2- . lib  rm -rf garbage future@@ -13,7 +11,7 @@  mkdir future cd future-darcs  init+darcs init touch titi darcs add titi darcs record -am titi@@ -68,9 +66,7 @@ #  alternative of a line of format #  only look at future vs darcs2 -if grep darcs-1 .darcs/defaults; then-    exit 200-fi+skip-formats darcs-1  # get future repo: ok # --to-match is needed because of bug###
+ tests/revert.sh view
@@ -0,0 +1,87 @@+#!/usr/bin/env bash+. ./lib++rm -rf temp1+mkdir temp1+cd temp1+darcs init+echo hello world > foo+darcs add foo+darcs record -lam add+echo goodbye world >> foo+darcs revert -a+darcs show contents foo | cmp foo -++# Now let's test a trickier revert where changes commute nontrivially.++cat > foo <<EOF+a+b+c+d+e+EOF++darcs record -am cleanup++mv foo foo.tmp+cat foo.tmp | grep -v b | grep -v d > foo++echo "nyy" | darcs revert++DARCS_DONT_COLOR=1 darcs wh > whatsnew+cat > correct <<EOF+hunk ./foo 2+-b+EOF+diff -c correct whatsnew++# Try a situation where earlier (kept) changes are depended upon by the+# changes we want to revert:++darcs record -am cleanup++echo hello world > bar+echo hello world > foo+darcs add bar+darcs replace hello goodbye bar foo++echo "cnnnyy/y" | tr / \\012 | darcs revert++DARCS_DONT_COLOR=1 darcs wh > whatsnew+cat > correct <<EOF+addfile ./bar+hunk ./bar 1++goodbye world+hunk ./foo 1+-a+-c+-d+-e++hello world+EOF+diff -c correct whatsnew++cd ..+rm -rf temp1++# test for reverting removed directory++darcs init temp1+cd temp1+mkdir d+darcs add d+darcs record -lam 'add dir'+rmdir d+darcs revert -a d+cd ..+rm -rf temp1++# revert unrecorded add++darcs init temp1+cd temp1+echo stuff > foo+darcs add foo+darcs revert -a+
− tests/revert_interactive.sh
@@ -1,67 +0,0 @@-#!/usr/bin/env bash-. ./lib--rm -rf temp1-mkdir temp1-cd temp1-darcs init-echo hello world > foo-darcs add foo-darcs record -a -m add -A x-echo goodbye world >> foo-echo y/y | tr / \\012 | darcs revert-darcs show contents foo | cmp foo ---# Now let's test a trickier revert where changes commute nontrivially.--cat > foo <<EOF-a-b-c-d-e-EOF--darcs record -a -A me -m cleanup--mv foo foo.tmp-cat foo.tmp | grep -v b | grep -v d > foo--echo "nyy" | darcs revert--DARCS_DONT_COLOR=1 darcs wh > whatsnew-cat > correct <<EOF-hunk ./foo 2--b-EOF-diff -c correct whatsnew--# Try a situation where earlier (kept) changes are depended upon by the-# changes we want to revert:--darcs record -a -A me -m cleanup--echo hello world > bar-echo hello world > foo-darcs add bar-darcs replace hello goodbye bar foo--echo "cnnnyy/y" | tr / \\012 | darcs revert--DARCS_DONT_COLOR=1 darcs wh > whatsnew-cat > correct <<EOF-addfile ./bar-hunk ./bar 1-+goodbye world-hunk ./foo 1--a--c--d--e-+hello world-EOF-diff -c correct whatsnew--cd ..-rm -rf temp1-
− tests/revert_unrecorded_add.sh
@@ -1,13 +0,0 @@-#!/usr/bin/env bash-. ./lib--rm -rf temp-mkdir temp-cd temp--darcs init--echo stuff > foo-darcs add foo--darcs revert -a
tests/send-output-v1.sh view
@@ -24,11 +24,9 @@ ## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. -#pragma repo-format darcs-1- . lib                  # Load some portability helpers. -grep darcs-1 $HOME/.darcs/defaults || exit 200+skip-formats darcs-2  rm -rf empty mkdir empty
tests/send-output-v2.sh view
@@ -24,11 +24,9 @@ ## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. -#pragma repo-format darcs-2- . lib                  # Load some portability helpers. -grep darcs-2 $HOME/.darcs/defaults || exit 200+skip-formats darcs-1  rm -rf empty mkdir empty
− tests/several_commands.sh
@@ -1,25 +0,0 @@-#!/usr/bin/env bash-. ./lib--rm -rf temp1-mkdir temp1-cd temp1-darcs init-echo hello world > foo-darcs add foo-darcs record -a -m add -A x-echo goodbye world >> foo-darcs diff-darcs diff -u-darcs whatsnew-darcs whatsnew --summary-echo y | darcs revert -a-darcs show contents foo | cmp foo --mkdir d-darcs add d-darcs record -a -m 'add dir' -A x-rmdir d-darcs revert -a d-cd ..-rm -rf temp1-
− tests/show-bug.sh
@@ -1,22 +0,0 @@-#!/usr/bin/env bash--## All these commands SHOULD fail (hence leading NOTs).-. lib--darcs show bug --debug 1> stdout 2> stderr || true--cat stdout-cat stderr--echo The following test will fail if this version of darcs is marked as-echo obsolete.-echo ==================================================================--not grep 'please do not' stderr--# The following test fails if HTTP isn't present, but would be a nice test-# to have in place.--#not grep unable stderr--grep 'fake bug' stderr
tests/show_files.sh view
@@ -89,3 +89,28 @@  cd .. rm -rf temp++darcs init --repo R+cd R++for file in foo bar baz quux+do+    touch "$file"+    darcs add "$file"+    darcs record --all --name "Add $file"+done++darcs unrecord --all --patches "quux"+darcs rebase suspend --all --patches "foo"++# (pending, match): (False, False)+check_manifest "bar baz" "" "--no-pending"+# (pending, match): (False, True)+check_manifest "bar" "" "--no-pending --patch bar"+# (pending, match): (True, False)+check_manifest "bar baz quux" "" "--pending"+# (pending, match): (True, True)+not darcs show files --pending --patch "bar"++cd ..+rm -rf R
tests/split-patches.sh view
@@ -24,8 +24,6 @@ ## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. -#pragma repo-format darcs-1,darcs-2- . lib                  # Load some portability helpers.  if grep darcs-2 .darcs/defaults; then
+ tests/switch-encoding.sh view
@@ -0,0 +1,87 @@+. lib++switch_to_utf8_locale+lc_utf8=$LC_ALL++darcs init E+darcs clone E U++cd U+mkdir Texte+echo 'Müßiggang' > 'Texte/böse Zeichen'+darcs record -lam 'Erste Änderung'+darcs log -v+darcs send -ao bundle+tail -n+7 bundle > u_bundle++LC_ALL=C++darcs log -v+darcs send -ao bundle+tail -n+7 bundle > c_bundle++diff u_bundle c_bundle++darcs apply u_bundle | grep 'already .*applied'+darcs obliterate -a+darcs apply u_bundle | grep 'Finished applying'+darcs unrecord -a+darcs revert -a+darcs apply u_bundle | grep 'Finished applying'+++LC_ALL=$lc_utf8++darcs apply c_bundle | grep 'already .*applied'+darcs obliterate -a+darcs apply c_bundle | grep 'Finished applying'+darcs unrecord -a+darcs revert -a+darcs apply c_bundle | grep 'Finished applying'++LC_ALL=C++cd ..++darcs clone U C+diff -r U/Texte C/Texte++cd C+darcs pull ../E --set-default++darcs apply ../U/u_bundle | grep 'already .*applied'+diff -r ../U/Texte Texte+darcs obliterate -ao ou_bundle+diff ../U/u_bundle ou_bundle+darcs apply ou_bundle | grep 'Finished applying'+diff -r ../U/Texte Texte+darcs unrecord -a+darcs revert -a+darcs pull ../U -a+diff -r ../U/Texte Texte+darcs send -ao bundle+tail -n+7 bundle > c_bundle++LC_ALL=$lc_utf8++darcs send -ao bundle+tail -n+7 bundle > u_bundle+diff u_bundle c_bundle++darcs apply c_bundle | grep 'already .*applied'+diff -r ../U/Texte Texte+darcs obliterate -ao oc_bundle+diff c_bundle oc_bundle+darcs apply c_bundle | grep 'Finished applying'+diff -r ../U/Texte Texte+darcs unrecord -a+darcs revert -a+darcs pull ../U -a+diff -r ../U/Texte Texte+darcs send -ao bundle+tail -n+7 bundle > c_bundle++cd ..++diff U/u_bundle C/u_bundle+diff -r U/Texte C/Texte
− tests/toolbox.sh
@@ -1,16 +0,0 @@-#!/usr/bin/env bash--. lib--DIR="`pwd`"--# set up the repository-rm -rf temp1                    # another script may have left a mess.-mkdir temp1-cd temp1-darcs init-touch foo-darcs add foo-echo ny | darcs record-cd ..-rm -rf temp1
tests/utf8-display.sh view
@@ -30,7 +30,8 @@  switch_to_utf8_locale -export DARCS_DONT_ESCAPE_8BIT=1+#is now the default, must use DARCS_ESCAPE_8BIT to disable+#export DARCS_DONT_ESCAPE_8BIT=1  rm -rf R mkdir R
tests/v1-braced.sh view
@@ -24,11 +24,9 @@ ## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE ## SOFTWARE. -#pragma repo-format darcs-1- . lib                  # Load some portability helpers. -grep darcs-1 $HOME/.darcs/defaults || exit 200+skip-formats darcs-2  rm -rf braced gunzip -c $TESTDATA/braced.tgz | tar xf -
+ tests/whatsnew-adds-no-summary.sh view
@@ -0,0 +1,51 @@+#!/bin/sh -e+##+## Test for the interaction of --look-for-adds and --no-summary in darcs whatsnew+##+## Copyright (C) 2017 Ganesh Sittampalam+##+## Permission is hereby granted, free of charge, to any person+## obtaining a copy of this software and associated documentation+## files (the "Software"), to deal in the Software without+## restriction, including without limitation the rights to use, copy,+## modify, merge, publish, distribute, sublicense, and/or sell copies+## of the Software, and to permit persons to whom the Software is+## furnished to do so, subject to the following conditions:+##+## The above copyright notice and this permission notice shall be+## included in all copies or substantial portions of the Software.+##+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS+## BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN+## ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+## CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+## SOFTWARE.++. lib++rm -rf R+mkdir R+cd R++darcs init++echo A > A+echo B > B++darcs add A+darcs rec -am "add A"++echo "A 2" > A++darcs whatsnew --look-for-adds --no-summary > output.txt++grep "hunk \./A 1" output.txt+grep "\-A" output.txt+grep "+A 2" output.txt+grep "addfile \./B" output.txt+grep "hunk \./B 1" output.txt+grep "+B" output.txt+
tests/whatsnew.sh view
@@ -21,7 +21,8 @@ touch look_summary.txt darcs whatsnew -l | grep -i "a ./look_summary.txt" -#whatsnew works with uncommon file names+# whatsnew works with uncommon file names and does NOT display+# the internal "white space encoded" filename if echo $OS | grep -i windows; then   echo  test does not work on windows   exit 0;@@ -29,13 +30,13 @@   echo foo > \\   darcs add \\   darcs whatsnew | tee log-  grep 'hunk ./\\92\\' log+  grep 'hunk ./\\' log fi  echo foo > "foo bar" darcs add "foo bar" darcs wh | tee log-grep 'hunk ./foo\\32\\bar' log+grep 'hunk ./foo bar' log  # check that filename encoding does not botch up the index darcs rec -am "weird filenames"@@ -141,10 +142,9 @@ cat out grep date out | wc -l | grep 1 -# This one fails actually, but it's not my fault. Filed as issue1196.-#darcs wh foo foo/../foo/. > out-#cat out-#grep date out | wc -l | grep 1+darcs wh foo foo/../foo/. > out+cat out+grep date out | wc -l | grep 1  cd .. rm -rf temp1