[darcs-users] Darcs equivalent of force-pushing and branching

Ben Franksen ben.franksen at online.de
Tue Sep 14 11:38:53 UTC 2021


Am 13.09.21 um 22:17 schrieb James Cook:
> On Fri, Sep 10, 2021 at 08:19:29PM +0900, Stephen J. Turnbull wrote:
>> All of this is obviously quite possible with Darcs.  The problem is
>> getting the "accounting" right when separating the management of
>> *sets* of patches from the management of *histories*.

True, but this problem is already solved. In our code base there is no 
explicit representation for "set of patches", we always treat them 
internally as sequences. Two sequences may or may not be equivalent in 
the sense that they represent "the same set of patches" (nominally 
speaking i.e. "same set of patch identities"). Indeed, since we use 
phantom types for the start and end context of any patch or sequence of 
patches, any two sequences of the same type must be equivalent in this 
sense. This has the notable consequence that none of our patch types 
have a standard instance for (homegenous) equality, as that would be 
trivial i.e. always return True. Instead, our two equality operators are 
heterogeneous: they require (only) the start /or/ the end contexts to 
coincide and (if comparison succeeds) return a proof of equality between 
(the phantom types symbolizing) the two remaining contexts. This makes 
the manipulation of sequences (re-arrangement, merging, etc) pretty easy 
and safe, because almost all the mistakes you can make become type errors.

[The flip side is that we also make extensive use of laziness, including 
unsafeInterleaveIO when reading patches from disk, which means that 
semantically transparent changes can have devastating consequences for 
performance or even lead to bugs when transfering patches (because we 
may store too few or too many patch or inventory files).]

>> IIRC, in Darcs
>> the history is in the patches, which means a bit of tedious surgery on
>> data structures needs to be done.
> 
> I'm not sure what you mean by "histories" as distinct from "sets of
> patches". Shouldn't a branch just be a set of patches?

Definitely.

It is /not/ true that in Darcs "the history is in the patches", quite 
the opposite in fact: a patch by itself, as read from disk, makes no 
sense without a context i.e. the set of patches preceding it. The 
history is explicitly stored on disk, separately from the patches 
themselves (in the form of "inventories"). To see that, you can look at 
_darcs/hashed_inventory, which is a plain text file listing the patches 
(since the last clean tag) in order from earliest to latest. For each 
patch, it contains its PatchInfo (meta data) plus a sha256 hash of its 
content /in this specific context/. It also contains a hash of the tree 
corresponding to the "HEAD" (the recorded state, including the content 
of all tracked files).

Technically seen, it would be a simple thing to allow multiple such 
files to coexist in a repository, one of them being chosen as the 
"current" one; IOW branches. Since each has its own tree hash, 
calculating the diff between any two branch heads is cheap, as is 
replacing the working tree with the recorded state of another branch 
("checkout"). (Naturally, comparing or checkout of intermediate states 
is more involved: for this we have to unapply patches from the end state.)

The only non-trivial problems on the way toward internal branches in 
Darcs are (1) design and implementation of the UI and (2) maintaining 
compatibility between repositories and Darcs versions.

Cheers
Ben
-- 
I would rather have questions that cannot be answered, than answers that
cannot be questioned.  -- Richard Feynman




More information about the darcs-users mailing list