Multiple changeset pushes to ON
By mbp on Dec 30, 2008
When ON switched to Mercurial from Teamware earlier this year ON went from having per-file delta's to per-repository changesets. In many ways Mercurial is a superior SCM to Teamware but this particular difference makes something I regularly find useful more difficult - fixing multiple unrelated Change-Requests (bugs and RFEs, referred to as CRs) with a single putback/push whilst maintaining a per-CR delta/changeset. Here is what I now do when fixing multiple unrelated CRs.
Create clones and snapshots of ONIt is generally a good idea to clone from the nightly tag as it ensures that
usris in sync with
usr/closed. This is probably not so important if ON is cloned from opensolaris.org. ZFS is nicely suited for use with Mercurial as painless clones and snapshots can be extremely handy.
$ zfs create -o compress=on local/onnv-clone $ cd /local/onnv-clone $ hg clone -r nightly onnv-clone /local/onnv-clone ... $ hg clone -r nightly onnv-closed-clone usr/closed ... $ zfs snapshot local/onnv-clone@`date +%Y%m%d`I like to maintain one repository per independent CR. With ZFS there is almost no downside as clones can be created almost instantly.
$ zfs clone local/onnv-clone@`date +%Y%m%d` local/5047971 $ zfs clone local/onnv-clone@`date +%Y%m%d` local/6704459 $ zfs clone local/onnv-clone@`date +%Y%m%d` local/6763503 ...I then work on each CR in its own repository individually. Building, unit-testing etc. can be performed for each CR in isolation.
Mercurial QueueMercurial Queue (MQ) is an extension to Mercurial. MQ is patch focused and maintains a queue of patches which can be pushed or popped. For historical reasons MQ commands begin with q. The MQ extension is included with OpenSolaris. It is not enabled by default. It can be enabled by modifying
$ ggrep -A 1 extensions ~/.hgrc [extensions] hgext.Tq =A new clone of onnv-clone is created which will be managed by the MQ extension of Mercurial. It will contain patches for all the individual CRs. The
qinitindicates that the patches themselves should be managed in a Mercurial repository. By default this repository is
$ zfs clone local/onnv-clone@`date +%Y%m%d` local/miscbugs $ cd /local/miscbugs $ hg qinit -cFor each of the individual workspaces (one per CR) the changes are exported as a patch and then imported into the MQ repository.
$ hg -R ../5047971 pdiffs > /tmp/5047971.patch $ hg qimport /tmp/5047971.patch adding 5047971.patch to series file $ hg -R ../6704459 pdiffs > /tmp/6704459.patch $ hg qimport /tmp/6704459.patch adding 6704459.patch to series file $ hg -R ../6763503 pdiffs > /tmp/6763503.patch $ hg qimport /tmp/6763503.patch adding 6763503.patch to series file $ hg qseries 6763503.patch 6704459.patch 5047971.patchThe comments should adhere to the ON convention. By default the comment will be the same as the patch name which can be set during
-noption. To change the comment of an existing patch the patch must be pushed to the top of the queue and the comment set with the
$ hg qpush applying 6763503.patch Now at: 6763503.patch $ hg qrefresh -m "6763503 Prompts for kadmin and ktutil use too much space" $ hg qpush applying 6704459.patch Now at: 6704459.patch $ hg qrefresh -m "6704459 assert defined in k5-thread.h produces number of false positives" $ hg qpush applying 5047971.patch Now at: 5047971.patch $ hg qrefresh -m "kadmin could use libtecla for enhanced command history and editing"The patches are committed to the MQ repository so they can be cloned later.
$ hg qcommit -m "Patches for 6763503, 6704459, 5047971"
Build machineA new clone on a build machine is created.
$ hg clone -r nightly onnv-clone ... $ hg clone -r nightly onnv-closed-clone onnv-clone/usr/closed ...The MQ repository is cloned so the build machine has all the MQ controlled patches.
$ cd onnv-clone $ hg clone ssh://dev_host//local/miscbugs/.hg/patches .hg/patches ...Patches are applied to the build-machine gate.
$ hg qpush -aThe fixes for the individual CRs can now be tested as a combined whole. Building, regression testing etc. are performed.
Push changesThe recommended pre-push procedure (
hg commit -m "merge turd",
hg recommit) will collapse all the changesets into a single changeset. As the CRs are independent this is undesirable - it would be better to have one changeset per CR. MQ provides a means to do that. The patches are popped off, the repository is updated, and a snapshot is created of the updated repository without the applied patches.
$ hg qpop -a Patch queue now empty $ hg pull -u ... $ zfs snapshot onnv-clone@prepush $ hg qpush -a applying 6763503.patch applying 6704459.patch applying 5047971.patch Now at: 5047971.patchThe MQ patches are converted into regular Mercurial changesets which are then pushed into the gate.
$ hg qrm -r 6763503.patch $ hg qrm -r 6704459.patch $ hg qrm -r 5047971.patch $ hg push ssh://firstname.lastname@example.org//export/onnv-gateIf someone sneaks a push to onnv-gate in the window between the "
hg qrm" and the "
hg push" then
$ zfs rollback onnv-clone@prepush $ hg pull -u ... $ zfs destroy onnv-clone@prepush $ zfs create onnv-clone@prepush $ hg qrm -r -a $ hg push ssh://email@example.com//export/onnv-gate ...The above is repeated until the push succeeds.