darcs-2.16.1: src/Darcs/Patch/Conflict.hs
-- Copyright (C) 2002-2003 David Roundy, 2010 Ganesh Sittampalam
module Darcs.Patch.Conflict
( Conflict(..)
, ConflictDetails(..)
, Mangled
, Unravelled
, mangleOrFail
, combineConflicts
) where
import Darcs.Prelude
import Darcs.Patch.CommuteFn ( commuterIdFL )
import Darcs.Patch.CommuteNoConflicts ( CommuteNoConflicts(..) )
import Darcs.Patch.Permutations ()
import Darcs.Patch.FromPrim ( PrimOf )
import Darcs.Patch.Prim ( PrimMangleUnravelled(..), Mangled, Unravelled )
import Darcs.Patch.Witnesses.Ordered ( FL(..), RL(..), (:>)(..) )
data ConflictDetails prim wX =
ConflictDetails {
conflictMangled :: Maybe (Mangled prim wX),
conflictParts :: Unravelled prim wX
}
mangleOrFail :: PrimMangleUnravelled prim
=> Unravelled prim wX -> ConflictDetails prim wX
mangleOrFail parts =
ConflictDetails {
conflictMangled = mangleUnravelled parts,
conflictParts = parts
}
class Conflict p where
-- | The first parameter is a context containing all patches
-- preceding the ones for which we want to calculate the conflict
-- resolution, which is the second parameter.
-- Each element of the result list represents the resolution
-- of one maximal set of transitively conflicting alternatives,
-- in other words, a connected subset of the conflict graph.
-- But the elements themselves must not conflict with each other,
-- guaranteeing that they can be cleanly merged into a single 'FL' of prims.
resolveConflicts :: RL p wO wX -> RL p wX wY -> [ConflictDetails (PrimOf p) wY]
-- | By definition, a conflicting patch is resolved if another patch
-- (that is not itself conflicted) depends on the conflict. If the
-- representation of conflicts is self-contained as it is for V1 and V2,
-- then we can calculate the maximal set of conflicting alternatives for
-- a conflict separately for each conflictor at the end of a repo.
-- This function can then be used to lift this to an 'RL' of patches.
--
-- So, when looking for conflicts in a list of patches, we go
-- through the whole list looking for individual patches that represent
-- a conflict. But then we try to commute them past all the
-- patches we've already seen. If we fail, i.e. there's something
-- that depends on the conflict, then we forget about the conflict;
-- this is the Nothing case of the 'commuteNoConflictsFL' call.
-- Otherwise the patch is now in the correct position to extract the
-- conflicting alternatives.
combineConflicts
:: forall p wX wY. CommuteNoConflicts p
=> (forall wA wB. p wA wB -> [Unravelled (PrimOf p) wB])
-> RL p wX wY -> [Unravelled (PrimOf p) wY]
combineConflicts resolveOne x = rcs x NilFL
where
rcs :: RL p wX wM -> FL p wM wY -> [Unravelled (PrimOf p) wY]
rcs NilRL _ = []
rcs (ps :<: p) passedby
| null (resolveOne p) = seq passedby rest -- TODO why seq here?
| otherwise =
case commuterIdFL commuteNoConflicts (p :> passedby) of
Just (_ :> p') -> resolveOne p' ++ rest
Nothing -> rest
where
rest = rcs ps (p :>: passedby)