{-# LANGUAGE ViewPatterns #-}
module Darcs.Patch.V3.Contexted
(
Contexted
, ctxId
, ctxView
, ctxNoConflict
, ctxToFL
, ctx
, ctxAdd
, ctxAddRL
, ctxAddInvFL
, ctxAddFL
, commutePast
, commutePastRL
, ctxTouches
, ctxHunkMatches
, showCtx
, readCtx
, prop_ctxInvariants
, prop_ctxEq
, prop_ctxPositive
) where
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as BC ( pack )
import Data.Maybe ( isNothing, isJust )
import Darcs.Prelude
import Darcs.Patch.Commute
import Darcs.Patch.Format ( PatchListFormat(..) )
import Darcs.Patch.Ident
import Darcs.Patch.Invert
import Darcs.Patch.Inspect
import Darcs.Patch.Merge ( CleanMerge(..) )
import Darcs.Patch.Read ( ReadPatch(..) )
import Darcs.Util.Parser ( Parser, lexString )
import Darcs.Patch.Show ( ShowPatchBasic(..), ShowPatchFor )
import Darcs.Patch.Viewing ()
import Darcs.Patch.Witnesses.Eq
import Darcs.Patch.Witnesses.Ordered
import Darcs.Patch.Witnesses.Sealed
import Darcs.Patch.Witnesses.Show
import Darcs.Util.Path ( AnchoredPath )
import Darcs.Util.Printer
data Contexted p wX where
Contexted :: FL p wX wY -> p wY wZ -> Contexted p wX
instance Ident p => Eq (Contexted p wX) where
c1 == c2 = ctxId c1 == ctxId c2
instance Ident p => Ord (Contexted p wX) where
cp `compare` cq = ctxId cp `compare` ctxId cq
instance Show2 p => Show (Contexted p wX) where
showsPrec d (Contexted ps p) =
showParen (d > appPrec) $ showString "Contexted " .
showsPrec2 (appPrec + 1) ps . showString " " .
showsPrec2 (appPrec + 1) p
instance Show2 p => Show1 (Contexted p)
prop_ctxInvariants :: (Commute p, Invert p, SignedIdent p) => Contexted p wX -> Bool
prop_ctxInvariants (Contexted NilFL _) = True
prop_ctxInvariants c@(Contexted (_ :>: ps) q) =
prop_ctxInvariants (Contexted ps q) && prop_ctxNotCom c && prop_ctxNotInv c
prop_ctxNotCom :: Commute p => Contexted p wX -> Bool
prop_ctxNotCom (Contexted NilFL _) = True
prop_ctxNotCom (Contexted (p :>: ps) q) =
isNothing $ commuteFL (p :> ps +>+ q :>: NilFL)
prop_ctxPositive :: SignedIdent p => Contexted p wX -> Bool
prop_ctxPositive (Contexted ps p) =
allFL (positiveId . ident) ps && positiveId (ident p)
prop_ctxNotInv :: SignedIdent p => Contexted p wX -> Bool
prop_ctxNotInv (Contexted NilFL _) = True
prop_ctxNotInv (Contexted (p :>: ps) _) =
invertId (ident p) `notElem` mapFL ident ps
prop_ctxEq :: (Commute p, Eq2 p, Ident p) => Contexted p wX -> Contexted p wX -> Bool
prop_ctxEq cp@(Contexted ps p) cq@(Contexted qs q)
| cp == cq =
case ps =\/= qs of
IsEq -> isIsEq (p =\/= q)
NotEq -> False
prop_ctxEq _ _ = True
{-# INLINE ctxId #-}
ctxId :: Ident p => Contexted p wX -> PatchId p
ctxId (Contexted _ p) = ident p
ctxNoConflict :: (CleanMerge p, Commute p, Ident p)
=> Contexted p wX -> Contexted p wX -> Bool
ctxNoConflict cp cq | cp == cq = True
ctxNoConflict (Contexted ps p) (Contexted qs q)
| ident p `elem` mapFL ident qs || ident q `elem` mapFL ident ps = False
| otherwise =
case findCommonFL ps qs of
Fork _ ps' qs' ->
isJust $ cleanMerge (ps' +>+ p :>: NilFL :\/: qs' +>+ q :>: NilFL)
ctxView :: Contexted p wX -> Sealed ((FL p :> p) wX)
ctxView (Contexted cs p) = Sealed (cs :> p)
ctxToFL :: Contexted p wX -> Sealed (FL p wX)
ctxToFL (ctxView -> Sealed (ps :> p)) = Sealed (ps +>+ p :>: NilFL)
ctx :: p wX wY -> Contexted p wX
ctx p = Contexted NilFL p
ctxAdd :: (Commute p, Invert p, Ident p)
=> p wX wY -> Contexted p wY -> Contexted p wX
ctxAdd p (Contexted ps q)
| Just ps' <- fastRemoveFL (invert p) ps = Contexted ps' q
ctxAdd p c@(Contexted ps q) =
case commutePast p c of
Just c' -> c'
Nothing -> Contexted (p :>: ps) q
ctxAddRL :: (Commute p, Invert p, Ident p)
=> RL p wX wY -> Contexted p wY -> Contexted p wX
ctxAddRL NilRL cp = cp
ctxAddRL (ps :<: p) cp = ctxAddRL ps (ctxAdd p cp)
ctxAddInvFL :: (Commute p, Invert p, Ident p)
=> FL p wX wY -> Contexted p wX -> Contexted p wY
ctxAddInvFL = ctxAddRL . invertFL
ctxAddFL :: (Commute p, Invert p, Ident p)
=> FL p wX wY -> Contexted p wY -> Contexted p wX
ctxAddFL NilFL t = t
ctxAddFL (p :>: ps) t = ctxAdd p (ctxAddFL ps t)
commutePast :: Commute p
=> p wX wY -> Contexted p wY -> Maybe (Contexted p wX)
commutePast q (Contexted ps p) = do
ps' :> q' <- commuteFL (q :> ps)
p' :> _ <- commute (q' :> p)
return (Contexted ps' p')
commutePastRL :: Commute p
=> RL p wX wY -> Contexted p wY -> Maybe (Contexted p wX)
commutePastRL = foldRL_M commutePast
ctxTouches :: PatchInspect p => Contexted p wX -> [AnchoredPath]
ctxTouches (Contexted ps p) =
concat $ listTouchedFiles p : mapFL listTouchedFiles ps
ctxHunkMatches :: PatchInspect p => (B.ByteString -> Bool)
-> Contexted p wX -> Bool
ctxHunkMatches f (Contexted ps p) = hunkMatches f ps || hunkMatches f p
showCtx :: (ShowPatchBasic p, PatchListFormat p)
=> ShowPatchFor -> Contexted p wX -> Doc
showCtx f (Contexted c p) =
hiddenPrefix "|" (showPatch f c) $$ hiddenPrefix "|" (blueText ":") $$ showPatch f p
readCtx :: (ReadPatch p, PatchListFormat p)
=> Parser (Contexted p wX)
readCtx = do
Sealed ps <- readPatch'
lexString (BC.pack ":")
Sealed p <- readPatch'
return $ Contexted ps p