I found out that while the two branches of the project do not (yet)
contain Duplicates or Conflictors, Duplicates do appear when we merge
them. This can be seen by first obliterating 7d7eb29c (including patches
that depend on it), which depends on the duplicates, which causes the
problem.
So this is indeed the well-known fundamental problem with the darcs-1 and
darcs-2 patch semantics and the main reason why both are unsound; and the
reason is that conflicted patches (I am including darcs-2 Duplicates
here) do not track prim patch identities.
As for mitigation, the only possible way I can see is to change the
algorithm for merging patch sequences, so that when commuting common
patches to the tail fails, we still try to merge what remains, even
though there may be residual common patches in the two branches. To make
this work, we need a more robust version of merge (for single patches
with identity), such that merging a patch with itself is not an error:
-- | Like class 'Merge' but defined for every input.
class Merge p => RobustMerge p where
robustMerge :: (p :\/: p) wX wY -> (Maybe2 p :/\: Maybe2 p) wX wY
We then have to replace the generic Merge instance for FL with
instance (Indent p, RobustMerge p) => Merge (FL p)
where we iteratively apply robustMerge, and afterwards filter out the
"null patches" using
-- | Throw out the 'Nothing2's, keep what's in the 'Just2's.
catMaybesFL :: FL (Maybe2 p) wX wY -> FL p wX wY
catMaybesFL (Nothing2 :>: ps) = catMaybes2 ps
catMaybesFL (mp :>: ps) = mp :>: catMaybes2 ps
I will give this a try and see if this allows the merge to succeed.
|