|Version 2 (modified by lele, 7 years ago) (diff)|
Better (maybe even right) recipes for two-way sync
The development of tailor started right from this need, and if it's still a little flaky it's because the need fade away. Luckily other people keeps hinting about proper solution to the problem (as ticket #1 witnesses)
Let there be two tailor directories, once which ports patches from svn to darcs (called "SD" from here on) and one which ports patches from darcs to svn (called "DS" from here on). Each of these tailor directories contains an svn working dir subdirectory (called "SDs" or "DSs") and a darcs repo subdirectory (called "SDd" or "DSd").
In addition there is (of course) the SVN repo "SO" and an "official" darcs repo "DO".
Let "the internally consistent condition" be such that the contents of all four of the subdirectories SDs, SDd, DSs, and DSd are up-to-date with each other, and furthermore that SDs and DSs are each a subset of SO (i.e., svn diff would show no changes) and SDd and DSd are each a subset of DO (i.e. darcs push DO would have no effect).
Subroutine C will return to the internally consistent state when it completes, if possible. If it is not possible to return to the internally consistent state then there is a conflict which has to be resolved by the user.
Let "the up-to-date condition" be such that the contents of all six of SDs, SDd, DSs, DSd, SO, and DO are up-to-date with each other. The up-to-date condition implies the internally-consistent condition. The complete Algorithm -- Algorithm D will result in the up-to-date state unless there is a conflict or unless new patches are added to SO or to DO after the algorithm has checked for new patches and before it terminates.
I'll first show three subroutines and then show the complete algorithm.
Subroutine A: translate the next patch from SVN to darcs
- Use tailor in the SD directory to translate the next patch from SVN to darcs. This will update SDs to that revision and add a new patch into SDd. Let REVNUMBER be the svn revision number of the original svn patch and let HASH be the darcs identifier of the newly created darcs patch.
- Use darcs push --match='hash $HASH' to push the resulting darcs patch from the SDd to DO (where HASH is equal to the hash of the patch which was just created). If the push fails for the reason that pushing would cause a conflict in DO then this algorithm must stop and notify the user of a conflict condition.
- Run svn up -r$REVNUMBER in DSs (note: not SDs), with REVNUMBER equal to the revision number of the patch that was translated from SVN world in step A1.
- Run darcs pull --match='hash $HASH' in DSd (note: not SDd), with HASH equal to the hash of the patch which was created in darcs world in step A1.
Subroutine B: translate the next patch from darcs to SVN
- Use tailor in the DS directory to translate the next patch from darcs to SVN. This will pull the next patch from DO into DSd and create a new revision in DSs and attempt to commit it to SO. Let REVNUMBER be the SVN revision number of this patch.
- If the attempt to commit the new patch to SO fails due to merge conflict then this algorithm must stop and notify the user of a conflict condition.
- Verify that there were no changes in SO between the previous REVNUMBER from the last time step B4 was run (if any) and the current REVNUMBER. If there were changes in SVN between those two revisions then flag a conflict and stop.
- Run svn up -r$REVNUMBER in SDs (note: not DSs).
- Run darcs pull --match='hash $HASH' in SDd (note: not DSd), with HASH equal to the hash of the patch that was translated from darcs world in step b1.
Observe that the starting from the internally-consistent condition is necessary but not sufficient for Subroutine B to result in the internally-consistent condition. In addition to the internally-consistent condition, another condition is required, namely that SDs is required to have been up-to-date with SO. If SDs was not up-to-date with SO before Subroutine B, then step B4 will, in addition to adding the new patch into SDs also add other patches into SDs which are not also in SDd, violating the internally-consistent condition. This is why step B3 has to be inserted in Subroutine B.
That motivates us to invent this subroutine:
Subroutine C: translate all patches from SVN to darcs and then translate the next patch from darcs to SVN
- Iterate Subroutine A until there are no more patches in SO that are not already in SDs, i.e. that SDs is up-to-date with SO.
- Run Subroutine B.
Algorithm D: translate all patches between worlds
- Iterate Subroutine C until there are no more patches in DO that are not already in DSd, i.e. that DSd is up-to-date with DO.
Now it is safe to invoke Algorithm D whenever you want to synchronize the two worlds. One of three things will happen:
- the worlds will be synchronized
- it will turn out that there is a merge conflict, Algorithm D will stop at that point (either step A2 or else step B2) and notify the user.
- it will turn out that another patch was committed to SO between step C1 and step C2. Algorithm D will stop at that point and notify the user.
Darcs patches which were originally svn patches created by svn commit to SO and then transferred into darcs world by this algorithm can have the SVN revision number inserted into their patch name (e.g. by using the following two tailor options:
patch-name-format = [r%(revision)s] %(firstlogline)s remove-first-log-line = True
However, darcs patches originally created by darcs record and then transferred into svn world by this algorithm will not have the svn revision number in their patch name in darcs world, although of course they will get a revision number assigned to them when translated into svn world. Too bad that there isn't a way to assign revision numbers to the original darcs-world patch without too many sync/conflict issues cropping up.