hgbook

annotate fr/ch13-mq-collab.xml @ 977:719b03ea27c8

merge with Italian, and very (few) work on ch03
author Romain PELISSE <belaran@gmail.com>
date Fri Sep 04 16:33:46 2009 +0200 (2009-09-04)
parents
children 6f8c48362758
rev   line source
belaran@964 1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
belaran@964 2
belaran@964 3 <chapter>
belaran@964 4 <title>Advanced uses of Mercurial Queues</title>
belaran@964 5 <para>\label{chap:mq-collab}</para>
belaran@964 6
belaran@964 7 <para>While it's easy to pick up straightforward uses of Mercurial Queues,
belaran@964 8 use of a little discipline and some of MQ's less frequently used
belaran@964 9 capabilities makes it possible to work in complicated development
belaran@964 10 environments.</para>
belaran@964 11
belaran@964 12 <para>In this chapter, I will use as an example a technique I have used to
belaran@964 13 manage the development of an Infiniband device driver for the Linux
belaran@964 14 kernel. The driver in question is large (at least as drivers go),
belaran@964 15 with 25,000 lines of code spread across 35 source files. It is
belaran@964 16 maintained by a small team of developers.</para>
belaran@964 17
belaran@964 18 <para>While much of the material in this chapter is specific to Linux, the
belaran@964 19 same principles apply to any code base for which you're not the
belaran@964 20 primary owner, and upon which you need to do a lot of development.</para>
belaran@964 21
belaran@964 22 <sect1>
belaran@964 23 <title>The problem of many targets</title>
belaran@964 24
belaran@964 25 <para>The Linux kernel changes rapidly, and has never been internally
belaran@964 26 stable; developers frequently make drastic changes between releases.
belaran@964 27 This means that a version of the driver that works well with a
belaran@964 28 particular released version of the kernel will not even <emphasis>compile</emphasis>
belaran@964 29 correctly against, typically, any other version.</para>
belaran@964 30
belaran@964 31 <para>To maintain a driver, we have to keep a number of distinct versions of
belaran@964 32 Linux in mind.</para>
belaran@964 33 <itemizedlist>
belaran@964 34 <listitem><para>One target is the main Linux kernel development tree.
belaran@964 35 Maintenance of the code is in this case partly shared by other
belaran@964 36 developers in the kernel community, who make <quote>drive-by</quote>
belaran@964 37 modifications to the driver as they develop and refine kernel
belaran@964 38 subsystems.</para>
belaran@964 39 </listitem>
belaran@964 40 <listitem><para>We also maintain a number of <quote>backports</quote> to older versions of
belaran@964 41 the Linux kernel, to support the needs of customers who are running
belaran@964 42 older Linux distributions that do not incorporate our drivers. (To
belaran@964 43 <emphasis>backport</emphasis> a piece of code is to modify it to work in an older
belaran@964 44 version of its target environment than the version it was developed
belaran@964 45 for.)</para>
belaran@964 46 </listitem>
belaran@964 47 <listitem><para>Finally, we make software releases on a schedule that is
belaran@964 48 necessarily not aligned with those used by Linux distributors and
belaran@964 49 kernel developers, so that we can deliver new features to customers
belaran@964 50 without forcing them to upgrade their entire kernels or
belaran@964 51 distributions.
belaran@964 52 </para>
belaran@964 53 </listitem></itemizedlist>
belaran@964 54
belaran@964 55 <sect2>
belaran@964 56 <title>Tempting approaches that don't work well</title>
belaran@964 57
belaran@964 58 <para>There are two <quote>standard</quote> ways to maintain a piece of software that
belaran@964 59 has to target many different environments.
belaran@964 60 </para>
belaran@964 61
belaran@964 62 <para>The first is to maintain a number of branches, each intended for a
belaran@964 63 single target. The trouble with this approach is that you must
belaran@964 64 maintain iron discipline in the flow of changes between repositories.
belaran@964 65 A new feature or bug fix must start life in a <quote>pristine</quote> repository,
belaran@964 66 then percolate out to every backport repository. Backport changes are
belaran@964 67 more limited in the branches they should propagate to; a backport
belaran@964 68 change that is applied to a branch where it doesn't belong will
belaran@964 69 probably stop the driver from compiling.
belaran@964 70 </para>
belaran@964 71
belaran@964 72 <para>The second is to maintain a single source tree filled with conditional
belaran@964 73 statements that turn chunks of code on or off depending on the
belaran@964 74 intended target. Because these <quote>ifdefs</quote> are not allowed in the
belaran@964 75 Linux kernel tree, a manual or automatic process must be followed to
belaran@964 76 strip them out and yield a clean tree. A code base maintained in this
belaran@964 77 fashion rapidly becomes a rat's nest of conditional blocks that are
belaran@964 78 difficult to understand and maintain.
belaran@964 79 </para>
belaran@964 80
belaran@964 81 <para>Neither of these approaches is well suited to a situation where you
belaran@964 82 don't <quote>own</quote> the canonical copy of a source tree. In the case of a
belaran@964 83 Linux driver that is distributed with the standard kernel, Linus's
belaran@964 84 tree contains the copy of the code that will be treated by the world
belaran@964 85 as canonical. The upstream version of <quote>my</quote> driver can be modified
belaran@964 86 by people I don't know, without me even finding out about it until
belaran@964 87 after the changes show up in Linus's tree.
belaran@964 88 </para>
belaran@964 89
belaran@964 90 <para>These approaches have the added weakness of making it difficult to
belaran@964 91 generate well-formed patches to submit upstream.
belaran@964 92 </para>
belaran@964 93
belaran@964 94 <para>In principle, Mercurial Queues seems like a good candidate to manage a
belaran@964 95 development scenario such as the above. While this is indeed the
belaran@964 96 case, MQ contains a few added features that make the job more
belaran@964 97 pleasant.
belaran@964 98 </para>
belaran@964 99
belaran@964 100 <para>\section{Conditionally applying patches with
belaran@964 101 guards}
belaran@964 102 </para>
belaran@964 103
belaran@964 104 <para>Perhaps the best way to maintain sanity with so many targets is to be
belaran@964 105 able to choose specific patches to apply for a given situation. MQ
belaran@964 106 provides a feature called <quote>guards</quote> (which originates with quilt's
belaran@964 107 <literal>guards</literal> command) that does just this. To start off, let's
belaran@964 108 create a simple repository for experimenting in.
belaran@964 109 <!-- &interaction.mq.guards.init; -->
belaran@964 110 This gives us a tiny repository that contains two patches that don't
belaran@964 111 have any dependencies on each other, because they touch different files.
belaran@964 112 </para>
belaran@964 113
belaran@964 114 <para>The idea behind conditional application is that you can <quote>tag</quote> a
belaran@964 115 patch with a <emphasis>guard</emphasis>, which is simply a text string of your
belaran@964 116 choosing, then tell MQ to select specific guards to use when applying
belaran@964 117 patches. MQ will then either apply, or skip over, a guarded patch,
belaran@964 118 depending on the guards that you have selected.
belaran@964 119 </para>
belaran@964 120
belaran@964 121 <para>A patch can have an arbitrary number of guards;
belaran@964 122 each one is <emphasis>positive</emphasis> (<quote>apply this patch if this guard is
belaran@964 123 selected</quote>) or <emphasis>negative</emphasis> (<quote>skip this patch if this guard is
belaran@964 124 selected</quote>). A patch with no guards is always applied.
belaran@964 125 </para>
belaran@964 126
belaran@964 127 </sect2>
belaran@964 128 </sect1>
belaran@964 129 <sect1>
belaran@964 130 <title>Controlling the guards on a patch</title>
belaran@964 131
belaran@964 132 <para>The <command role="hg-ext-mq">qguard</command> command lets you determine which guards should
belaran@964 133 apply to a patch, or display the guards that are already in effect.
belaran@964 134 Without any arguments, it displays the guards on the current topmost
belaran@964 135 patch.
belaran@964 136 <!-- &interaction.mq.guards.qguard; -->
belaran@964 137 To set a positive guard on a patch, prefix the name of the guard with
belaran@964 138 a <quote><literal>+</literal></quote>.
belaran@964 139 <!-- &interaction.mq.guards.qguard.pos; -->
belaran@964 140 To set a negative guard on a patch, prefix the name of the guard with
belaran@964 141 a <quote><literal>-</literal></quote>.
belaran@964 142 <!-- &interaction.mq.guards.qguard.neg; -->
belaran@964 143 </para>
belaran@964 144
belaran@964 145 <note>
belaran@964 146 <para> The <command role="hg-ext-mq">qguard</command> command <emphasis>sets</emphasis> the guards on a patch; it
belaran@964 147 doesn't <emphasis>modify</emphasis> them. What this means is that if you run
belaran@964 148 <command role="hg-cmd">hg qguard +a +b</command> on a patch, then <command role="hg-cmd">hg qguard +c</command> on
belaran@964 149 the same patch, the <emphasis>only</emphasis> guard that will be set on it
belaran@964 150 afterwards is <literal>+c</literal>.
belaran@964 151 </para>
belaran@964 152 </note>
belaran@964 153
belaran@964 154 <para>Mercurial stores guards in the <filename role="special">series</filename> file; the form in
belaran@964 155 which they are stored is easy both to understand and to edit by hand.
belaran@964 156 (In other words, you don't have to use the <command role="hg-ext-mq">qguard</command> command if
belaran@964 157 you don't want to; it's okay to simply edit the <filename role="special">series</filename>
belaran@964 158 file.)
belaran@964 159 <!-- &interaction.mq.guards.series; -->
belaran@964 160 </para>
belaran@964 161
belaran@964 162 </sect1>
belaran@964 163 <sect1>
belaran@964 164 <title>Selecting the guards to use</title>
belaran@964 165
belaran@964 166 <para>The <command role="hg-ext-mq">qselect</command> command determines which guards are active at a
belaran@964 167 given time. The effect of this is to determine which patches MQ will
belaran@964 168 apply the next time you run <command role="hg-ext-mq">qpush</command>. It has no other effect; in
belaran@964 169 particular, it doesn't do anything to patches that are already
belaran@964 170 applied.
belaran@964 171 </para>
belaran@964 172
belaran@964 173 <para>With no arguments, the <command role="hg-ext-mq">qselect</command> command lists the guards
belaran@964 174 currently in effect, one per line of output. Each argument is treated
belaran@964 175 as the name of a guard to apply.
belaran@964 176 <!-- &interaction.mq.guards.qselect.foo; -->
belaran@964 177 In case you're interested, the currently selected guards are stored in
belaran@964 178 the <filename role="special">guards</filename> file.
belaran@964 179 <!-- &interaction.mq.guards.qselect.cat; -->
belaran@964 180 We can see the effect the selected guards have when we run
belaran@964 181 <command role="hg-ext-mq">qpush</command>.
belaran@964 182 <!-- &interaction.mq.guards.qselect.qpush; -->
belaran@964 183 </para>
belaran@964 184
belaran@964 185 <para>A guard cannot start with a <quote><literal>+</literal></quote> or <quote><literal>-</literal></quote>
belaran@964 186 character. The name of a guard must not contain white space, but most
belaran@964 187 other characters are acceptable. If you try to use a guard with an
belaran@964 188 invalid name, MQ will complain:
belaran@964 189 <!-- &interaction.mq.guards.qselect.error; -->
belaran@964 190 Changing the selected guards changes the patches that are applied.
belaran@964 191 <!-- &interaction.mq.guards.qselect.quux; -->
belaran@964 192 You can see in the example below that negative guards take precedence
belaran@964 193 over positive guards.
belaran@964 194 <!-- &interaction.mq.guards.qselect.foobar; -->
belaran@964 195 </para>
belaran@964 196
belaran@964 197 </sect1>
belaran@964 198 <sect1>
belaran@964 199 <title>MQ's rules for applying patches</title>
belaran@964 200
belaran@964 201 <para>The rules that MQ uses when deciding whether to apply a patch
belaran@964 202 are as follows.
belaran@964 203 </para>
belaran@964 204 <itemizedlist>
belaran@964 205 <listitem><para>A patch that has no guards is always applied.
belaran@964 206 </para>
belaran@964 207 </listitem>
belaran@964 208 <listitem><para>If the patch has any negative guard that matches any currently
belaran@964 209 selected guard, the patch is skipped.
belaran@964 210 </para>
belaran@964 211 </listitem>
belaran@964 212 <listitem><para>If the patch has any positive guard that matches any currently
belaran@964 213 selected guard, the patch is applied.
belaran@964 214 </para>
belaran@964 215 </listitem>
belaran@964 216 <listitem><para>If the patch has positive or negative guards, but none matches
belaran@964 217 any currently selected guard, the patch is skipped.
belaran@964 218 </para>
belaran@964 219 </listitem></itemizedlist>
belaran@964 220
belaran@964 221 </sect1>
belaran@964 222 <sect1>
belaran@964 223 <title>Trimming the work environment</title>
belaran@964 224
belaran@964 225 <para>In working on the device driver I mentioned earlier, I don't apply the
belaran@964 226 patches to a normal Linux kernel tree. Instead, I use a repository
belaran@964 227 that contains only a snapshot of the source files and headers that are
belaran@964 228 relevant to Infiniband development. This repository is 1% the size
belaran@964 229 of a kernel repository, so it's easier to work with.
belaran@964 230 </para>
belaran@964 231
belaran@964 232 <para>I then choose a <quote>base</quote> version on top of which the patches are
belaran@964 233 applied. This is a snapshot of the Linux kernel tree as of a revision
belaran@964 234 of my choosing. When I take the snapshot, I record the changeset ID
belaran@964 235 from the kernel repository in the commit message. Since the snapshot
belaran@964 236 preserves the <quote>shape</quote> and content of the relevant parts of the
belaran@964 237 kernel tree, I can apply my patches on top of either my tiny
belaran@964 238 repository or a normal kernel tree.
belaran@964 239 </para>
belaran@964 240
belaran@964 241 <para>Normally, the base tree atop which the patches apply should be a
belaran@964 242 snapshot of a very recent upstream tree. This best facilitates the
belaran@964 243 development of patches that can easily be submitted upstream with few
belaran@964 244 or no modifications.
belaran@964 245 </para>
belaran@964 246
belaran@964 247 </sect1>
belaran@964 248 <sect1>
belaran@964 249 <title>Dividing up the <filename role="special">series</filename> file</title>
belaran@964 250
belaran@964 251 <para>I categorise the patches in the <filename role="special">series</filename> file into a number
belaran@964 252 of logical groups. Each section of like patches begins with a block
belaran@964 253 of comments that describes the purpose of the patches that follow.
belaran@964 254 </para>
belaran@964 255
belaran@964 256 <para>The sequence of patch groups that I maintain follows. The ordering of
belaran@964 257 these groups is important; I'll describe why after I introduce the
belaran@964 258 groups.
belaran@964 259 </para>
belaran@964 260 <itemizedlist>
belaran@964 261 <listitem><para>The <quote>accepted</quote> group. Patches that the development team has
belaran@964 262 submitted to the maintainer of the Infiniband subsystem, and which
belaran@964 263 he has accepted, but which are not present in the snapshot that the
belaran@964 264 tiny repository is based on. These are <quote>read only</quote> patches,
belaran@964 265 present only to transform the tree into a similar state as it is in
belaran@964 266 the upstream maintainer's repository.
belaran@964 267 </para>
belaran@964 268 </listitem>
belaran@964 269 <listitem><para>The <quote>rework</quote> group. Patches that I have submitted, but that
belaran@964 270 the upstream maintainer has requested modifications to before he
belaran@964 271 will accept them.
belaran@964 272 </para>
belaran@964 273 </listitem>
belaran@964 274 <listitem><para>The <quote>pending</quote> group. Patches that I have not yet submitted to
belaran@964 275 the upstream maintainer, but which we have finished working on.
belaran@964 276 These will be <quote>read only</quote> for a while. If the upstream maintainer
belaran@964 277 accepts them upon submission, I'll move them to the end of the
belaran@964 278 <quote>accepted</quote> group. If he requests that I modify any, I'll move
belaran@964 279 them to the beginning of the <quote>rework</quote> group.
belaran@964 280 </para>
belaran@964 281 </listitem>
belaran@964 282 <listitem><para>The <quote>in progress</quote> group. Patches that are actively being
belaran@964 283 developed, and should not be submitted anywhere yet.
belaran@964 284 </para>
belaran@964 285 </listitem>
belaran@964 286 <listitem><para>The <quote>backport</quote> group. Patches that adapt the source tree to
belaran@964 287 older versions of the kernel tree.
belaran@964 288 </para>
belaran@964 289 </listitem>
belaran@964 290 <listitem><para>The <quote>do not ship</quote> group. Patches that for some reason should
belaran@964 291 never be submitted upstream. For example, one such patch might
belaran@964 292 change embedded driver identification strings to make it easier to
belaran@964 293 distinguish, in the field, between an out-of-tree version of the
belaran@964 294 driver and a version shipped by a distribution vendor.
belaran@964 295 </para>
belaran@964 296 </listitem></itemizedlist>
belaran@964 297
belaran@964 298 <para>Now to return to the reasons for ordering groups of patches in this
belaran@964 299 way. We would like the lowest patches in the stack to be as stable as
belaran@964 300 possible, so that we will not need to rework higher patches due to
belaran@964 301 changes in context. Putting patches that will never be changed first
belaran@964 302 in the <filename role="special">series</filename> file serves this purpose.
belaran@964 303 </para>
belaran@964 304
belaran@964 305 <para>We would also like the patches that we know we'll need to modify to be
belaran@964 306 applied on top of a source tree that resembles the upstream tree as
belaran@964 307 closely as possible. This is why we keep accepted patches around for
belaran@964 308 a while.
belaran@964 309 </para>
belaran@964 310
belaran@964 311 <para>The <quote>backport</quote> and <quote>do not ship</quote> patches float at the end of the
belaran@964 312 <filename role="special">series</filename> file. The backport patches must be applied on top
belaran@964 313 of all other patches, and the <quote>do not ship</quote> patches might as well
belaran@964 314 stay out of harm's way.
belaran@964 315 </para>
belaran@964 316
belaran@964 317 </sect1>
belaran@964 318 <sect1>
belaran@964 319 <title>Maintaining the patch series</title>
belaran@964 320
belaran@964 321 <para>In my work, I use a number of guards to control which patches are to
belaran@964 322 be applied.
belaran@964 323 </para>
belaran@964 324
belaran@964 325 <itemizedlist>
belaran@964 326 <listitem><para><quote>Accepted</quote> patches are guarded with <literal>accepted</literal>. I
belaran@964 327 enable this guard most of the time. When I'm applying the patches
belaran@964 328 on top of a tree where the patches are already present, I can turn
belaran@964 329 this patch off, and the patches that follow it will apply cleanly.
belaran@964 330 </para>
belaran@964 331 </listitem>
belaran@964 332 <listitem><para>Patches that are <quote>finished</quote>, but not yet submitted, have no
belaran@964 333 guards. If I'm applying the patch stack to a copy of the upstream
belaran@964 334 tree, I don't need to enable any guards in order to get a reasonably
belaran@964 335 safe source tree.
belaran@964 336 </para>
belaran@964 337 </listitem>
belaran@964 338 <listitem><para>Those patches that need reworking before being resubmitted are
belaran@964 339 guarded with <literal>rework</literal>.
belaran@964 340 </para>
belaran@964 341 </listitem>
belaran@964 342 <listitem><para>For those patches that are still under development, I use
belaran@964 343 <literal>devel</literal>.
belaran@964 344 </para>
belaran@964 345 </listitem>
belaran@964 346 <listitem><para>A backport patch may have several guards, one for each version
belaran@964 347 of the kernel to which it applies. For example, a patch that
belaran@964 348 backports a piece of code to 2.6.9 will have a <literal>2.6.9</literal> guard.
belaran@964 349 </para>
belaran@964 350 </listitem></itemizedlist>
belaran@964 351 <para>This variety of guards gives me considerable flexibility in
belaran@964 352 determining what kind of source tree I want to end up with. For most
belaran@964 353 situations, the selection of appropriate guards is automated during
belaran@964 354 the build process, but I can manually tune the guards to use for less
belaran@964 355 common circumstances.
belaran@964 356 </para>
belaran@964 357
belaran@964 358 <sect2>
belaran@964 359 <title>The art of writing backport patches</title>
belaran@964 360
belaran@964 361 <para>Using MQ, writing a backport patch is a simple process. All such a
belaran@964 362 patch has to do is modify a piece of code that uses a kernel feature
belaran@964 363 not present in the older version of the kernel, so that the driver
belaran@964 364 continues to work correctly under that older version.
belaran@964 365 </para>
belaran@964 366
belaran@964 367 <para>A useful goal when writing a good backport patch is to make your code
belaran@964 368 look as if it was written for the older version of the kernel you're
belaran@964 369 targeting. The less obtrusive the patch, the easier it will be to
belaran@964 370 understand and maintain. If you're writing a collection of backport
belaran@964 371 patches to avoid the <quote>rat's nest</quote> effect of lots of
belaran@964 372 <literal>#ifdef</literal>s (hunks of source code that are only used
belaran@964 373 conditionally) in your code, don't introduce version-dependent
belaran@964 374 <literal>#ifdef</literal>s into the patches. Instead, write several patches,
belaran@964 375 each of which makes unconditional changes, and control their
belaran@964 376 application using guards.
belaran@964 377 </para>
belaran@964 378
belaran@964 379 <para>There are two reasons to divide backport patches into a distinct
belaran@964 380 group, away from the <quote>regular</quote> patches whose effects they modify.
belaran@964 381 The first is that intermingling the two makes it more difficult to use
belaran@964 382 a tool like the <literal role="hg-ext">patchbomb</literal> extension to automate the process of
belaran@964 383 submitting the patches to an upstream maintainer. The second is that
belaran@964 384 a backport patch could perturb the context in which a subsequent
belaran@964 385 regular patch is applied, making it impossible to apply the regular
belaran@964 386 patch cleanly <emphasis>without</emphasis> the earlier backport patch already being
belaran@964 387 applied.
belaran@964 388 </para>
belaran@964 389
belaran@964 390 </sect2>
belaran@964 391 </sect1>
belaran@964 392 <sect1>
belaran@964 393 <title>Useful tips for developing with MQ</title>
belaran@964 394
belaran@964 395 <sect2>
belaran@964 396 <title>Organising patches in directories</title>
belaran@964 397
belaran@964 398 <para>If you're working on a substantial project with MQ, it's not difficult
belaran@964 399 to accumulate a large number of patches. For example, I have one
belaran@964 400 patch repository that contains over 250 patches.
belaran@964 401 </para>
belaran@964 402
belaran@964 403 <para>If you can group these patches into separate logical categories, you
belaran@964 404 can if you like store them in different directories; MQ has no
belaran@964 405 problems with patch names that contain path separators.
belaran@964 406 </para>
belaran@964 407
belaran@964 408 </sect2>
belaran@964 409 <sect2>
belaran@964 410 <title>Viewing the history of a patch</title>
belaran@964 411 <para>\label{mq-collab:tips:interdiff}
belaran@964 412 </para>
belaran@964 413
belaran@964 414 <para>If you're developing a set of patches over a long time, it's a good
belaran@964 415 idea to maintain them in a repository, as discussed in
belaran@964 416 section <xref linkend="sec:mq:repo"/>. If you do so, you'll quickly discover that
belaran@964 417 using the <command role="hg-cmd">hg diff</command> command to look at the history of changes to a
belaran@964 418 patch is unworkable. This is in part because you're looking at the
belaran@964 419 second derivative of the real code (a diff of a diff), but also
belaran@964 420 because MQ adds noise to the process by modifying time stamps and
belaran@964 421 directory names when it updates a patch.
belaran@964 422 </para>
belaran@964 423
belaran@964 424 <para>However, you can use the <literal role="hg-ext">extdiff</literal> extension, which is bundled
belaran@964 425 with Mercurial, to turn a diff of two versions of a patch into
belaran@964 426 something readable. To do this, you will need a third-party package
belaran@964 427 called <literal role="package">patchutils</literal> <citation>web:patchutils</citation>. This provides a
belaran@964 428 command named <command>interdiff</command>, which shows the differences between
belaran@964 429 two diffs as a diff. Used on two versions of the same diff, it
belaran@964 430 generates a diff that represents the diff from the first to the second
belaran@964 431 version.
belaran@964 432 </para>
belaran@964 433
belaran@964 434 <para>You can enable the <literal role="hg-ext">extdiff</literal> extension in the usual way, by
belaran@964 435 adding a line to the <literal role="rc-extensions">extensions</literal> section of your <filename role="special"> /.hgrc</filename>.
belaran@964 436 </para>
belaran@964 437 <programlisting>
belaran@964 438 <para> [extensions]
belaran@964 439 extdiff =
belaran@964 440 </para>
belaran@964 441 </programlisting>
belaran@964 442 <para>The <command>interdiff</command> command expects to be passed the names of two
belaran@964 443 files, but the <literal role="hg-ext">extdiff</literal> extension passes the program it runs a
belaran@964 444 pair of directories, each of which can contain an arbitrary number of
belaran@964 445 files. We thus need a small program that will run <command>interdiff</command>
belaran@964 446 on each pair of files in these two directories. This program is
belaran@964 447 available as <filename role="special">hg-interdiff</filename> in the <filename class="directory">examples</filename>
belaran@964 448 directory of the source code repository that accompanies this book.
belaran@964 449 <!-- &example.hg-interdiff; -->
belaran@964 450 </para>
belaran@964 451
belaran@964 452 <para>With the <filename role="special">hg-interdiff</filename> program in your shell's search path,
belaran@964 453 you can run it as follows, from inside an MQ patch directory:
belaran@964 454 </para>
belaran@964 455 <programlisting>
belaran@964 456 <para> hg extdiff -p hg-interdiff -r A:B my-change.patch
belaran@964 457 </para>
belaran@964 458 </programlisting>
belaran@964 459 <para>Since you'll probably want to use this long-winded command a lot, you
belaran@964 460 can get <literal role="hg-ext">hgext</literal> to make it available as a normal Mercurial
belaran@964 461 command, again by editing your <filename role="special"> /.hgrc</filename>.
belaran@964 462 </para>
belaran@964 463 <programlisting>
belaran@964 464 <para> [extdiff]
belaran@964 465 cmd.interdiff = hg-interdiff
belaran@964 466 </para>
belaran@964 467 </programlisting>
belaran@964 468 <para>This directs <literal role="hg-ext">hgext</literal> to make an <literal>interdiff</literal> command
belaran@964 469 available, so you can now shorten the previous invocation of
belaran@964 470 <command role="hg-ext-extdiff">extdiff</command> to something a little more wieldy.
belaran@964 471 </para>
belaran@964 472 <programlisting>
belaran@964 473 <para> hg interdiff -r A:B my-change.patch
belaran@964 474 </para>
belaran@964 475 </programlisting>
belaran@964 476
belaran@964 477 <note>
belaran@964 478 <para> The <command>interdiff</command> command works well only if the underlying
belaran@964 479 files against which versions of a patch are generated remain the
belaran@964 480 same. If you create a patch, modify the underlying files, and then
belaran@964 481 regenerate the patch, <command>interdiff</command> may not produce useful
belaran@964 482 output.
belaran@964 483 </para>
belaran@964 484 </note>
belaran@964 485
belaran@964 486 <para>The <literal role="hg-ext">extdiff</literal> extension is useful for more than merely improving
belaran@964 487 the presentation of MQ patches. To read more about it, go to
belaran@964 488 section <xref linkend="sec:hgext:extdiff"/>.
belaran@964 489 </para>
belaran@964 490
belaran@964 491 </sect2>
belaran@964 492 </sect1>
belaran@964 493 </chapter>
belaran@964 494
belaran@964 495 <!--
belaran@964 496 local variables:
belaran@964 497 sgml-parent-document: ("00book.xml" "book" "chapter")
belaran@964 498 end:
belaran@964 499 -->