module Darcs.Patch.Named
( Named(..)
, infopatch
, adddeps
, anonymous
, HasDeps(..)
, patch2patchinfo
, patchname
, patchcontents
, fmapNamed
, fmapFL_Named
, mergerIdNamed
, ShowDepsFormat(..)
, showDependencies
) where
import Darcs.Prelude
import Data.List.Ordered ( nubSort )
import qualified Data.Set as S
import Darcs.Patch.CommuteFn ( MergeFn, commuterIdFL, mergerIdFL )
import Darcs.Patch.Conflict ( Conflict(..) )
import Darcs.Patch.Debug ( PatchDebug(..) )
import Darcs.Patch.Effect ( Effect(effect) )
import Darcs.Patch.FileHunk ( IsHunk(..) )
import Darcs.Patch.Format ( PatchListFormat )
import Darcs.Patch.Info ( PatchInfo, readPatchInfo, showPatchInfo, patchinfo,
piName, displayPatchInfo, makePatchname )
import Darcs.Patch.Merge ( CleanMerge(..), Merge(..) )
import Darcs.Patch.Apply ( Apply(..) )
import Darcs.Patch.Commute ( Commute(..) )
import Darcs.Patch.Ident ( Ident(..), PatchId, IdEq2(..) )
import Darcs.Patch.Inspect ( PatchInspect(..) )
import Darcs.Patch.Permutations ( genCommuteWhatWeCanRL )
import Darcs.Patch.Read ( ReadPatch(..) )
import Darcs.Patch.FromPrim ( PrimPatchBase(..), FromPrim(..) )
import Darcs.Util.Parser ( Parser, option, lexChar,
choice, skipWhile, anyChar )
import Darcs.Patch.Repair ( mapMaybeSnd, Repair(..), RepairToFL, Check(..) )
import Darcs.Patch.Show
( ShowContextPatch(..)
, ShowPatch(..)
, ShowPatchBasic(..)
, ShowPatchFor(..)
, displayPatch
)
import Darcs.Patch.Summary
( Summary(..)
, plainSummaryFL
)
import Darcs.Patch.Unwind ( Unwind(..), squashUnwound )
import Darcs.Patch.Viewing ()
import Darcs.Patch.Witnesses.Eq ( Eq2(..) )
import Darcs.Patch.Witnesses.Ordered
( (:>)(..), (:\/:)(..), (:/\:)(..)
, FL(..), RL(..), mapFL, mapFL_FL, mapRL_RL
, (+>+), concatRLFL, reverseFL
, (+<<+), (+>>+), concatFL
)
import Darcs.Patch.Witnesses.Sealed ( Sealed, mapSeal )
import Darcs.Patch.Witnesses.Show ( Show1, Show2 )
import Darcs.Util.IsoDate ( showIsoDateTime, theBeginning )
import Darcs.Util.Printer
( Doc, ($$), (<+>), 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
type instance PatchId (Named p) = PatchInfo
instance Ident (Named p) where
ident = patch2patchinfo
instance IdEq2 (Named 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) => Parser (Sealed (Named p wX))
readNamed = do n <- readPatchInfo
d <- readDepends
p <- readPatch'
return $ (NamedP n d) `mapSeal` p
readDepends :: Parser [PatchInfo]
readDepends =
option [] $ do lexChar '<'
readPis
readPis :: Parser [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
unapply (NamedP _ _ p) = unapply p
instance RepairToFL p => Repair (Named p) where
applyAndTryToFix (NamedP n d p) = mapMaybeSnd (NamedP n d) `fmap` applyAndTryToFix p
anonymous :: FromPrim p => FL (PrimOf p) wX wY -> IO (Named p wX wY)
anonymous ps = do
info <- patchinfo (showIsoDateTime theBeginning) "anonymous" "unknown" ["anonymous"]
return $ infopatch info ps
infopatch :: forall p wX wY. FromPrim p => PatchInfo -> FL (PrimOf p) wX wY -> Named p wX wY
infopatch pi ps = NamedP pi [] (fromPrims pi ps) where
adddeps :: Named p wX wY -> [PatchInfo] -> Named p wX wY
adddeps (NamedP pi _ p) ds = NamedP pi ds p
class HasDeps p where
getdeps :: p wX wY -> [PatchInfo]
instance HasDeps (Named p) where
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
patchcontentsRL :: RL (Named p) wX wY -> RL p wX wY
patchcontentsRL = concatRLFL . mapRL_RL patchcontents
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 Eq2 (Named p) where
unsafeCompare (NamedP n1 _ _) (NamedP n2 _ _) = n1 == n2
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')
instance CleanMerge p => CleanMerge (Named p) where
cleanMerge (NamedP n1 d1 p1 :\/: NamedP n2 d2 p2)
| n1 == n2 = error "cannot cleanMerge identical Named patches"
| otherwise = do
p2' :/\: p1' <- cleanMerge (p1 :\/: p2)
return $ NamedP n2 d2 p2' :/\: NamedP n1 d1 p1'
instance Merge p => Merge (Named p) where
merge (NamedP n1 d1 p1 :\/: NamedP n2 d2 p2)
| n1 == n2 = error "cannot merge identical Named patches"
| otherwise =
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 (Commute p, Conflict p) => Conflict (Named p) where
resolveConflicts context patches =
case separate S.empty patches NilFL NilFL of
deps :> nondeps ->
resolveConflicts (patchcontentsRL context +<<+ deps) (reverseFL nondeps)
where
separate :: S.Set PatchInfo
-> RL (Named p) w1 w2
-> FL p w2 w3
-> FL p w3 w4
-> (FL p :> FL p) w1 w4
separate acc_deps (ps :<: NamedP name deps contents) resolved unresolved
| name `S.member` acc_deps =
separate (acc_deps +| deps) ps (contents +>+ resolved) unresolved
| otherwise =
case genCommuteWhatWeCanRL (commuterIdFL commute)
(reverseFL contents :> resolved) of
dragged :> resolved' :> more_unresolved ->
separate (acc_deps +| deps) ps
(dragged +>>+ resolved') (more_unresolved +>>+ unresolved)
separate _ NilRL resolved unresolved = resolved :> unresolved
some +| more = foldr S.insert some more
instance (PrimPatchBase p, Unwind p) => Unwind (Named p) where
fullUnwind (NamedP _ _ ps) = squashUnwound (mapFL_FL fullUnwind ps)
instance PatchInspect p => PatchInspect (Named p) where
listTouchedFiles (NamedP _ _ p) = listTouchedFiles p
hunkMatches f (NamedP _ _ p) = hunkMatches f p
instance Summary p => Summary (Named p) where
conflictedEffect = conflictedEffect . patchcontents
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
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
data ShowDepsFormat = ShowDepsVerbose | ShowDepsSummary
deriving (Eq)
showDependencies :: ShowDepsFormat -> [PatchInfo] -> Doc
showDependencies format deps = vcat (map showDependency deps)
where
showDependency d =
mark <+>
cyanText (show (makePatchname d)) $$ asterisk <+> text (piName d)
mark
| format == ShowDepsVerbose = blueText "depend"
| otherwise = text "D"
asterisk = text " *"
instance (Summary p, PatchListFormat p,
PrimPatchBase p, ShowPatch p) => ShowPatch (Named p) where
description (NamedP n _ _) = displayPatchInfo n
summary (NamedP _ ds ps) =
showDependencies ShowDepsSummary ds $$ plainSummaryFL ps
summaryFL nps =
showDependencies ShowDepsSummary ds $$ plainSummaryFL ps
where
ds = nubSort $ concat $ mapFL getdeps nps
ps = concatFL $ mapFL_FL patchcontents nps
content (NamedP _ ds ps) =
showDependencies ShowDepsVerbose ds $$ displayPatch ps
instance Show2 p => Show1 (Named p wX)
instance Show2 p => Show2 (Named p)
instance PatchDebug p => PatchDebug (Named p)