module Darcs.Patch.Prim.Class ( PrimConstruct(..), PrimCanonize(..) , PrimClassify(..), PrimDetails(..) , PrimSift(..) , PrimShow(..), PrimRead(..) , PrimApply(..) , PrimPatch , PrimMangleUnravelled(..) , Mangled , Unravelled , primCleanMerge ) where import Darcs.Prelude import Darcs.Patch.ApplyMonad ( ApplyMonad ) import Darcs.Patch.FileHunk ( FileHunk, IsHunk ) import Darcs.Patch.Format ( FileNameFormat, PatchListFormat ) import Darcs.Patch.Inspect ( PatchInspect ) import Darcs.Patch.Apply ( Apply(..) ) import Darcs.Patch.Commute ( Commute(..) ) import Darcs.Patch.CommuteFn ( PartialMergeFn ) import Darcs.Patch.Invert ( Invert(..) ) import Darcs.Patch.Merge ( CleanMerge(..) ) import Darcs.Patch.Read ( ReadPatch ) import Darcs.Patch.Repair ( RepairToFL ) import Darcs.Patch.Show ( ShowPatch, ShowContextPatch ) import Darcs.Patch.SummaryData ( SummDetail ) import Darcs.Patch.Witnesses.Eq ( Eq2(..) ) import Darcs.Patch.Witnesses.Ordered ( FL, (:>)(..), (:\/:)(..), (:/\:)(..) ) import Darcs.Patch.Witnesses.Show ( Show2 ) import Darcs.Patch.Witnesses.Sealed ( Sealed ) import Darcs.Util.Parser ( Parser ) import Darcs.Util.Path ( AnchoredPath ) import Darcs.Util.Printer ( Doc ) import qualified Darcs.Util.Diff as D ( DiffAlgorithm ) import qualified Data.ByteString as B ( ByteString ) type PrimPatch prim = ( Apply prim , CleanMerge 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 , PrimSift prim , PrimMangleUnravelled prim , ReadPatch prim , ShowPatch prim , ShowContextPatch prim , PatchListFormat prim ) class PrimClassify prim where primIsAddfile :: prim wX wY -> Bool primIsRmfile :: prim wX wY -> Bool primIsAdddir :: prim wX wY -> Bool primIsRmdir :: prim wX wY -> Bool primIsMove :: prim wX wY -> Bool primIsHunk :: prim wX wY -> Bool primIsTokReplace :: prim wX wY -> Bool primIsBinary :: prim wX wY -> Bool primIsSetpref :: prim wX wY -> Bool is_filepatch :: prim wX wY -> Maybe AnchoredPath class PrimConstruct prim where addfile :: AnchoredPath -> prim wX wY rmfile :: AnchoredPath -> prim wX wY adddir :: AnchoredPath -> prim wX wY rmdir :: AnchoredPath -> prim wX wY move :: AnchoredPath -> AnchoredPath -> prim wX wY changepref :: String -> String -> String -> prim wX wY hunk :: AnchoredPath -> Int -> [B.ByteString] -> [B.ByteString] -> prim wX wY tokreplace :: AnchoredPath -> String -> String -> String -> prim wX wY binary :: AnchoredPath -> B.ByteString -> B.ByteString -> prim wX wY primFromHunk :: FileHunk wX wY -> prim wX wY class PrimCanonize prim where -- | @tryToShrink ps@ simplifies @ps@ by getting rid of self-cancellations -- or coalescing patches -- -- Question (Eric Kow): what properties should this have? For example, -- the prim1 implementation only gets rid of the first self-cancellation -- it finds (as far as I can tell). Is that OK? Can we try harder? tryToShrink :: FL prim wX wY -> FL prim wX wY -- | 'sortCoalesceFL' @ps@ coalesces as many patches in @ps@ as -- possible, sorting the results in some standard order. sortCoalesceFL :: FL prim wX wY -> FL prim wX wY -- | It can sometimes be handy to have a canonical representation of a given -- patch. We achieve this by defining a canonical form for each patch type, -- and a function 'canonize' which takes a patch and puts it into -- canonical form. This routine is used by the diff function to create an -- optimal patch (based on an LCS algorithm) from a simple hunk describing the -- old and new version of a file. canonize :: D.DiffAlgorithm -> prim wX wY -> FL prim wX wY -- | 'canonizeFL' @ps@ puts a sequence of primitive patches into -- canonical form. Even if the patches are just hunk patches, -- this is not necessarily the same set of results as you would get -- if you applied the sequence to a specific tree and recalculated -- a diff. -- -- Note that this process does not preserve the commutation behaviour -- of the patches and is therefore not appropriate for use when -- working with already recorded patches (unless doing amend-record -- or the like). canonizeFL :: D.DiffAlgorithm -> FL prim wX wY -> FL prim wX wY -- | Either 'primCoalesce' or cancel inverses. -- -- prop> primCoalesce (p :> q) == Just r => apply r = apply p >> apply q -- prop> primCoalesce (p :> q) == Just r => lengthFL r < 2 coalesce :: (prim :> prim) wX wY -> Maybe (FL prim wX wY) -- | Coalesce adjacent patches to one with the same effect. -- -- prop> apply (primCoalesce p q) == apply p >> apply q primCoalesce :: prim wX wY -> prim wY wZ -> Maybe (prim wX wZ) -- | If 'primCoalesce' is addition, then this is subtraction. -- -- prop> Just r == primCoalesce p q => primDecoalesce r p == Just q primDecoalesce :: prim wX wZ -> prim wX wY -> Maybe (prim wY wZ) -- TODO This has been cut'n'pasted from Darcs.Repository.Pending. -- It is not a good interface and should be re-designed. class PrimSift prim where -- | @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 :: FL prim wX wY -> Sealed (FL prim wX) class PrimDetails prim where summarizePrim :: prim wX wY -> [SummDetail] class PrimShow prim where showPrim :: FileNameFormat -> prim wA wB -> Doc showPrimCtx :: ApplyMonad (ApplyState prim) m => FileNameFormat -> prim wA wB -> m Doc class PrimRead prim where readPrim :: FileNameFormat -> Parser (Sealed (prim wX)) class PrimApply prim where applyPrimFL :: ApplyMonad (ApplyState prim) m => FL prim wX wY -> m () -- | A list of conflicting alternatives. They form a connected -- component of the conflict graph i.e. one transitive conflict. type Unravelled prim wX = [Sealed (FL prim wX)] -- | Result of mangling a single Unravelled. type Mangled prim wX = Sealed (FL prim wX) class PrimMangleUnravelled prim where -- | Mangle conflicting alternatives if possible. mangleUnravelled :: Unravelled prim wX -> Maybe (Mangled prim wX) primCleanMerge :: (Commute prim, Invert prim) => PartialMergeFn prim prim primCleanMerge (p :\/: q) = do q' :> ip' <- commute (invert p :> q) return $ q' :/\: invert ip'