hgbook

diff en/ch12-mq-collab.xml @ 583:28b5a5befb08

Fold preface and intro into one
author Bryan O'Sullivan <bos@serpentine.com>
date Thu Mar 19 20:54:12 2009 -0700 (2009-03-19)
parents en/ch13-mq-collab.xml@8366882f67f2
children c838b3975bc6
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/en/ch12-mq-collab.xml	Thu Mar 19 20:54:12 2009 -0700
     1.3 @@ -0,0 +1,518 @@
     1.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
     1.5 +
     1.6 +<chapter id="chap:mq-collab">
     1.7 +  <?dbhtml filename="advanced-uses-of-mercurial-queues.html"?>
     1.8 +  <title>Advanced uses of Mercurial Queues</title>
     1.9 +
    1.10 +  <para>While it's easy to pick up straightforward uses of Mercurial
    1.11 +    Queues, use of a little discipline and some of MQ's less
    1.12 +    frequently used capabilities makes it possible to work in
    1.13 +    complicated development environments.</para>
    1.14 +
    1.15 +  <para>In this chapter, I will use as an example a technique I have
    1.16 +    used to manage the development of an Infiniband device driver for
    1.17 +    the Linux kernel.  The driver in question is large (at least as
    1.18 +    drivers go), with 25,000 lines of code spread across 35 source
    1.19 +    files.  It is maintained by a small team of developers.</para>
    1.20 +
    1.21 +  <para>While much of the material in this chapter is specific to
    1.22 +    Linux, the same principles apply to any code base for which you're
    1.23 +    not the primary owner, and upon which you need to do a lot of
    1.24 +    development.</para>
    1.25 +
    1.26 +  <sect1>
    1.27 +    <title>The problem of many targets</title>
    1.28 +
    1.29 +    <para>The Linux kernel changes rapidly, and has never been
    1.30 +      internally stable; developers frequently make drastic changes
    1.31 +      between releases. This means that a version of the driver that
    1.32 +      works well with a particular released version of the kernel will
    1.33 +      not even <emphasis>compile</emphasis> correctly against,
    1.34 +      typically, any other version.</para>
    1.35 +
    1.36 +    <para>To maintain a driver, we have to keep a number of distinct
    1.37 +      versions of Linux in mind.</para>
    1.38 +    <itemizedlist>
    1.39 +      <listitem><para>One target is the main Linux kernel development
    1.40 +	  tree. Maintenance of the code is in this case partly shared
    1.41 +	  by other developers in the kernel community, who make
    1.42 +	  <quote>drive-by</quote> modifications to the driver as they
    1.43 +	  develop and refine kernel subsystems.</para>
    1.44 +      </listitem>
    1.45 +      <listitem><para>We also maintain a number of
    1.46 +	  <quote>backports</quote> to older versions of the Linux
    1.47 +	  kernel, to support the needs of customers who are running
    1.48 +	  older Linux distributions that do not incorporate our
    1.49 +	  drivers.  (To <emphasis>backport</emphasis> a piece of code
    1.50 +	  is to modify it to work in an older version of its target
    1.51 +	  environment than the version it was developed for.)</para>
    1.52 +      </listitem>
    1.53 +      <listitem><para>Finally, we make software releases on a schedule
    1.54 +	  that is necessarily not aligned with those used by Linux
    1.55 +	  distributors and kernel developers, so that we can deliver
    1.56 +	  new features to customers without forcing them to upgrade
    1.57 +	  their entire kernels or distributions.</para>
    1.58 +      </listitem></itemizedlist>
    1.59 +
    1.60 +    <sect2>
    1.61 +      <title>Tempting approaches that don't work well</title>
    1.62 +
    1.63 +      <para>There are two <quote>standard</quote> ways to maintain a
    1.64 +	piece of software that has to target many different
    1.65 +	environments.</para>
    1.66 +
    1.67 +      <para>The first is to maintain a number of branches, each
    1.68 +	intended for a single target.  The trouble with this approach
    1.69 +	is that you must maintain iron discipline in the flow of
    1.70 +	changes between repositories. A new feature or bug fix must
    1.71 +	start life in a <quote>pristine</quote> repository, then
    1.72 +	percolate out to every backport repository.  Backport changes
    1.73 +	are more limited in the branches they should propagate to; a
    1.74 +	backport change that is applied to a branch where it doesn't
    1.75 +	belong will probably stop the driver from compiling.</para>
    1.76 +
    1.77 +      <para>The second is to maintain a single source tree filled with
    1.78 +	conditional statements that turn chunks of code on or off
    1.79 +	depending on the intended target.  Because these
    1.80 +	<quote>ifdefs</quote> are not allowed in the Linux kernel
    1.81 +	tree, a manual or automatic process must be followed to strip
    1.82 +	them out and yield a clean tree.  A code base maintained in
    1.83 +	this fashion rapidly becomes a rat's nest of conditional
    1.84 +	blocks that are difficult to understand and maintain.</para>
    1.85 +
    1.86 +      <para>Neither of these approaches is well suited to a situation
    1.87 +	where you don't <quote>own</quote> the canonical copy of a
    1.88 +	source tree.  In the case of a Linux driver that is
    1.89 +	distributed with the standard kernel, Linus's tree contains
    1.90 +	the copy of the code that will be treated by the world as
    1.91 +	canonical.  The upstream version of <quote>my</quote> driver
    1.92 +	can be modified by people I don't know, without me even
    1.93 +	finding out about it until after the changes show up in
    1.94 +	Linus's tree.</para>
    1.95 +
    1.96 +      <para>These approaches have the added weakness of making it
    1.97 +	difficult to generate well-formed patches to submit
    1.98 +	upstream.</para>
    1.99 +
   1.100 +      <para>In principle, Mercurial Queues seems like a good candidate
   1.101 +	to manage a development scenario such as the above.  While
   1.102 +	this is indeed the case, MQ contains a few added features that
   1.103 +	make the job more pleasant.</para>
   1.104 +
   1.105 +    </sect2>
   1.106 +  </sect1>
   1.107 +  <sect1>
   1.108 +    <title>Conditionally applying patches with guards</title>
   1.109 +
   1.110 +    <para>Perhaps the best way to maintain sanity with so many targets
   1.111 +      is to be able to choose specific patches to apply for a given
   1.112 +      situation.  MQ provides a feature called <quote>guards</quote>
   1.113 +      (which originates with quilt's <literal>guards</literal>
   1.114 +      command) that does just this.  To start off, let's create a
   1.115 +      simple repository for experimenting in.</para>
   1.116 +
   1.117 +    &interaction.mq.guards.init;
   1.118 +
   1.119 +    <para>This gives us a tiny repository that contains two patches
   1.120 +      that don't have any dependencies on each other, because they
   1.121 +      touch different files.</para>
   1.122 +
   1.123 +    <para>The idea behind conditional application is that you can
   1.124 +      <quote>tag</quote> a patch with a <emphasis>guard</emphasis>,
   1.125 +      which is simply a text string of your choosing, then tell MQ to
   1.126 +      select specific guards to use when applying patches.  MQ will
   1.127 +      then either apply, or skip over, a guarded patch, depending on
   1.128 +      the guards that you have selected.</para>
   1.129 +
   1.130 +    <para>A patch can have an arbitrary number of guards; each one is
   1.131 +      <emphasis>positive</emphasis> (<quote>apply this patch if this
   1.132 +	guard is selected</quote>) or <emphasis>negative</emphasis>
   1.133 +      (<quote>skip this patch if this guard is selected</quote>).  A
   1.134 +      patch with no guards is always applied.</para>
   1.135 +
   1.136 +  </sect1>
   1.137 +  <sect1>
   1.138 +    <title>Controlling the guards on a patch</title>
   1.139 +
   1.140 +    <para>The <command role="hg-ext-mq">qguard</command> command lets
   1.141 +      you determine which guards should apply to a patch, or display
   1.142 +      the guards that are already in effect. Without any arguments, it
   1.143 +      displays the guards on the current topmost patch.</para>
   1.144 +
   1.145 +      &interaction.mq.guards.qguard;
   1.146 +
   1.147 +    <para>To set a positive guard on a patch, prefix the name of the
   1.148 +      guard with a <quote><literal>+</literal></quote>.</para>
   1.149 +
   1.150 +      &interaction.mq.guards.qguard.pos;
   1.151 +
   1.152 +    <para>To set a negative guard
   1.153 +      on a patch, prefix the name of the guard with a
   1.154 +      <quote><literal>-</literal></quote>.</para>
   1.155 +
   1.156 +    &interaction.mq.guards.qguard.neg;
   1.157 +
   1.158 +    <note>
   1.159 +      <para>  The <command role="hg-ext-mq">qguard</command> command
   1.160 +	<emphasis>sets</emphasis> the guards on a patch; it doesn't
   1.161 +	<emphasis>modify</emphasis> them.  What this means is that if
   1.162 +	you run <command role="hg-cmd">hg qguard +a +b</command> on a
   1.163 +	patch, then <command role="hg-cmd">hg qguard +c</command> on
   1.164 +	the same patch, the <emphasis>only</emphasis> guard that will
   1.165 +	be set on it afterwards is <literal>+c</literal>.</para>
   1.166 +    </note>
   1.167 +
   1.168 +    <para>Mercurial stores guards in the <filename
   1.169 +	role="special">series</filename> file; the form in which they
   1.170 +      are stored is easy both to understand and to edit by hand. (In
   1.171 +      other words, you don't have to use the <command
   1.172 +	role="hg-ext-mq">qguard</command> command if you don't want
   1.173 +      to; it's okay to simply edit the <filename
   1.174 +	role="special">series</filename> file.)</para>
   1.175 +
   1.176 +    &interaction.mq.guards.series;
   1.177 +
   1.178 +  </sect1>
   1.179 +  <sect1>
   1.180 +    <title>Selecting the guards to use</title>
   1.181 +
   1.182 +    <para>The <command role="hg-ext-mq">qselect</command> command
   1.183 +      determines which guards are active at a given time.  The effect
   1.184 +      of this is to determine which patches MQ will apply the next
   1.185 +      time you run <command role="hg-ext-mq">qpush</command>.  It has
   1.186 +      no other effect; in particular, it doesn't do anything to
   1.187 +      patches that are already applied.</para>
   1.188 +
   1.189 +    <para>With no arguments, the <command
   1.190 +	role="hg-ext-mq">qselect</command> command lists the guards
   1.191 +      currently in effect, one per line of output.  Each argument is
   1.192 +      treated as the name of a guard to apply.</para>
   1.193 +
   1.194 +      &interaction.mq.guards.qselect.foo;
   1.195 +
   1.196 +    <para>In case you're interested, the currently selected guards are
   1.197 +      stored in the <filename role="special">guards</filename> file.</para>
   1.198 +
   1.199 +    &interaction.mq.guards.qselect.cat;
   1.200 +
   1.201 +    <para>We can see the effect the selected guards have when we run
   1.202 +      <command role="hg-ext-mq">qpush</command>.</para>
   1.203 +
   1.204 +    &interaction.mq.guards.qselect.qpush;
   1.205 +
   1.206 +    <para>A guard cannot start with a
   1.207 +      <quote><literal>+</literal></quote> or
   1.208 +      <quote><literal>-</literal></quote> character.  The name of a
   1.209 +      guard must not contain white space, but most other characters
   1.210 +      are acceptable.  If you try to use a guard with an invalid name,
   1.211 +      MQ will complain:</para>
   1.212 +
   1.213 +    &interaction.mq.guards.qselect.error;
   1.214 +      
   1.215 +    <para>Changing the selected guards changes the patches that are
   1.216 +      applied.</para>
   1.217 +
   1.218 +    &interaction.mq.guards.qselect.quux;
   1.219 +
   1.220 +    <para>You can see in the example below that negative guards take
   1.221 +      precedence over positive guards.</para>
   1.222 +
   1.223 +    &interaction.mq.guards.qselect.foobar;
   1.224 +
   1.225 +  </sect1>
   1.226 +  <sect1>
   1.227 +    <title>MQ's rules for applying patches</title>
   1.228 +
   1.229 +    <para>The rules that MQ uses when deciding whether to apply a
   1.230 +      patch are as follows.</para>
   1.231 +    <itemizedlist>
   1.232 +      <listitem><para>A patch that has no guards is always
   1.233 +	  applied.</para>
   1.234 +      </listitem>
   1.235 +      <listitem><para>If the patch has any negative guard that matches
   1.236 +	  any currently selected guard, the patch is skipped.</para>
   1.237 +      </listitem>
   1.238 +      <listitem><para>If the patch has any positive guard that matches
   1.239 +	  any currently selected guard, the patch is applied.</para>
   1.240 +      </listitem>
   1.241 +      <listitem><para>If the patch has positive or negative guards,
   1.242 +	  but none matches any currently selected guard, the patch is
   1.243 +	  skipped.</para>
   1.244 +      </listitem></itemizedlist>
   1.245 +
   1.246 +  </sect1>
   1.247 +  <sect1>
   1.248 +    <title>Trimming the work environment</title>
   1.249 +
   1.250 +    <para>In working on the device driver I mentioned earlier, I don't
   1.251 +      apply the patches to a normal Linux kernel tree.  Instead, I use
   1.252 +      a repository that contains only a snapshot of the source files
   1.253 +      and headers that are relevant to Infiniband development.  This
   1.254 +      repository is 1% the size of a kernel repository, so it's easier
   1.255 +      to work with.</para>
   1.256 +
   1.257 +    <para>I then choose a <quote>base</quote> version on top of which
   1.258 +      the patches are applied.  This is a snapshot of the Linux kernel
   1.259 +      tree as of a revision of my choosing.  When I take the snapshot,
   1.260 +      I record the changeset ID from the kernel repository in the
   1.261 +      commit message.  Since the snapshot preserves the
   1.262 +      <quote>shape</quote> and content of the relevant parts of the
   1.263 +      kernel tree, I can apply my patches on top of either my tiny
   1.264 +      repository or a normal kernel tree.</para>
   1.265 +
   1.266 +    <para>Normally, the base tree atop which the patches apply should
   1.267 +      be a snapshot of a very recent upstream tree.  This best
   1.268 +      facilitates the development of patches that can easily be
   1.269 +      submitted upstream with few or no modifications.</para>
   1.270 +
   1.271 +  </sect1>
   1.272 +  <sect1>
   1.273 +    <title>Dividing up the <filename role="special">series</filename>
   1.274 +      file</title>
   1.275 +
   1.276 +    <para>I categorise the patches in the <filename
   1.277 +	role="special">series</filename> file into a number of logical
   1.278 +      groups.  Each section of like patches begins with a block of
   1.279 +      comments that describes the purpose of the patches that
   1.280 +      follow.</para>
   1.281 +
   1.282 +    <para>The sequence of patch groups that I maintain follows.  The
   1.283 +      ordering of these groups is important; I'll describe why after I
   1.284 +      introduce the groups.</para>
   1.285 +    <itemizedlist>
   1.286 +      <listitem><para>The <quote>accepted</quote> group.  Patches that
   1.287 +	  the development team has submitted to the maintainer of the
   1.288 +	  Infiniband subsystem, and which he has accepted, but which
   1.289 +	  are not present in the snapshot that the tiny repository is
   1.290 +	  based on.  These are <quote>read only</quote> patches,
   1.291 +	  present only to transform the tree into a similar state as
   1.292 +	  it is in the upstream maintainer's repository.</para>
   1.293 +      </listitem>
   1.294 +      <listitem><para>The <quote>rework</quote> group.  Patches that I
   1.295 +	  have submitted, but that the upstream maintainer has
   1.296 +	  requested modifications to before he will accept
   1.297 +	  them.</para>
   1.298 +      </listitem>
   1.299 +      <listitem><para>The <quote>pending</quote> group.  Patches that
   1.300 +	  I have not yet submitted to the upstream maintainer, but
   1.301 +	  which we have finished working on. These will be <quote>read
   1.302 +	    only</quote> for a while.  If the upstream maintainer
   1.303 +	  accepts them upon submission, I'll move them to the end of
   1.304 +	  the <quote>accepted</quote> group.  If he requests that I
   1.305 +	  modify any, I'll move them to the beginning of the
   1.306 +	  <quote>rework</quote> group.</para>
   1.307 +      </listitem>
   1.308 +      <listitem><para>The <quote>in progress</quote> group.  Patches
   1.309 +	  that are actively being developed, and should not be
   1.310 +	  submitted anywhere yet.</para>
   1.311 +      </listitem>
   1.312 +      <listitem><para>The <quote>backport</quote> group.  Patches that
   1.313 +	  adapt the source tree to older versions of the kernel
   1.314 +	  tree.</para>
   1.315 +      </listitem>
   1.316 +      <listitem><para>The <quote>do not ship</quote> group.  Patches
   1.317 +	  that for some reason should never be submitted upstream.
   1.318 +	  For example, one such patch might change embedded driver
   1.319 +	  identification strings to make it easier to distinguish, in
   1.320 +	  the field, between an out-of-tree version of the driver and
   1.321 +	  a version shipped by a distribution vendor.</para>
   1.322 +      </listitem></itemizedlist>
   1.323 +
   1.324 +    <para>Now to return to the reasons for ordering groups of patches
   1.325 +      in this way.  We would like the lowest patches in the stack to
   1.326 +      be as stable as possible, so that we will not need to rework
   1.327 +      higher patches due to changes in context.  Putting patches that
   1.328 +      will never be changed first in the <filename
   1.329 +	role="special">series</filename> file serves this
   1.330 +      purpose.</para>
   1.331 +
   1.332 +    <para>We would also like the patches that we know we'll need to
   1.333 +      modify to be applied on top of a source tree that resembles the
   1.334 +      upstream tree as closely as possible.  This is why we keep
   1.335 +      accepted patches around for a while.</para>
   1.336 +
   1.337 +    <para>The <quote>backport</quote> and <quote>do not ship</quote>
   1.338 +      patches float at the end of the <filename
   1.339 +	role="special">series</filename> file.  The backport patches
   1.340 +      must be applied on top of all other patches, and the <quote>do
   1.341 +	not ship</quote> patches might as well stay out of harm's
   1.342 +      way.</para>
   1.343 +
   1.344 +  </sect1>
   1.345 +  <sect1>
   1.346 +    <title>Maintaining the patch series</title>
   1.347 +
   1.348 +    <para>In my work, I use a number of guards to control which
   1.349 +      patches are to be applied.</para>
   1.350 +
   1.351 +    <itemizedlist>
   1.352 +      <listitem><para><quote>Accepted</quote> patches are guarded with
   1.353 +	  <literal>accepted</literal>.  I enable this guard most of
   1.354 +	  the time.  When I'm applying the patches on top of a tree
   1.355 +	  where the patches are already present, I can turn this patch
   1.356 +	  off, and the patches that follow it will apply
   1.357 +	  cleanly.</para>
   1.358 +      </listitem>
   1.359 +      <listitem><para>Patches that are <quote>finished</quote>, but
   1.360 +	  not yet submitted, have no guards.  If I'm applying the
   1.361 +	  patch stack to a copy of the upstream tree, I don't need to
   1.362 +	  enable any guards in order to get a reasonably safe source
   1.363 +	  tree.</para>
   1.364 +      </listitem>
   1.365 +      <listitem><para>Those patches that need reworking before being
   1.366 +	  resubmitted are guarded with
   1.367 +	  <literal>rework</literal>.</para>
   1.368 +      </listitem>
   1.369 +      <listitem><para>For those patches that are still under
   1.370 +	  development, I use <literal>devel</literal>.</para>
   1.371 +      </listitem>
   1.372 +      <listitem><para>A backport patch may have several guards, one
   1.373 +	  for each version of the kernel to which it applies.  For
   1.374 +	  example, a patch that backports a piece of code to 2.6.9
   1.375 +	  will have a <literal>2.6.9</literal> guard.</para>
   1.376 +      </listitem></itemizedlist>
   1.377 +    <para>This variety of guards gives me considerable flexibility in
   1.378 +      determining what kind of source tree I want to end up with.  For
   1.379 +      most situations, the selection of appropriate guards is
   1.380 +      automated during the build process, but I can manually tune the
   1.381 +      guards to use for less common circumstances.</para>
   1.382 +
   1.383 +    <sect2>
   1.384 +      <title>The art of writing backport patches</title>
   1.385 +
   1.386 +      <para>Using MQ, writing a backport patch is a simple process.
   1.387 +	All such a patch has to do is modify a piece of code that uses
   1.388 +	a kernel feature not present in the older version of the
   1.389 +	kernel, so that the driver continues to work correctly under
   1.390 +	that older version.</para>
   1.391 +
   1.392 +      <para>A useful goal when writing a good backport patch is to
   1.393 +	make your code look as if it was written for the older version
   1.394 +	of the kernel you're targeting.  The less obtrusive the patch,
   1.395 +	the easier it will be to understand and maintain.  If you're
   1.396 +	writing a collection of backport patches to avoid the
   1.397 +	<quote>rat's nest</quote> effect of lots of
   1.398 +	<literal>#ifdef</literal>s (hunks of source code that are only
   1.399 +	used conditionally) in your code, don't introduce
   1.400 +	version-dependent <literal>#ifdef</literal>s into the patches.
   1.401 +	Instead, write several patches, each of which makes
   1.402 +	unconditional changes, and control their application using
   1.403 +	guards.</para>
   1.404 +
   1.405 +      <para>There are two reasons to divide backport patches into a
   1.406 +	distinct group, away from the <quote>regular</quote> patches
   1.407 +	whose effects they modify. The first is that intermingling the
   1.408 +	two makes it more difficult to use a tool like the <literal
   1.409 +	  role="hg-ext">patchbomb</literal> extension to automate the
   1.410 +	process of submitting the patches to an upstream maintainer.
   1.411 +	The second is that a backport patch could perturb the context
   1.412 +	in which a subsequent regular patch is applied, making it
   1.413 +	impossible to apply the regular patch cleanly
   1.414 +	<emphasis>without</emphasis> the earlier backport patch
   1.415 +	already being applied.</para>
   1.416 +
   1.417 +    </sect2>
   1.418 +  </sect1>
   1.419 +  <sect1>
   1.420 +    <title>Useful tips for developing with MQ</title>
   1.421 +
   1.422 +    <sect2>
   1.423 +      <title>Organising patches in directories</title>
   1.424 +
   1.425 +      <para>If you're working on a substantial project with MQ, it's
   1.426 +	not difficult to accumulate a large number of patches.  For
   1.427 +	example, I have one patch repository that contains over 250
   1.428 +	patches.</para>
   1.429 +
   1.430 +      <para>If you can group these patches into separate logical
   1.431 +	categories, you can if you like store them in different
   1.432 +	directories; MQ has no problems with patch names that contain
   1.433 +	path separators.</para>
   1.434 +
   1.435 +    </sect2>
   1.436 +    <sect2 id="mq-collab:tips:interdiff">
   1.437 +      <title>Viewing the history of a patch</title>
   1.438 +
   1.439 +      <para>If you're developing a set of patches over a long time,
   1.440 +	it's a good idea to maintain them in a repository, as
   1.441 +	discussed in section <xref linkend="sec:mq:repo"/>.  If you do
   1.442 +	so, you'll quickly
   1.443 +	discover that using the <command role="hg-cmd">hg
   1.444 +	  diff</command> command to look at the history of changes to
   1.445 +	a patch is unworkable.  This is in part because you're looking
   1.446 +	at the second derivative of the real code (a diff of a diff),
   1.447 +	but also because MQ adds noise to the process by modifying
   1.448 +	time stamps and directory names when it updates a
   1.449 +	patch.</para>
   1.450 +
   1.451 +      <para>However, you can use the <literal
   1.452 +	  role="hg-ext">extdiff</literal> extension, which is bundled
   1.453 +	with Mercurial, to turn a diff of two versions of a patch into
   1.454 +	something readable.  To do this, you will need a third-party
   1.455 +	package called <literal role="package">patchutils</literal>
   1.456 +	<citation>web:patchutils</citation>.  This provides a command
   1.457 +	named <command>interdiff</command>, which shows the
   1.458 +	differences between two diffs as a diff.  Used on two versions
   1.459 +	of the same diff, it generates a diff that represents the diff
   1.460 +	from the first to the second version.</para>
   1.461 +
   1.462 +      <para>You can enable the <literal
   1.463 +	  role="hg-ext">extdiff</literal> extension in the usual way,
   1.464 +	by adding a line to the <literal
   1.465 +	  role="rc-extensions">extensions</literal> section of your
   1.466 +	<filename role="special">~/.hgrc</filename>.</para>
   1.467 +      <programlisting>[extensions]
   1.468 +extdiff =</programlisting>
   1.469 +      <para>The <command>interdiff</command> command expects to be
   1.470 +	passed the names of two files, but the <literal
   1.471 +	  role="hg-ext">extdiff</literal> extension passes the program
   1.472 +	it runs a pair of directories, each of which can contain an
   1.473 +	arbitrary number of files.  We thus need a small program that
   1.474 +	will run <command>interdiff</command> on each pair of files in
   1.475 +	these two directories.  This program is available as <filename
   1.476 +	  role="special">hg-interdiff</filename> in the <filename
   1.477 +	  class="directory">examples</filename> directory of the
   1.478 +	source code repository that accompanies this book. <!--
   1.479 +	&example.hg-interdiff; --></para>
   1.480 +
   1.481 +      <para>With the <filename role="special">hg-interdiff</filename>
   1.482 +	program in your shell's search path, you can run it as
   1.483 +	follows, from inside an MQ patch directory:</para>
   1.484 +      <programlisting>hg extdiff -p hg-interdiff -r A:B my-change.patch</programlisting>
   1.485 +      <para>Since you'll probably want to use this long-winded command
   1.486 +	a lot, you can get <literal role="hg-ext">hgext</literal> to
   1.487 +	make it available as a normal Mercurial command, again by
   1.488 +	editing your <filename
   1.489 +	  role="special">~/.hgrc</filename>.</para>
   1.490 +      <programlisting>[extdiff]
   1.491 +cmd.interdiff = hg-interdiff</programlisting>
   1.492 +      <para>This directs <literal role="hg-ext">hgext</literal> to
   1.493 +	make an <literal>interdiff</literal> command available, so you
   1.494 +	can now shorten the previous invocation of <command
   1.495 +	  role="hg-ext-extdiff">extdiff</command> to something a
   1.496 +	little more wieldy.</para>
   1.497 +      <programlisting>hg interdiff -r A:B my-change.patch</programlisting>
   1.498 +
   1.499 +      <note>
   1.500 +	<para>  The <command>interdiff</command> command works well
   1.501 +	  only if the underlying files against which versions of a
   1.502 +	  patch are generated remain the same.  If you create a patch,
   1.503 +	  modify the underlying files, and then regenerate the patch,
   1.504 +	  <command>interdiff</command> may not produce useful
   1.505 +	  output.</para>
   1.506 +      </note>
   1.507 +
   1.508 +      <para>The <literal role="hg-ext">extdiff</literal> extension is
   1.509 +	useful for more than merely improving the presentation of MQ
   1.510 +	patches.  To read more about it, go to section <xref
   1.511 +	  linkend="sec:hgext:extdiff"/>.</para>
   1.512 +
   1.513 +    </sect2>
   1.514 +  </sect1>
   1.515 +</chapter>
   1.516 +
   1.517 +<!--
   1.518 +local variables: 
   1.519 +sgml-parent-document: ("00book.xml" "book" "chapter")
   1.520 +end:
   1.521 +-->