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