Based on the work in vcs-packaging, I've had some more discussions with other packagers and collected input.

One important reason for using patch systems in the first place seems to be that it is easier to apply them to a new upstream version, because you can do it step by step. Think about a piece of software, were you have 3 features inflicting changes to the source. The 3 are interdependent on each other, and therefore must be applied in order. If the packager wants to upgrade to a new upstream version, he applies the first one, resolves all conflicts and updates the patch, then goes to the next patch.

I've continued to think about this problem, and have a solution how this work flow can be accomplished using a VCS system like bzr or git. Consider the picture below:

:misc:loompoints.png

In the beginning, we have revision 1, the initial upstream import (it doesn't matter at this point if it has a history, like the upstream VCS history, or not). Imagine the package has been managed by dpatch until now, and we want to handle it in bzr. The horizontal lines labeled 'Loom' represent the “Level”, on which the dpatch is based on.

First, we import the first dpatch into bzr. We do it by applying it to the source, resulting in revision 2. After this, we import the second dpatch, resulting in revision 3. We are now in Loom 2, since both patches are applied. So far so good. Now we notice that we want to improve the first dpatch. What do to now? Well, using dpatch, you would first unapply dpatch 2, edit the source and refresh dpatch1. With bzr, you would do the same: Remove commit number 3, edit the source and commit. This time we get another revision, lets call this revision 2.1 for now.

Revision 2.1 represents the most up to date revision of the source containing dpatch one. Lets call it the latest loompoint. We also see that the latest loompoint of dpatch 2 is revision 3. Since we updated loom 1, we need to make sure that dpatch 2 still applies and works. In order to do this, we merge the updated loompoint 1 (revision 2.1) with the loompoint 2 (revision 3), resulting in revision 3.1, which represents the updated loompoint for loom 2. At this point, depending on the changes you've done in revision 2.1 it is possible that this merge is not free of conflicts and you have to solve them manually. That's no problem, the result is an updated dpatch.

You might want to read the above paragraph again. If you think about it, this is about the same procedure as you would do with using plain dpatch. There is some new terminology, plus all your single steps are recorded in the revision history.

It is important to note, that all looms represent a stack of patches. Each item of the stack is latest loompoint recorded in the revision history. This means that in order to create the dpatch for loom1, you need to compare the loompoint 0 (this means the unpatched upstream source, revision 1 here) with loompoint 1 (2.1 at this point). The result is the diff for dpatch 1. More generally, to get a dpatch for loom n you make the difference between loompoint n-1 and loompoint n. This of course only works if all loompoints are “up-to-date”. A branch is only then “up-to-date”, if the highest loompoint is the only head in the revision graph. If there are other loompoints as heads, you need to update (merge) the other loompoints as described above.

Introducing a new loompoint is easy. You just create a new revision based on the loompoint you want to start from. In the picture, to start loom 3, you just make a new revision (4 in the picture). To insert a new loom not based on the highest loom, the process is the same: you make a new revision based on the appropriate loompoint. However, you have to update all later loompoints as described above.

Now how does this help to update a new upstream version? Like described in my previous article, you update the upstream branch with the new upstream version (revision 1.1) in the picture. This represents your new loompoint 0. Now you need to update all loompoints again as described above. If you think about it, this is exactly the same procedure as if you were using dpatch: You try to apply each dpatch after the other and resolve conflicts manually.

Now I've explained the concept of how to manage dpatch based packages with a VCS. In my next article I'll sketch how to a bzr plugin could work which implements this work flow.