module Darcs.Patch.Named
( Named(..),
infopatch,
adddeps, namepatch, anonymous,
getdeps,
patch2patchinfo, patchname, patchcontents,
fmapNamed, fmapFL_Named,
commuterIdNamed, commuterNamedId,
mergerIdNamed
)
where
import Prelude ()
import Darcs.Prelude
import Prelude hiding ( pi )
import Darcs.Patch.CommuteFn ( CommuteFn, commuterIdFL, commuterFLId
, MergeFn, mergerIdFL )
import Darcs.Patch.Conflict ( Conflict(..), CommuteNoConflicts )
import Darcs.Patch.Debug ( PatchDebug(..) )
import Darcs.Patch.Effect ( Effect(effect, effectRL) )
import Darcs.Patch.FileHunk ( IsHunk(..) )
import Darcs.Patch.Format ( PatchListFormat )
import Darcs.Patch.Info ( PatchInfo, readPatchInfo, showPatchInfo, patchinfo,
piName, displayPatchInfo, makePatchname, invertName )
import Darcs.Patch.Merge ( Merge(..) )
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(..), ShowContextPatch(..), ShowPatchFor(..) )
import Darcs.Patch.Summary ( plainSummary )
import Darcs.Patch.Viewing ()
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
( Doc, ($$), (<+>), (<>), prefix, text, vcat, cyanText, blueText )
data Named p wX wY where
NamedP :: !PatchInfo
-> ![PatchInfo]
-> !(FL p wX wY)
-> Named p wX wY
deriving Show
instance PrimPatchBase p => PrimPatchBase (Named p) where
type PrimOf (Named p) = PrimOf p
instance Effect p => Effect (Named p) where
effect (NamedP _ _ p) = effect p
effectRL (NamedP _ _ p) = effectRL p
instance IsHunk (Named p) where
isHunk _ = Nothing
instance PatchListFormat (Named p)
instance (ReadPatch p, PatchListFormat p) => ReadPatch (Named p) where
readPatch' = readNamed
readNamed :: (ReadPatch p, PatchListFormat p, ParserM m) => m (Sealed (Named p wX))
readNamed
= do n <- readPatchInfo
d <- readDepends
p <- readPatch'
return $ (NamedP n d) `mapSeal` p
readDepends :: ParserM m => m [PatchInfo]
readDepends =
option [] $ do lexChar '<'
readPis
readPis :: ParserM m => m [PatchInfo]
readPis = choice [ do pi <- readPatchInfo
pis <- readPis
return (pi:pis)
, do skipWhile (/= '>')
_ <- anyChar
return [] ]
instance Apply p => Apply (Named p) where
type ApplyState (Named p) = ApplyState p
apply (NamedP _ _ p) = apply p
instance RepairToFL p => Repair (Named p) where
applyAndTryToFix (NamedP n d p) = mapMaybeSnd (NamedP n d) `fmap` applyAndTryToFix p
namepatch :: String -> String -> String -> [String] -> FL p wX wY -> IO (Named p wX wY)
namepatch date name author desc p
| '\n' `elem` name = error "Patch names cannot contain newlines."
| otherwise = do pinf <- patchinfo date name author desc
return $ NamedP pinf [] p
anonymous :: FL p wX wY -> IO (Named p wX wY)
anonymous p = namepatch "today" "anonymous" "unknown" ["anonymous"] p
infopatch :: PatchInfo -> FL p wX wY -> Named p wX wY
infopatch pi p = NamedP pi [] p
adddeps :: Named p wX wY -> [PatchInfo] -> Named p wX wY
adddeps (NamedP pi _ p) ds = NamedP pi ds p
getdeps :: Named p wX wY -> [PatchInfo]
getdeps (NamedP _ ds _) = ds
patch2patchinfo :: Named p wX wY -> PatchInfo
patch2patchinfo (NamedP i _ _) = i
patchname :: Named p wX wY -> String
patchname (NamedP i _ _) = show $ makePatchname i
patchcontents :: Named p wX wY -> FL p wX wY
patchcontents (NamedP _ _ p) = p
fmapNamed :: (forall wA wB . p wA wB -> q wA wB) -> Named p wX wY -> Named q wX wY
fmapNamed f (NamedP i deps p) = NamedP i deps (mapFL_FL f p)
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, Eq2 p) => Eq2 (Named p) where
unsafeCompare (NamedP n1 d1 p1) (NamedP n2 d2 p2) =
n1 == n2 && d1 == d2 && unsafeCompare p1 p2
instance Invert p => Invert (Named p) where
invert (NamedP n d p) = NamedP (invertName n) (map invertName d) (invert p)
instance Commute p => Commute (Named p) where
commute (NamedP n1 d1 p1 :> NamedP n2 d2 p2) =
if n2 `elem` d1 || n1 `elem` d2
then Nothing
else do (p2' :> p1') <- commute (p1 :> p2)
return (NamedP n2 d2 p2' :> NamedP n1 d1 p1')
commuterIdNamed :: CommuteFn p1 p2 -> CommuteFn p1 (Named p2)
commuterIdNamed commuter (p1 :> NamedP n2 d2 p2) =
do p2' :> p1' <- commuterIdFL commuter (p1 :> p2)
return (NamedP n2 d2 p2' :> p1')
commuterNamedId :: CommuteFn p1 p2 -> CommuteFn (Named p1) p2
commuterNamedId commuter (NamedP n1 d1 p1 :> p2) =
do p2' :> p1' <- commuterFLId commuter (p1 :> p2)
return (p2' :> NamedP n1 d1 p1')
instance Merge p => Merge (Named p) where
merge (NamedP n1 d1 p1 :\/: NamedP n2 d2 p2)
= case merge (p1 :\/: p2) of
(p2' :/\: p1') -> NamedP n2 d2 p2' :/\: NamedP n1 d1 p1'
mergerIdNamed :: MergeFn p1 p2 -> MergeFn p1 (Named p2)
mergerIdNamed merger (p1 :\/: NamedP n2 d2 p2) =
case mergerIdFL merger (p1 :\/: p2) of
p2' :/\: p1' -> NamedP n2 d2 p2' :/\: p1'
instance PatchInspect p => PatchInspect (Named p) where
listTouchedFiles (NamedP _ _ p) = listTouchedFiles p
hunkMatches f (NamedP _ _ p) = hunkMatches f p
instance (CommuteNoConflicts p, Conflict p) => Conflict (Named p) where
resolveConflicts (NamedP _ _ p) = resolveConflicts p
conflictedEffect (NamedP _ _ p) = conflictedEffect p
instance Check p => Check (Named p) where
isInconsistent (NamedP _ _ p) = isInconsistent p
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 f (NamedP n d p) = showNamedPrefix f n d $ showPatch f 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
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)
summaryFL = vcat . mapFL summary
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
instance Show2 p => Show2 (Named p) where
showDict2 = ShowDictClass
instance PatchDebug p => PatchDebug (Named p)