hgbook

view en/ch14-hgext.xml @ 1114:527b86d55d4a

inotify: update installation information

inotify is shipped in Mercurial since 1.0, which greatly simplifies the installation process
author Nicolas Dumazet <nicdumz.commits@gmail.com>
date Sun Dec 13 16:35:56 2009 +0900 (2009-12-13)
parents acf9dc5f088d
children
line source
1 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
3 <chapter id="chap:hgext">
4 <?dbhtml filename="adding-functionality-with-extensions.html"?>
5 <title>Adding functionality with extensions</title>
7 <para id="x_4fe">While the core of Mercurial is quite complete from a
8 functionality standpoint, it's deliberately shorn of fancy
9 features. This approach of preserving simplicity keeps the
10 software easy to deal with for both maintainers and users.</para>
12 <para id="x_4ff">However, Mercurial doesn't box you in with an inflexible
13 command set: you can add features to it as
14 <emphasis>extensions</emphasis> (sometimes known as
15 <emphasis>plugins</emphasis>). We've already discussed a few of
16 these extensions in earlier chapters.</para>
17 <itemizedlist>
18 <listitem><para id="x_500"><xref linkend="sec:tour-merge:fetch"/>
19 covers the <literal role="hg-ext">fetch</literal> extension;
20 this combines pulling new changes and merging them with local
21 changes into a single command, <command
22 role="hg-ext-fetch">fetch</command>.</para>
23 </listitem>
24 <listitem><para id="x_501">In <xref linkend="chap:hook"/>, we covered
25 several extensions that are useful for hook-related
26 functionality: <literal role="hg-ext">acl</literal> adds
27 access control lists; <literal
28 role="hg-ext">bugzilla</literal> adds integration with the
29 Bugzilla bug tracking system; and <literal
30 role="hg-ext">notify</literal> sends notification emails on
31 new changes.</para>
32 </listitem>
33 <listitem><para id="x_502">The Mercurial Queues patch management extension is
34 so invaluable that it merits two chapters and an appendix all
35 to itself. <xref linkend="chap:mq"/> covers the
36 basics; <xref
37 linkend="chap:mq-collab"/> discusses advanced topics;
38 and <xref linkend="chap:mqref"/> goes into detail on
39 each
40 command.</para>
41 </listitem></itemizedlist>
43 <para id="x_503">In this chapter, we'll cover some of the other extensions that
44 are available for Mercurial, and briefly touch on some of the
45 machinery you'll need to know about if you want to write an
46 extension of your own.</para>
47 <itemizedlist>
48 <listitem><para id="x_504">In <xref linkend="sec:hgext:inotify"/>,
49 we'll discuss the possibility of <emphasis>huge</emphasis>
50 performance improvements using the <literal
51 role="hg-ext">inotify</literal> extension.</para>
52 </listitem></itemizedlist>
54 <sect1 id="sec:hgext:inotify">
55 <title>Improve performance with the <literal
56 role="hg-ext">inotify</literal> extension</title>
58 <para id="x_505">Are you interested in having some of the most common
59 Mercurial operations run as much as a hundred times faster?
60 Read on!</para>
62 <para id="x_506">Mercurial has great performance under normal circumstances.
63 For example, when you run the <command role="hg-cmd">hg
64 status</command> command, Mercurial has to scan almost every
65 directory and file in your repository so that it can display
66 file status. Many other Mercurial commands need to do the same
67 work behind the scenes; for example, the <command
68 role="hg-cmd">hg diff</command> command uses the status
69 machinery to avoid doing an expensive comparison operation on
70 files that obviously haven't changed.</para>
72 <para id="x_507">Because obtaining file status is crucial to good
73 performance, the authors of Mercurial have optimised this code
74 to within an inch of its life. However, there's no avoiding the
75 fact that when you run <command role="hg-cmd">hg
76 status</command>, Mercurial is going to have to perform at
77 least one expensive system call for each managed file to
78 determine whether it's changed since the last time Mercurial
79 checked. For a sufficiently large repository, this can take a
80 long time.</para>
82 <para id="x_508">To put a number on the magnitude of this effect, I created a
83 repository containing 150,000 managed files. I timed <command
84 role="hg-cmd">hg status</command> as taking ten seconds to
85 run, even when <emphasis>none</emphasis> of those files had been
86 modified.</para>
88 <para id="x_509">Many modern operating systems contain a file notification
89 facility. If a program signs up to an appropriate service, the
90 operating system will notify it every time a file of interest is
91 created, modified, or deleted. On Linux systems, the kernel
92 component that does this is called
93 <literal>inotify</literal>.</para>
95 <para id="x_50a">Mercurial's <literal role="hg-ext">inotify</literal>
96 extension talks to the kernel's <literal>inotify</literal>
97 component to optimise <command role="hg-cmd">hg status</command>
98 commands. The extension has two components. A daemon sits in
99 the background and receives notifications from the
100 <literal>inotify</literal> subsystem. It also listens for
101 connections from a regular Mercurial command. The extension
102 modifies Mercurial's behavior so that instead of scanning the
103 filesystem, it queries the daemon. Since the daemon has perfect
104 information about the state of the repository, it can respond
105 with a result instantaneously, avoiding the need to scan every
106 directory and file in the repository.</para>
108 <para id="x_50b">Recall the ten seconds that I measured plain Mercurial as
109 taking to run <command role="hg-cmd">hg status</command> on a
110 150,000 file repository. With the <literal
111 role="hg-ext">inotify</literal> extension enabled, the time
112 dropped to 0.1 seconds, a factor of <emphasis>one
113 hundred</emphasis> faster.</para>
115 <para id="x_50c">Before we continue, please pay attention to some
116 caveats.</para>
117 <itemizedlist>
118 <listitem><para id="x_50d">The <literal role="hg-ext">inotify</literal>
119 extension is Linux-specific. Because it interfaces directly
120 to the Linux kernel's <literal>inotify</literal> subsystem,
121 it does not work on other operating systems.</para>
122 </listitem>
123 <listitem><para id="x_50e">It should work on any Linux distribution that
124 was released after early 2005. Older distributions are
125 likely to have a kernel that lacks
126 <literal>inotify</literal>, or a version of
127 <literal>glibc</literal> that does not have the necessary
128 interfacing support.</para>
129 </listitem>
130 <listitem><para id="x_50f">Not all filesystems are suitable for use with
131 the <literal role="hg-ext">inotify</literal> extension.
132 Network filesystems such as NFS are a non-starter, for
133 example, particularly if you're running Mercurial on several
134 systems, all mounting the same network filesystem. The
135 kernel's <literal>inotify</literal> system has no way of
136 knowing about changes made on another system. Most local
137 filesystems (e.g. ext3, XFS, ReiserFS) should work
138 fine.</para>
139 </listitem></itemizedlist>
141 <para id="x_510">The <literal role="hg-ext">inotify</literal> extension is
142 shipped with Mercurial since 1.0.
143 All you need to do to enable the <literal
144 role="hg-ext">inotify</literal> extension is add an entry to
145 your <filename role="special">~/.hgrc</filename>.</para>
146 <programlisting>[extensions] inotify =</programlisting>
147 <para id="x_51c">When the <literal role="hg-ext">inotify</literal> extension
148 is enabled, Mercurial will automatically and transparently start
149 the status daemon the first time you run a command that needs
150 status in a repository. It runs one status daemon per
151 repository.</para>
153 <para id="x_51d">The status daemon is started silently, and runs in the
154 background. If you look at a list of running processes after
155 you've enabled the <literal role="hg-ext">inotify</literal>
156 extension and run a few commands in different repositories,
157 you'll thus see a few <literal>hg</literal> processes sitting
158 around, waiting for updates from the kernel and queries from
159 Mercurial.</para>
161 <para id="x_51e">The first time you run a Mercurial command in a repository
162 when you have the <literal role="hg-ext">inotify</literal>
163 extension enabled, it will run with about the same performance
164 as a normal Mercurial command. This is because the status
165 daemon needs to perform a normal status scan so that it has a
166 baseline against which to apply later updates from the kernel.
167 However, <emphasis>every</emphasis> subsequent command that does
168 any kind of status check should be noticeably faster on
169 repositories of even fairly modest size. Better yet, the bigger
170 your repository is, the greater a performance advantage you'll
171 see. The <literal role="hg-ext">inotify</literal> daemon makes
172 status operations almost instantaneous on repositories of all
173 sizes!</para>
175 <para id="x_51f">If you like, you can manually start a status daemon using
176 the <command role="hg-ext-inotify">inserve</command> command.
177 This gives you slightly finer control over how the daemon ought
178 to run. This command will of course only be available when the
179 <literal role="hg-ext">inotify</literal> extension is
180 enabled.</para>
182 <para id="x_520">When you're using the <literal
183 role="hg-ext">inotify</literal> extension, you should notice
184 <emphasis>no difference at all</emphasis> in Mercurial's
185 behavior, with the sole exception of status-related commands
186 running a whole lot faster than they used to. You should
187 specifically expect that commands will not print different
188 output; neither should they give different results. If either of
189 these situations occurs, please report a bug.</para>
191 </sect1>
192 <sect1 id="sec:hgext:extdiff">
193 <title>Flexible diff support with the <literal
194 role="hg-ext">extdiff</literal> extension</title>
196 <para id="x_521">Mercurial's built-in <command role="hg-cmd">hg
197 diff</command> command outputs plaintext unified diffs.</para>
199 &interaction.extdiff.diff;
201 <para id="x_522">If you would like to use an external tool to display
202 modifications, you'll want to use the <literal
203 role="hg-ext">extdiff</literal> extension. This will let you
204 use, for example, a graphical diff tool.</para>
206 <para id="x_523">The <literal role="hg-ext">extdiff</literal> extension is
207 bundled with Mercurial, so it's easy to set up. In the <literal
208 role="rc-extensions">extensions</literal> section of your
209 <filename role="special">~/.hgrc</filename>, simply add a
210 one-line entry to enable the extension.</para>
211 <programlisting>[extensions]
212 extdiff =</programlisting>
213 <para id="x_524">This introduces a command named <command
214 role="hg-ext-extdiff">extdiff</command>, which by default uses
215 your system's <command>diff</command> command to generate a
216 unified diff in the same form as the built-in <command
217 role="hg-cmd">hg diff</command> command.</para>
219 &interaction.extdiff.extdiff;
221 <para id="x_525">The result won't be exactly the same as with the built-in
222 <command role="hg-cmd">hg diff</command> variations, because the
223 output of <command>diff</command> varies from one system to
224 another, even when passed the same options.</para>
226 <para id="x_526">As the <quote><literal>making snapshot</literal></quote>
227 lines of output above imply, the <command
228 role="hg-ext-extdiff">extdiff</command> command works by
229 creating two snapshots of your source tree. The first snapshot
230 is of the source revision; the second, of the target revision or
231 working directory. The <command
232 role="hg-ext-extdiff">extdiff</command> command generates
233 these snapshots in a temporary directory, passes the name of
234 each directory to an external diff viewer, then deletes the
235 temporary directory. For efficiency, it only snapshots the
236 directories and files that have changed between the two
237 revisions.</para>
239 <para id="x_527">Snapshot directory names have the same base name as your
240 repository. If your repository path is <filename
241 class="directory">/quux/bar/foo</filename>, then <filename
242 class="directory">foo</filename> will be the name of each
243 snapshot directory. Each snapshot directory name has its
244 changeset ID appended, if appropriate. If a snapshot is of
245 revision <literal>a631aca1083f</literal>, the directory will be
246 named <filename class="directory">foo.a631aca1083f</filename>.
247 A snapshot of the working directory won't have a changeset ID
248 appended, so it would just be <filename
249 class="directory">foo</filename> in this example. To see what
250 this looks like in practice, look again at the <command
251 role="hg-ext-extdiff">extdiff</command> example above. Notice
252 that the diff has the snapshot directory names embedded in its
253 header.</para>
255 <para id="x_528">The <command role="hg-ext-extdiff">extdiff</command> command
256 accepts two important options. The <option
257 role="hg-ext-extdiff-cmd-extdiff-opt">hg -p</option> option
258 lets you choose a program to view differences with, instead of
259 <command>diff</command>. With the <option
260 role="hg-ext-extdiff-cmd-extdiff-opt">hg -o</option> option,
261 you can change the options that <command
262 role="hg-ext-extdiff">extdiff</command> passes to the program
263 (by default, these options are
264 <quote><literal>-Npru</literal></quote>, which only make sense
265 if you're running <command>diff</command>). In other respects,
266 the <command role="hg-ext-extdiff">extdiff</command> command
267 acts similarly to the built-in <command role="hg-cmd">hg
268 diff</command> command: you use the same option names, syntax,
269 and arguments to specify the revisions you want, the files you
270 want, and so on.</para>
272 <para id="x_529">As an example, here's how to run the normal system
273 <command>diff</command> command, getting it to generate context
274 diffs (using the <option role="cmd-opt-diff">-c</option> option)
275 instead of unified diffs, and five lines of context instead of
276 the default three (passing <literal>5</literal> as the argument
277 to the <option role="cmd-opt-diff">-C</option> option).</para>
279 &interaction.extdiff.extdiff-ctx;
281 <para id="x_52a">Launching a visual diff tool is just as easy. Here's how to
282 launch the <command>kdiff3</command> viewer.</para>
283 <programlisting>hg extdiff -p kdiff3 -o</programlisting>
285 <para id="x_52b">If your diff viewing command can't deal with directories,
286 you can easily work around this with a little scripting. For an
287 example of such scripting in action with the <literal
288 role="hg-ext">mq</literal> extension and the
289 <command>interdiff</command> command, see <xref
290 linkend="mq-collab:tips:interdiff"/>.</para>
292 <sect2>
293 <title>Defining command aliases</title>
295 <para id="x_52c">It can be cumbersome to remember the options to both the
296 <command role="hg-ext-extdiff">extdiff</command> command and
297 the diff viewer you want to use, so the <literal
298 role="hg-ext">extdiff</literal> extension lets you define
299 <emphasis>new</emphasis> commands that will invoke your diff
300 viewer with exactly the right options.</para>
302 <para id="x_52d">All you need to do is edit your <filename
303 role="special">~/.hgrc</filename>, and add a section named
304 <literal role="rc-extdiff">extdiff</literal>. Inside this
305 section, you can define multiple commands. Here's how to add
306 a <literal>kdiff3</literal> command. Once you've defined
307 this, you can type <quote><literal>hg kdiff3</literal></quote>
308 and the <literal role="hg-ext">extdiff</literal> extension
309 will run <command>kdiff3</command> for you.</para>
310 <programlisting>[extdiff]
311 cmd.kdiff3 =</programlisting>
312 <para id="x_52e">If you leave the right hand side of the definition empty,
313 as above, the <literal role="hg-ext">extdiff</literal>
314 extension uses the name of the command you defined as the name
315 of the external program to run. But these names don't have to
316 be the same. Here, we define a command named
317 <quote><literal>hg wibble</literal></quote>, which runs
318 <command>kdiff3</command>.</para>
319 <programlisting>[extdiff]
320 cmd.wibble = kdiff3</programlisting>
322 <para id="x_52f">You can also specify the default options that you want to
323 invoke your diff viewing program with. The prefix to use is
324 <quote><literal>opts.</literal></quote>, followed by the name
325 of the command to which the options apply. This example
326 defines a <quote><literal>hg vimdiff</literal></quote> command
327 that runs the <command>vim</command> editor's
328 <literal>DirDiff</literal> extension.</para>
329 <programlisting>[extdiff]
330 cmd.vimdiff = vim
331 opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'</programlisting>
333 </sect2>
334 </sect1>
335 <sect1 id="sec:hgext:transplant">
336 <title>Cherrypicking changes with the <literal
337 role="hg-ext">transplant</literal> extension</title>
339 <para id="x_530">Need to have a long chat with Brendan about this.</para>
341 </sect1>
342 <sect1 id="sec:hgext:patchbomb">
343 <title>Send changes via email with the <literal
344 role="hg-ext">patchbomb</literal> extension</title>
346 <para id="x_531">Many projects have a culture of <quote>change
347 review</quote>, in which people send their modifications to a
348 mailing list for others to read and comment on before they
349 commit the final version to a shared repository. Some projects
350 have people who act as gatekeepers; they apply changes from
351 other people to a repository to which those others don't have
352 access.</para>
354 <para id="x_532">Mercurial makes it easy to send changes over email for
355 review or application, via its <literal
356 role="hg-ext">patchbomb</literal> extension. The extension is
357 so named because changes are formatted as patches, and it's usual
358 to send one changeset per email message. Sending a long series
359 of changes by email is thus much like <quote>bombing</quote> the
360 recipient's inbox, hence <quote>patchbomb</quote>.</para>
362 <para id="x_533">As usual, the basic configuration of the <literal
363 role="hg-ext">patchbomb</literal> extension takes just one or
364 two lines in your <filename role="special">
365 /.hgrc</filename>.</para>
366 <programlisting>[extensions]
367 patchbomb =</programlisting>
368 <para id="x_534">Once you've enabled the extension, you will have a new
369 command available, named <command
370 role="hg-ext-patchbomb">email</command>.</para>
372 <para id="x_535">The safest and best way to invoke the <command
373 role="hg-ext-patchbomb">email</command> command is to
374 <emphasis>always</emphasis> run it first with the <option
375 role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option.
376 This will show you what the command <emphasis>would</emphasis>
377 send, without actually sending anything. Once you've had a
378 quick glance over the changes and verified that you are sending
379 the right ones, you can rerun the same command, with the <option
380 role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option
381 removed.</para>
383 <para id="x_536">The <command role="hg-ext-patchbomb">email</command> command
384 accepts the same kind of revision syntax as every other
385 Mercurial command. For example, this command will send every
386 revision between 7 and <literal>tip</literal>, inclusive.</para>
387 <programlisting>hg email -n 7:tip</programlisting>
388 <para id="x_537">You can also specify a <emphasis>repository</emphasis> to
389 compare with. If you provide a repository but no revisions, the
390 <command role="hg-ext-patchbomb">email</command> command will
391 send all revisions in the local repository that are not present
392 in the remote repository. If you additionally specify revisions
393 or a branch name (the latter using the <option
394 role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> option),
395 this will constrain the revisions sent.</para>
397 <para id="x_538">It's perfectly safe to run the <command
398 role="hg-ext-patchbomb">email</command> command without the
399 names of the people you want to send to: if you do this, it will
400 just prompt you for those values interactively. (If you're
401 using a Linux or Unix-like system, you should have enhanced
402 <literal>readline</literal>-style editing capabilities when
403 entering those headers, too, which is useful.)</para>
405 <para id="x_539">When you are sending just one revision, the <command
406 role="hg-ext-patchbomb">email</command> command will by
407 default use the first line of the changeset description as the
408 subject of the single email message it sends.</para>
410 <para id="x_53a">If you send multiple revisions, the <command
411 role="hg-ext-patchbomb">email</command> command will usually
412 send one message per changeset. It will preface the series with
413 an introductory message, in which you should describe the
414 purpose of the series of changes you're sending.</para>
416 <sect2>
417 <title>Changing the behavior of patchbombs</title>
419 <para id="x_53b">Not every project has exactly the same conventions for
420 sending changes in email; the <literal
421 role="hg-ext">patchbomb</literal> extension tries to
422 accommodate a number of variations through command line
423 options.</para>
424 <itemizedlist>
425 <listitem><para id="x_53c">You can write a subject for the introductory
426 message on the command line using the <option
427 role="hg-ext-patchbomb-cmd-email-opt">hg -s</option>
428 option. This takes one argument, the text of the subject
429 to use.</para>
430 </listitem>
431 <listitem><para id="x_53d">To change the email address from which the
432 messages originate, use the <option
433 role="hg-ext-patchbomb-cmd-email-opt">hg -f</option>
434 option. This takes one argument, the email address to
435 use.</para>
436 </listitem>
437 <listitem><para id="x_53e">The default behavior is to send unified diffs
438 (see <xref linkend="sec:mq:patch"/> for a
439 description of the
440 format), one per message. You can send a binary bundle
441 instead with the <option
442 role="hg-ext-patchbomb-cmd-email-opt">hg -b</option>
443 option.</para>
444 </listitem>
445 <listitem><para id="x_53f">Unified diffs are normally prefaced with a
446 metadata header. You can omit this, and send unadorned
447 diffs, with the <option
448 role="hg-ext-patchbomb-cmd-email-opt">hg
449 --plain</option> option.</para>
450 </listitem>
451 <listitem><para id="x_540">Diffs are normally sent <quote>inline</quote>,
452 in the same body part as the description of a patch. This
453 makes it easiest for the largest number of readers to
454 quote and respond to parts of a diff, as some mail clients
455 will only quote the first MIME body part in a message. If
456 you'd prefer to send the description and the diff in
457 separate body parts, use the <option
458 role="hg-ext-patchbomb-cmd-email-opt">hg -a</option>
459 option.</para>
460 </listitem>
461 <listitem><para id="x_541">Instead of sending mail messages, you can
462 write them to an <literal>mbox</literal>-format mail
463 folder using the <option
464 role="hg-ext-patchbomb-cmd-email-opt">hg -m</option>
465 option. That option takes one argument, the name of the
466 file to write to.</para>
467 </listitem>
468 <listitem><para id="x_542">If you would like to add a
469 <command>diffstat</command>-format summary to each patch,
470 and one to the introductory message, use the <option
471 role="hg-ext-patchbomb-cmd-email-opt">hg -d</option>
472 option. The <command>diffstat</command> command displays
473 a table containing the name of each file patched, the
474 number of lines affected, and a histogram showing how much
475 each file is modified. This gives readers a qualitative
476 glance at how complex a patch is.</para>
477 </listitem></itemizedlist>
479 </sect2>
480 </sect1>
481 </chapter>
483 <!--
484 local variables:
485 sgml-parent-document: ("00book.xml" "book" "chapter")
486 end:
487 -->