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 --> |