{-# LANGUAGE UndecidableInstances #-}
module Darcs.Patch.Rebase.Fixup
( RebaseFixup(..)
, commuteNamedFixup, commuteFixupNamed
, pushFixupFixup
, flToNamesPrims, namedToFixups
) where
import Darcs.Prelude
import Darcs.Patch.Apply ( Apply(..) )
import Darcs.Patch.Commute ( Commute(..), selfCommuter )
import Darcs.Patch.CommuteFn ( totalCommuterIdFL )
import Darcs.Patch.Effect ( Effect(..) )
import Darcs.Patch.Inspect ( PatchInspect(..) )
import Darcs.Patch.Invert ( Invert(..) )
import Darcs.Patch.Named ( Named(..) )
import Darcs.Patch.Format ( PatchListFormat )
import Darcs.Patch.FromPrim ( PrimPatchBase(..) )
import Darcs.Patch.Prim ( PrimPatch, canonizeFL )
import Darcs.Patch.Read ( ReadPatch(..) )
import Darcs.Patch.Rebase.Name
( RebaseName(..)
, commuteNamedName, commuteNameNamed
, commuterNamedId, commuterIdNamed
, commutePrimName, commuteNamePrim
, pushFixupName
)
import Darcs.Patch.Rebase.PushFixup ( PushFixupFn )
import Darcs.Patch.Show ( ShowPatchBasic(..) )
import Darcs.Patch.Witnesses.Eq ( Eq2(..), EqCheck(..) )
import Darcs.Patch.Witnesses.Maybe ( Maybe2(..), mapMB_MB )
import Darcs.Patch.Witnesses.Ordered
( FL(..), mapFL_FL, (:>)(..) )
import Darcs.Patch.Witnesses.Sealed ( Sealed, mapSeal )
import Darcs.Patch.Witnesses.Show ( Show1, Show2, showsPrec2, appPrec )
import qualified Darcs.Util.Diff as D ( DiffAlgorithm )
import Darcs.Util.Parser ( Parser, lexString )
import Darcs.Util.Printer ( ($$), (<+>), blueText )
import Control.Applicative ( (<|>) )
import qualified Data.ByteString as B ( ByteString )
import qualified Data.ByteString.Char8 as BC ( pack )
data RebaseFixup prim wX wY where
PrimFixup :: prim wX wY -> RebaseFixup prim wX wY
NameFixup :: RebaseName wX wY -> RebaseFixup prim wX wY
namedToFixups :: (PrimPatch (PrimOf p), Effect p) => Named p wX wY -> FL (RebaseFixup (PrimOf p)) wX wY
namedToFixups (NamedP p _ contents) = NameFixup (AddName p) :>: mapFL_FL PrimFixup (effect contents)
instance Show2 prim => Show (RebaseFixup prim wX wY) where
showsPrec d (PrimFixup p) =
showParen (d > appPrec) $ showString "PrimFixup " . showsPrec2 (appPrec + 1) p
showsPrec d (NameFixup p) =
showParen (d > appPrec) $ showString "NameFixup " . showsPrec2 (appPrec + 1) p
instance Show2 prim => Show1 (RebaseFixup prim wX)
instance Show2 prim => Show2 (RebaseFixup prim)
instance PrimPatch prim => PrimPatchBase (RebaseFixup prim) where
type PrimOf (RebaseFixup prim) = prim
instance Apply prim => Apply (RebaseFixup prim) where
type ApplyState (RebaseFixup prim) = ApplyState prim
apply (PrimFixup p) = apply p
apply (NameFixup _) = return ()
unapply (PrimFixup p) = unapply p
unapply (NameFixup _) = return ()
instance Invert prim => Invert (RebaseFixup prim) where
invert (PrimFixup p) = PrimFixup (invert p)
invert (NameFixup n) = NameFixup (invert n)
instance PatchInspect prim => PatchInspect (RebaseFixup prim) where
listTouchedFiles (PrimFixup p) = listTouchedFiles p
listTouchedFiles (NameFixup n) = listTouchedFiles n
hunkMatches f (PrimFixup p) = hunkMatches f p
hunkMatches f (NameFixup n) = hunkMatches f n
instance PatchListFormat (RebaseFixup prim)
instance ShowPatchBasic prim => ShowPatchBasic (RebaseFixup prim) where
showPatch f (PrimFixup p) =
blueText "rebase-fixup" <+> blueText "(" $$ showPatch f p $$ blueText ")"
showPatch f (NameFixup p) =
blueText "rebase-name" <+> blueText "(" $$ showPatch f p $$ blueText ")"
instance ReadPatch prim => ReadPatch (RebaseFixup prim) where
readPatch' =
mapSeal PrimFixup <$> readWith (BC.pack "rebase-fixup" ) <|>
mapSeal NameFixup <$> readWith (BC.pack "rebase-name" )
where
readWith :: forall q wX . ReadPatch q => B.ByteString -> Parser (Sealed (q wX))
readWith str = do
lexString str
lexString (BC.pack "(")
res <- readPatch'
lexString (BC.pack ")")
return res
instance Commute prim => Commute (RebaseFixup prim) where
commute (PrimFixup p :> PrimFixup q) = do
q' :> p' <- commute (p :> q)
return (PrimFixup q' :> PrimFixup p')
commute (NameFixup p :> NameFixup q) = do
q' :> p' <- commute (p :> q)
return (NameFixup q' :> NameFixup p')
commute (PrimFixup p :> NameFixup q) = do
q' :> p' <- return $ commutePrimName (p :> q)
return (NameFixup q' :> PrimFixup p')
commute (NameFixup p :> PrimFixup q) = do
q' :> p' <- return $ commuteNamePrim (p :> q)
return (PrimFixup q' :> NameFixup p')
pushFixupPrim
:: PrimPatch prim
=> D.DiffAlgorithm
-> PushFixupFn prim prim (FL prim) (Maybe2 prim)
pushFixupPrim da (f1 :> f2)
| IsEq <- isInverse = NilFL :> Nothing2
| otherwise
= case commute (f1 :> f2) of
Nothing -> canonizeFL da (f1 :>: f2 :>: NilFL) :> Nothing2
Just (f2' :> f1') -> (f2' :>: NilFL) :> Just2 f1'
where isInverse = invert f1 =\/= f2
pushFixupFixup
:: PrimPatch prim
=> D.DiffAlgorithm
-> PushFixupFn
(RebaseFixup prim) (RebaseFixup prim)
(FL (RebaseFixup prim)) (Maybe2 (RebaseFixup prim))
pushFixupFixup da (PrimFixup f1 :> PrimFixup f2)
= case pushFixupPrim da (f1 :> f2) of
fs2' :> f1' -> mapFL_FL PrimFixup fs2' :> mapMB_MB PrimFixup f1'
pushFixupFixup _da (PrimFixup f :> NameFixup n)
= case commutePrimName (f :> n) of
n' :> f' -> (NameFixup n' :>: NilFL) :> Just2 (PrimFixup f')
pushFixupFixup _da (NameFixup n1 :> NameFixup n2)
= case pushFixupName (n1 :> n2) of
ns2' :> n1' -> mapFL_FL NameFixup ns2' :> mapMB_MB NameFixup n1'
pushFixupFixup _da (NameFixup n :> PrimFixup f)
= case commuteNamePrim (n :> f) of
f' :> n' -> (PrimFixup f' :>: NilFL) :> Just2 (NameFixup n')
flToNamesPrims :: FL (RebaseFixup prim) wX wY
-> (FL RebaseName :> FL prim) wX wY
flToNamesPrims NilFL = NilFL :> NilFL
flToNamesPrims (NameFixup n :>: fs) =
case flToNamesPrims fs of
names :> prims -> (n :>: names) :> prims
flToNamesPrims (PrimFixup p :>: fs) =
case flToNamesPrims fs of
names :> prims ->
case totalCommuterIdFL commutePrimName (p :> names) of
names' :> p' -> names' :> (p' :>: prims)
commuteNamedFixup
:: Commute prim
=> (Named prim :> RebaseFixup prim) wX wY
-> Maybe ((RebaseFixup prim :> Named prim) wX wY)
commuteNamedFixup (p :> PrimFixup q) = do
q' :> p' <- commuterNamedId selfCommuter (p :> q)
return (PrimFixup q' :> p')
commuteNamedFixup (p :> NameFixup n) = do
n' :> p' <- commuteNamedName (p :> n)
return (NameFixup n' :> p')
commuteFixupNamed
:: Commute prim
=> (RebaseFixup prim :> Named prim) wX wY
-> Maybe ((Named prim :> RebaseFixup prim) wX wY)
commuteFixupNamed (PrimFixup p :> q) = do
q' :> p' <- commuterIdNamed selfCommuter (p :> q)
return (q' :> PrimFixup p')
commuteFixupNamed (NameFixup n :> q) = do
q' :> n' <- commuteNameNamed (n :> q)
return (q' :> NameFixup n')