Over the last week or so, I have finally gotten around to digging into the whole concept of using Mercurial Queues to manage patches against an upstream project; in my case dwm.1 Essentially, this mercurial extension helps you manage a stack of patches on top of a directory tree. This gives you quite a lot of fine-grained control over your patchset and assists immeasurably with automating the application of patches when the underlying codebase changes.
After having played around with queues for the last couple of days, I am quite impressed: both the concept and the execution are simple and powerful. The concept of Mercurial Queues is best described in the Mercurial book: the aptly titled, Mercurial: The Definitive Guide:2
MQ's marriage of distributed revision control with patches makes it much easier to isolate your work. Your patches live on top of normal revision history, and you can make them disappear or reappear at will. If you don't like a patch, you can drop it. If a patch isn't quite as you want it to be, simply fix it—as many times as you need to, until you have refined it into the form you desire.
I followed Filippo Negroni’s excellent
tutorial on the dwm site
to setup my own
dwm patchset
based on
tip, and the process was
surprisingly straightforward; the only caveat being it is a good idea to plan
quite carefully what changes you want in each particular patch. Once I had
completed the setup, it got me thinking about the fact that the final install
is done without pacman
, just using make install
. And, as a proof-of-concept
more than anything else, I wondered whether this functionality could be used
with makepkg
.3
Turns out, as you might expect with Arch, it was not much of a job to set it up at all.
Note: this doesn’t mean I think it is a good idea; I was just interested to see if it could be done and how it would work once it was set up. For something like dwm, this is definitely a case of introducing a huge amount of complexity for no apparent benefit (for those people running Gnome, this may quite appeal to you…).
I have a
working PKGBUILD
that you can use if you want to follow along at home. Once you have downloaded
it into dwm-hg/, run makepkg
to clone the dwm
repository and build the binary. Then you need to make sure that the mercurial
queue extension is enabled, so your .hgrc needs to
contain:
1 2 |
|
Now, you need to setup the queue repository. We do this in $srcdir
, which
is dwm-hg/src/dwm:
1
|
|
The next step is to start applying the various patches that you want to comprise your patchset on dwm. In my case that is base customizations to config.def.h and three other patches: statuscolours, cycle, and push. There are other patches in my repository, one of which patches the appropriate settings for an Arch build in the relevant makefiles. This is taken care of by the PKGBUILD in this case.
From here, it is very much as Filippo describes it in his tutorial: make some changes, add them to the queue and rinse and repeat:
1 2 3 4 |
|
After committing each of your changes as a discrete patch, you can review the queue
with hg qseries
:
1 2 3 4 5 6 |
|
And hg qapplied
will tell you which of the patches is currently
applied in the working repository; at this stage the list should look
the same as that in hg qseries
. The next step is to remove all of the
patches from the queue so that we have a clean repository:
1 2 3 4 5 6 7 |
|
Should you need to edit a patch, it is simply a matter of popping to that spot in the stack (you can do so by name or by index number, beginning at 0):
1 2 3 4 5 6 7 8 9 |
|
Once you are satisfied with the state of the stack, remove all of the
patches to return to the original clean working directory and cd
back
to dwm-hg/. You can now use makepkg -fi
to
rebuild the package and you should see the pushed patches as part of
the output:
1 2 3 4 5 6 7 8 |
|
…and when you restart dwm, your customizations will be applied.
When new changes are pushed to
the dwm repo
you can just makepkg -fi
, and, if any of the patches fail due
to changes in the underlying code, pop the stack to the failed
patch, rebase the code, hg qrefresh
and continue until done.
As I said at the beginning of this post, this isn’t a particularly smart way to
use Mercurial Queues, PKGBUILDs or a combination of the two. You are much
better off just cloning dwm to your local repository, initializing a queue
repository and, once you are done setting up your patchset, issuing make &&
sudo make install
.
If you have more than one machine, you can easily setup a repository for
your patchset on
bitbucket
and host it there: then just pull the patchset queue
from your other boxes and hg qpush -a
. If you require a slightly
different patchset for each box, you can use MQ to manage this
process as well. This is where MQ really excels;
I’ll cover this in more detail in my next post.
Notes
- See related dwm posts.
- I can’t recommend this {book,wiki} highly enough; it is an excellent example of thorough, accessible documentation.
- In the case of something like dwm, this is really irrelevant, as there
is a single tiny binary and a
man
page, so keeping track of these files on your system is not an issue at all.
Flickr Creative Commons image by RachelH