hgbook
changeset 559:b90b024729f1
WIP DocBook snapshot that all compiles. Mirabile dictu!
author | Bryan O'Sullivan <bos@serpentine.com> |
---|---|
date | Wed Feb 18 00:22:09 2009 -0800 (2009-02-18) |
parents | 8631da51309b |
children | dbe91bb622d8 |
files | .hgignore en/00book.xml en/Makefile en/appA-cmdref.xml en/appB-mq-ref.xml en/appC-srcinstall.xml en/appD-license.xml en/ch00-preface.xml en/ch02-tour-basic.xml en/ch03-tour-merge.xml en/ch04-concepts.xml en/ch05-daily.xml en/ch06-collab.xml en/ch07-filenames.xml en/ch08-branch.xml en/ch09-undo.xml en/ch10-hook.xml en/ch11-template.xml en/ch12-mq.xml en/ch13-mq-collab.xml en/ch14-hgext.xml tools/latex-to-docbook |
line diff
1.1 --- a/.hgignore Mon Feb 09 23:25:40 2009 -0800 1.2 +++ b/.hgignore Wed Feb 18 00:22:09 2009 -0800 1.3 @@ -35,3 +35,4 @@ 1.4 .*.swp 1.5 .\#* 1.6 .run 1.7 +xsl/system-xsl
2.1 --- a/en/00book.xml Mon Feb 09 23:25:40 2009 -0800 2.2 +++ b/en/00book.xml Wed Feb 18 00:22:09 2009 -0800 2.3 @@ -9,7 +9,22 @@ 2.4 2.5 <!ENTITY ch01 SYSTEM "ch01-intro.xml"> 2.6 <!ENTITY ch02 SYSTEM "ch02-tour-basic.xml"> 2.7 +<!ENTITY ch03 SYSTEM "ch03-tour-merge.xml"> 2.8 +<!ENTITY ch04 SYSTEM "ch04-concepts.xml"> 2.9 +<!ENTITY ch05 SYSTEM "ch05-daily.xml"> 2.10 +<!ENTITY ch06 SYSTEM "ch06-collab.xml"> 2.11 +<!ENTITY ch07 SYSTEM "ch07-filenames.xml"> 2.12 +<!ENTITY ch08 SYSTEM "ch08-branch.xml"> 2.13 +<!ENTITY ch09 SYSTEM "ch09-undo.xml"> 2.14 +<!ENTITY ch10 SYSTEM "ch10-hook.xml"> 2.15 +<!ENTITY ch11 SYSTEM "ch11-template.xml"> 2.16 <!ENTITY ch12 SYSTEM "ch12-mq.xml"> 2.17 +<!ENTITY ch13 SYSTEM "ch13-mq-collab.xml"> 2.18 +<!ENTITY ch14 SYSTEM "ch14-hgext.xml"> 2.19 +<!ENTITY appA SYSTEM "appA-cmdref.xml"> 2.20 +<!ENTITY appB SYSTEM "appB-mq-ref.xml"> 2.21 +<!ENTITY appC SYSTEM "appC-srcinstall.xml"> 2.22 +<!ENTITY appD SYSTEM "appD-license.xml"> 2.23 2.24 <!-- Include our standard shortcuts. --> 2.25 2.26 @@ -41,5 +56,20 @@ 2.27 2.28 &ch01; 2.29 &ch02; 2.30 + &ch03; 2.31 + &ch04; 2.32 + &ch05; 2.33 + &ch06; 2.34 + &ch07; 2.35 + &ch08; 2.36 + &ch09; 2.37 + &ch10; 2.38 + &ch11; 2.39 &ch12; 2.40 + &ch13; 2.41 + &ch14; 2.42 + <!-- &appA; --> 2.43 + &appB; 2.44 + &appC; 2.45 + &appD; 2.46 </book>
3.1 --- a/en/Makefile Mon Feb 09 23:25:40 2009 -0800 3.2 +++ b/en/Makefile Wed Feb 18 00:22:09 2009 -0800 3.3 @@ -33,9 +33,8 @@ 3.4 3.5 xml-src-files := \ 3.6 00book.xml \ 3.7 - ch01-intro.xml \ 3.8 - ch02-tour-basic.xml \ 3.9 - ch12-mq.xml 3.10 + app*.xml \ 3.11 + ch*.xml 3.12 3.13 image-dot := $(filter %.dot,$(image-sources)) 3.14 image-svg := $(filter %.svg,$(image-sources))
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/en/appA-cmdref.xml Wed Feb 18 00:22:09 2009 -0800 4.3 @@ -0,0 +1,223 @@ 4.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 4.5 + 4.6 +<appendix id="cmdref"> 4.7 +<title>Command reference</title> 4.8 + 4.9 +<para>\cmdref{add}{add files at the next commit} 4.10 +\optref{add}{I}{include} 4.11 +\optref{add}{X}{exclude} 4.12 +\optref{add}{n}{dry-run}</para> 4.13 + 4.14 +<para>\cmdref{diff}{print changes in history or working directory}</para> 4.15 + 4.16 +<para>Show differences between revisions for the specified files or 4.17 +directories, using the unified diff format. For a description of the 4.18 +unified diff format, see section <xref linkend="sec:mq:patch"/>.</para> 4.19 + 4.20 +<para>By default, this command does not print diffs for files that Mercurial 4.21 +considers to contain binary data. To control this behaviour, see the 4.22 +<option role="hg-opt-diff">-a</option> and <option role="hg-opt-diff">--git</option> options.</para> 4.23 + 4.24 +<sect2> 4.25 +<title>Options</title> 4.26 + 4.27 +<para>\loptref{diff}{nodates}</para> 4.28 + 4.29 +<para>Omit date and time information when printing diff headers.</para> 4.30 + 4.31 +<para>\optref{diff}{B}{ignore-blank-lines}</para> 4.32 + 4.33 +<para>Do not print changes that only insert or delete blank lines. A line 4.34 +that contains only whitespace is not considered blank. 4.35 +</para> 4.36 + 4.37 +<para>\optref{diff}{I}{include} 4.38 +</para> 4.39 + 4.40 +<para>Include files and directories whose names match the given patterns. 4.41 +</para> 4.42 + 4.43 +<para>\optref{diff}{X}{exclude} 4.44 +</para> 4.45 + 4.46 +<para>Exclude files and directories whose names match the given patterns. 4.47 +</para> 4.48 + 4.49 +<para>\optref{diff}{a}{text} 4.50 +</para> 4.51 + 4.52 +<para>If this option is not specified, <command role="hg-cmd">hg diff</command> will refuse to print 4.53 +diffs for files that it detects as binary. Specifying <option role="hg-opt-diff">-a</option> 4.54 +forces <command role="hg-cmd">hg diff</command> to treat all files as text, and generate diffs for 4.55 +all of them. 4.56 +</para> 4.57 + 4.58 +<para>This option is useful for files that are <quote>mostly text</quote> but have a 4.59 +few embedded NUL characters. If you use it on files that contain a 4.60 +lot of binary data, its output will be incomprehensible. 4.61 +</para> 4.62 + 4.63 +<para>\optref{diff}{b}{ignore-space-change} 4.64 +</para> 4.65 + 4.66 +<para>Do not print a line if the only change to that line is in the amount 4.67 +of white space it contains. 4.68 +</para> 4.69 + 4.70 +<para>\optref{diff}{g}{git} 4.71 +</para> 4.72 + 4.73 +<para>Print <command>git</command>-compatible diffs. XXX reference a format 4.74 +description. 4.75 +</para> 4.76 + 4.77 +<para>\optref{diff}{p}{show-function} 4.78 +</para> 4.79 + 4.80 +<para>Display the name of the enclosing function in a hunk header, using a 4.81 +simple heuristic. This functionality is enabled by default, so the 4.82 +<option role="hg-opt-diff">-p</option> option has no effect unless you change the value of 4.83 +the <envar role="rc-item-diff">showfunc</envar> config item, as in the following example.</para> 4.84 + 4.85 +<!-- &interaction.cmdref.diff-p; --> 4.86 + 4.87 +<para>\optref{diff}{r}{rev} 4.88 +</para> 4.89 + 4.90 +<para>Specify one or more revisions to compare. The <command role="hg-cmd">hg diff</command> command 4.91 +accepts up to two <option role="hg-opt-diff">-r</option> options to specify the revisions to 4.92 +compare. 4.93 +</para> 4.94 + 4.95 +<orderedlist> 4.96 +<listitem><para>Display the differences between the parent revision of the 4.97 + working directory and the working directory. 4.98 +</para> 4.99 +</listitem> 4.100 +<listitem><para>Display the differences between the specified changeset and the 4.101 + working directory. 4.102 +</para> 4.103 +</listitem> 4.104 +<listitem><para>Display the differences between the two specified changesets. 4.105 +</para> 4.106 +</listitem></orderedlist> 4.107 + 4.108 +<para>You can specify two revisions using either two <option role="hg-opt-diff">-r</option> 4.109 +options or revision range notation. For example, the two revision 4.110 +specifications below are equivalent. 4.111 +</para> 4.112 +<programlisting>hg diff -r 10 -r 20 4.113 +hg diff -r10:20</programlisting> 4.114 + 4.115 +<para>When you provide two revisions, Mercurial treats the order of those 4.116 +revisions as significant. Thus, <command role="hg-cmd">hg diff -r10:20</command> will 4.117 +produce a diff that will transform files from their contents as of 4.118 +revision 10 to their contents as of revision 20, while 4.119 +<command role="hg-cmd">hg diff -r20:10</command> means the opposite: the diff that will 4.120 +transform files from their revision 20 contents to their revision 10 4.121 +contents. You cannot reverse the ordering in this way if you are 4.122 +diffing against the working directory. 4.123 +</para> 4.124 + 4.125 +<para>\optref{diff}{w}{ignore-all-space} 4.126 +</para> 4.127 + 4.128 +<para>\cmdref{version}{print version and copyright information} 4.129 +</para> 4.130 + 4.131 +<para>This command displays the version of Mercurial you are running, and 4.132 +its copyright license. There are four kinds of version string that 4.133 +you may see. 4.134 +</para> 4.135 +<itemizedlist> 4.136 +<listitem><para>The string <quote><literal>unknown</literal></quote>. This version of Mercurial was 4.137 + not built in a Mercurial repository, and cannot determine its own 4.138 + version. 4.139 +</para> 4.140 +</listitem> 4.141 +<listitem><para>A short numeric string, such as <quote><literal>1.1</literal></quote>. This is a 4.142 + build of a revision of Mercurial that was identified by a specific 4.143 + tag in the repository where it was built. (This doesn't necessarily 4.144 + mean that you're running an official release; someone else could 4.145 + have added that tag to any revision in the repository where they 4.146 + built Mercurial.) 4.147 +</para> 4.148 +</listitem> 4.149 +<listitem><para>A hexadecimal string, such as <quote><literal>875489e31abe</literal></quote>. This 4.150 + is a build of the given revision of Mercurial. 4.151 +</para> 4.152 +</listitem> 4.153 +<listitem><para>A hexadecimal string followed by a date, such as 4.154 + <quote><literal>875489e31abe+20070205</literal></quote>. This is a build of the given 4.155 + revision of Mercurial, where the build repository contained some 4.156 + local changes that had not been committed. 4.157 +</para> 4.158 +</listitem></itemizedlist> 4.159 + 4.160 +</sect2> 4.161 +<sect2> 4.162 +<title>Tips and tricks</title> 4.163 + 4.164 +<sect3 id="cmdref:diff-vs-status"> 4.165 +<title>Why do the results of <command role="hg-cmd">hg diff</command> and <command role="hg-cmd">hg status</command> differ?</title> 4.166 + 4.167 +<para>When you run the <command role="hg-cmd">hg status</command> command, you'll see a list of files 4.168 +that Mercurial will record changes for the next time you perform a 4.169 +commit. If you run the <command role="hg-cmd">hg diff</command> command, you may notice that it 4.170 +prints diffs for only a <emphasis>subset</emphasis> of the files that <command role="hg-cmd">hg status</command> 4.171 +listed. There are two possible reasons for this. 4.172 +</para> 4.173 + 4.174 +<para>The first is that <command role="hg-cmd">hg status</command> prints some kinds of modifications 4.175 +that <command role="hg-cmd">hg diff</command> doesn't normally display. The <command role="hg-cmd">hg diff</command> command 4.176 +normally outputs unified diffs, which don't have the ability to 4.177 +represent some changes that Mercurial can track. Most notably, 4.178 +traditional diffs can't represent a change in whether or not a file is 4.179 +executable, but Mercurial records this information. 4.180 +</para> 4.181 + 4.182 +<para>If you use the <option role="hg-opt-diff">--git</option> option to <command role="hg-cmd">hg diff</command>, it will 4.183 +display <command>git</command>-compatible diffs that <emphasis>can</emphasis> display this 4.184 +extra information. 4.185 +</para> 4.186 + 4.187 +<para>The second possible reason that <command role="hg-cmd">hg diff</command> might be printing diffs 4.188 +for a subset of the files displayed by <command role="hg-cmd">hg status</command> is that if you 4.189 +invoke it without any arguments, <command role="hg-cmd">hg diff</command> prints diffs against the 4.190 +first parent of the working directory. If you have run <command role="hg-cmd">hg merge</command> 4.191 +to merge two changesets, but you haven't yet committed the results of 4.192 +the merge, your working directory has two parents (use <command role="hg-cmd">hg parents</command> 4.193 +to see them). While <command role="hg-cmd">hg status</command> prints modifications relative to 4.194 +<emphasis>both</emphasis> parents after an uncommitted merge, <command role="hg-cmd">hg diff</command> still 4.195 +operates relative only to the first parent. You can get it to print 4.196 +diffs relative to the second parent by specifying that parent with the 4.197 +<option role="hg-opt-diff">-r</option> option. There is no way to print diffs relative to 4.198 +both parents. 4.199 +</para> 4.200 + 4.201 +</sect3> 4.202 +<sect3> 4.203 +<title>Generating safe binary diffs</title> 4.204 + 4.205 +<para>If you use the <option role="hg-opt-diff">-a</option> option to force Mercurial to print 4.206 +diffs of files that are either <quote>mostly text</quote> or contain lots of 4.207 +binary data, those diffs cannot subsequently be applied by either 4.208 +Mercurial's <command role="hg-cmd">hg import</command> command or the system's <command>patch</command> 4.209 +command. 4.210 +</para> 4.211 + 4.212 +<para>If you want to generate a diff of a binary file that is safe to use as 4.213 +input for <command role="hg-cmd">hg import</command>, use the <command role="hg-cmd">hg diff</command>{--git} option when you 4.214 +generate the patch. The system <command>patch</command> command cannot handle 4.215 +binary patches at all. 4.216 +</para> 4.217 + 4.218 +</sect3> 4.219 +</sect2> 4.220 +</appendix> 4.221 + 4.222 +<!-- 4.223 +local variables: 4.224 +sgml-parent-document: ("00book.xml" "book" "appendix") 4.225 +end: 4.226 +-->
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/en/appB-mq-ref.xml Wed Feb 18 00:22:09 2009 -0800 5.3 @@ -0,0 +1,568 @@ 5.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 5.5 + 5.6 +<appendix id="chap:mqref"> 5.7 + <title>Mercurial Queues reference</title> 5.8 + 5.9 + <sect1 id="sec:mqref:cmdref"> 5.10 + <title>MQ command reference</title> 5.11 + 5.12 + <para>For an overview of the commands provided by MQ, use the 5.13 + command <command role="hg-cmd">hg help mq</command>.</para> 5.14 + 5.15 + <sect2> 5.16 + <title><command role="hg-ext-mq">qapplied</command>&emdash;print 5.17 + applied patches</title> 5.18 + 5.19 + <para>The <command role="hg-ext-mq">qapplied</command> command 5.20 + prints the current stack of applied patches. Patches are 5.21 + printed in oldest-to-newest order, so the last patch in the 5.22 + list is the <quote>top</quote> patch.</para> 5.23 + 5.24 + </sect2> 5.25 + <sect2> 5.26 + <title><command role="hg-ext-mq">qcommit</command>&emdash;commit 5.27 + changes in the queue repository</title> 5.28 + 5.29 + <para>The <command role="hg-ext-mq">qcommit</command> command 5.30 + commits any outstanding changes in the <filename 5.31 + role="special" class="directory">.hg/patches</filename> 5.32 + repository. This command only works if the <filename 5.33 + role="special" class="directory">.hg/patches</filename> 5.34 + directory is a repository, i.e. you created the directory 5.35 + using <command role="hg-cmd">hg qinit <option 5.36 + role="hg-ext-mq-cmd-qinit-opt">-c</option></command> or 5.37 + ran <command role="hg-cmd">hg init</command> in the directory 5.38 + after running <command 5.39 + role="hg-ext-mq">qinit</command>.</para> 5.40 + 5.41 + <para>This command is shorthand for <command role="hg-cmd">hg 5.42 + commit --cwd .hg/patches</command>.</para> 5.43 + 5.44 + <para>\subsection{<command 5.45 + role="hg-ext-mq">qdelete</command>&emdash;delete a patch 5.46 + from the <filename role="special">series</filename> 5.47 + file}</para> 5.48 + 5.49 + <para>The <command role="hg-ext-mq">qdelete</command> command 5.50 + removes the entry for a patch from the <filename 5.51 + role="special">series</filename> file in the <filename 5.52 + role="special" class="directory">.hg/patches</filename> 5.53 + directory. It does not pop the patch if the patch is already 5.54 + applied. By default, it does not delete the patch file; use 5.55 + the <option role="hg-ext-mq-cmd-qdel-opt">-f</option> option 5.56 + to do that.</para> 5.57 + 5.58 + <para>Options:</para> 5.59 + <itemizedlist> 5.60 + <listitem><para><option 5.61 + role="hg-ext-mq-cmd-qdel-opt">-f</option>: Delete the 5.62 + patch file.</para> 5.63 + </listitem></itemizedlist> 5.64 + 5.65 + </sect2> 5.66 + <sect2> 5.67 + <title><command role="hg-ext-mq">qdiff</command>&emdash;print a 5.68 + diff of the topmost applied patch</title> 5.69 + 5.70 + <para>The <command role="hg-ext-mq">qdiff</command> command 5.71 + prints a diff of the topmost applied patch. It is equivalent 5.72 + to <command role="hg-cmd">hg diff -r-2:-1</command>.</para> 5.73 + 5.74 + </sect2> 5.75 + <sect2> 5.76 + <title><command role="hg-ext-mq">qfold</command>&emdash;merge 5.77 + (<quote>fold</quote>) several patches into one</title> 5.78 + 5.79 + <para>The <command role="hg-ext-mq">qfold</command> command 5.80 + merges multiple patches into the topmost applied patch, so 5.81 + that the topmost applied patch makes the union of all of the 5.82 + changes in the patches in question.</para> 5.83 + 5.84 + <para>The patches to fold must not be applied; <command 5.85 + role="hg-ext-mq">qfold</command> will exit with an error if 5.86 + any is. The order in which patches are folded is significant; 5.87 + <command role="hg-cmd">hg qfold a b</command> means 5.88 + <quote>apply the current topmost patch, followed by 5.89 + <literal>a</literal>, followed by 5.90 + <literal>b</literal></quote>.</para> 5.91 + 5.92 + <para>The comments from the folded patches are appended to the 5.93 + comments of the destination patch, with each block of comments 5.94 + separated by three asterisk 5.95 + (<quote><literal>*</literal></quote>) characters. Use the 5.96 + <option role="hg-ext-mq-cmd-qfold-opt">-e</option> option to 5.97 + edit the commit message for the combined patch/changeset after 5.98 + the folding has completed.</para> 5.99 + 5.100 + <para>Options:</para> 5.101 + <itemizedlist> 5.102 + <listitem><para><option 5.103 + role="hg-ext-mq-cmd-qfold-opt">-e</option>: Edit the 5.104 + commit message and patch description for the newly folded 5.105 + patch.</para> 5.106 + </listitem> 5.107 + <listitem><para><option 5.108 + role="hg-ext-mq-cmd-qfold-opt">-l</option>: Use the 5.109 + contents of the given file as the new commit message and 5.110 + patch description for the folded patch.</para> 5.111 + </listitem> 5.112 + <listitem><para><option 5.113 + role="hg-ext-mq-cmd-qfold-opt">-m</option>: Use the 5.114 + given text as the new commit message and patch description 5.115 + for the folded patch.</para> 5.116 + </listitem></itemizedlist> 5.117 + 5.118 + </sect2> 5.119 + <sect2> 5.120 + <title><command 5.121 + role="hg-ext-mq">qheader</command>&emdash;display the 5.122 + header/description of a patch</title> 5.123 + 5.124 + <para>The <command role="hg-ext-mq">qheader</command> command 5.125 + prints the header, or description, of a patch. By default, it 5.126 + prints the header of the topmost applied patch. Given an 5.127 + argument, it prints the header of the named patch.</para> 5.128 + 5.129 + </sect2> 5.130 + <sect2> 5.131 + <title><command role="hg-ext-mq">qimport</command>&emdash;import 5.132 + a third-party patch into the queue</title> 5.133 + 5.134 + <para>The <command role="hg-ext-mq">qimport</command> command 5.135 + adds an entry for an external patch to the <filename 5.136 + role="special">series</filename> file, and copies the patch 5.137 + into the <filename role="special" 5.138 + class="directory">.hg/patches</filename> directory. It adds 5.139 + the entry immediately after the topmost applied patch, but 5.140 + does not push the patch.</para> 5.141 + 5.142 + <para>If the <filename role="special" 5.143 + class="directory">.hg/patches</filename> directory is a 5.144 + repository, <command role="hg-ext-mq">qimport</command> 5.145 + automatically does an <command role="hg-cmd">hg add</command> 5.146 + of the imported patch.</para> 5.147 + 5.148 + </sect2> 5.149 + <sect2> 5.150 + <title><command role="hg-ext-mq">qinit</command>&emdash;prepare 5.151 + a repository to work with MQ</title> 5.152 + 5.153 + <para>The <command role="hg-ext-mq">qinit</command> command 5.154 + prepares a repository to work with MQ. It creates a directory 5.155 + called <filename role="special" 5.156 + class="directory">.hg/patches</filename>.</para> 5.157 + 5.158 + <para>Options:</para> 5.159 + <itemizedlist> 5.160 + <listitem><para><option 5.161 + role="hg-ext-mq-cmd-qinit-opt">-c</option>: Create 5.162 + <filename role="special" 5.163 + class="directory">.hg/patches</filename> as a repository 5.164 + in its own right. Also creates a <filename 5.165 + role="special">.hgignore</filename> file that will 5.166 + ignore the <filename role="special">status</filename> 5.167 + file.</para> 5.168 + </listitem></itemizedlist> 5.169 + 5.170 + <para>When the <filename role="special" 5.171 + class="directory">.hg/patches</filename> directory is a 5.172 + repository, the <command role="hg-ext-mq">qimport</command> 5.173 + and <command role="hg-ext-mq">qnew</command> commands 5.174 + automatically <command role="hg-cmd">hg add</command> new 5.175 + patches.</para> 5.176 + 5.177 + </sect2> 5.178 + <sect2> 5.179 + <title><command role="hg-ext-mq">qnew</command>&emdash;create a 5.180 + new patch</title> 5.181 + 5.182 + <para>The <command role="hg-ext-mq">qnew</command> command 5.183 + creates a new patch. It takes one mandatory argument, the 5.184 + name to use for the patch file. The newly created patch is 5.185 + created empty by default. It is added to the <filename 5.186 + role="special">series</filename> file after the current 5.187 + topmost applied patch, and is immediately pushed on top of 5.188 + that patch.</para> 5.189 + 5.190 + <para>If <command role="hg-ext-mq">qnew</command> finds modified 5.191 + files in the working directory, it will refuse to create a new 5.192 + patch unless the <option 5.193 + role="hg-ext-mq-cmd-qnew-opt">-f</option> option is used 5.194 + (see below). This behaviour allows you to <command 5.195 + role="hg-ext-mq">qrefresh</command> your topmost applied 5.196 + patch before you apply a new patch on top of it.</para> 5.197 + 5.198 + <para>Options:</para> 5.199 + <itemizedlist> 5.200 + <listitem><para><option 5.201 + role="hg-ext-mq-cmd-qnew-opt">-f</option>: Create a new 5.202 + patch if the contents of the working directory are 5.203 + modified. Any outstanding modifications are added to the 5.204 + newly created patch, so after this command completes, the 5.205 + working directory will no longer be modified.</para> 5.206 + </listitem> 5.207 + <listitem><para><option 5.208 + role="hg-ext-mq-cmd-qnew-opt">-m</option>: Use the given 5.209 + text as the commit message. This text will be stored at 5.210 + the beginning of the patch file, before the patch 5.211 + data.</para> 5.212 + </listitem></itemizedlist> 5.213 + 5.214 + </sect2> 5.215 + <sect2> 5.216 + <title><command role="hg-ext-mq">qnext</command>&emdash;print 5.217 + the name of the next patch</title> 5.218 + 5.219 + <para>The <command role="hg-ext-mq">qnext</command> command 5.220 + prints the name name of the next patch in the <filename 5.221 + role="special">series</filename> file after the topmost 5.222 + applied patch. This patch will become the topmost applied 5.223 + patch if you run <command 5.224 + role="hg-ext-mq">qpush</command>.</para> 5.225 + 5.226 + </sect2> 5.227 + <sect2> 5.228 + <title><command role="hg-ext-mq">qpop</command>&emdash;pop 5.229 + patches off the stack</title> 5.230 + 5.231 + <para>The <command role="hg-ext-mq">qpop</command> command 5.232 + removes applied patches from the top of the stack of applied 5.233 + patches. By default, it removes only one patch.</para> 5.234 + 5.235 + <para>This command removes the changesets that represent the 5.236 + popped patches from the repository, and updates the working 5.237 + directory to undo the effects of the patches.</para> 5.238 + 5.239 + <para>This command takes an optional argument, which it uses as 5.240 + the name or index of the patch to pop to. If given a name, it 5.241 + will pop patches until the named patch is the topmost applied 5.242 + patch. If given a number, <command 5.243 + role="hg-ext-mq">qpop</command> treats the number as an 5.244 + index into the entries in the series file, counting from zero 5.245 + (empty lines and lines containing only comments do not count). 5.246 + It pops patches until the patch identified by the given index 5.247 + is the topmost applied patch.</para> 5.248 + 5.249 + <para>The <command role="hg-ext-mq">qpop</command> command does 5.250 + not read or write patches or the <filename 5.251 + role="special">series</filename> file. It is thus safe to 5.252 + <command role="hg-ext-mq">qpop</command> a patch that you have 5.253 + removed from the <filename role="special">series</filename> 5.254 + file, or a patch that you have renamed or deleted entirely. 5.255 + In the latter two cases, use the name of the patch as it was 5.256 + when you applied it.</para> 5.257 + 5.258 + <para>By default, the <command role="hg-ext-mq">qpop</command> 5.259 + command will not pop any patches if the working directory has 5.260 + been modified. You can override this behaviour using the 5.261 + <option role="hg-ext-mq-cmd-qpop-opt">-f</option> option, 5.262 + which reverts all modifications in the working 5.263 + directory.</para> 5.264 + 5.265 + <para>Options:</para> 5.266 + <itemizedlist> 5.267 + <listitem><para><option 5.268 + role="hg-ext-mq-cmd-qpop-opt">-a</option>: Pop all 5.269 + applied patches. This returns the repository to its state 5.270 + before you applied any patches.</para> 5.271 + </listitem> 5.272 + <listitem><para><option 5.273 + role="hg-ext-mq-cmd-qpop-opt">-f</option>: Forcibly 5.274 + revert any modifications to the working directory when 5.275 + popping.</para> 5.276 + </listitem> 5.277 + <listitem><para><option 5.278 + role="hg-ext-mq-cmd-qpop-opt">-n</option>: Pop a patch 5.279 + from the named queue.</para> 5.280 + </listitem></itemizedlist> 5.281 + 5.282 + <para>The <command role="hg-ext-mq">qpop</command> command 5.283 + removes one line from the end of the <filename 5.284 + role="special">status</filename> file for each patch that it 5.285 + pops.</para> 5.286 + 5.287 + </sect2> 5.288 + <sect2> 5.289 + <title><command role="hg-ext-mq">qprev</command>&emdash;print 5.290 + the name of the previous patch</title> 5.291 + 5.292 + <para>The <command role="hg-ext-mq">qprev</command> command 5.293 + prints the name of the patch in the <filename 5.294 + role="special">series</filename> file that comes before the 5.295 + topmost applied patch. This will become the topmost applied 5.296 + patch if you run <command 5.297 + role="hg-ext-mq">qpop</command>.</para> 5.298 + 5.299 + </sect2> 5.300 + <sect2 id="sec:mqref:cmd:qpush"> 5.301 + <title><command role="hg-ext-mq">qpush</command>&emdash;push 5.302 + patches onto the stack</title> 5.303 + 5.304 + <para>The <command role="hg-ext-mq">qpush</command> command adds 5.305 + patches onto the applied stack. By default, it adds only one 5.306 + patch.</para> 5.307 + 5.308 + <para>This command creates a new changeset to represent each 5.309 + applied patch, and updates the working directory to apply the 5.310 + effects of the patches.</para> 5.311 + 5.312 + <para>The default data used when creating a changeset are as 5.313 + follows:</para> 5.314 + <itemizedlist> 5.315 + <listitem><para>The commit date and time zone are the current 5.316 + date and time zone. Because these data are used to 5.317 + compute the identity of a changeset, this means that if 5.318 + you <command role="hg-ext-mq">qpop</command> a patch and 5.319 + <command role="hg-ext-mq">qpush</command> it again, the 5.320 + changeset that you push will have a different identity 5.321 + than the changeset you popped.</para> 5.322 + </listitem> 5.323 + <listitem><para>The author is the same as the default used by 5.324 + the <command role="hg-cmd">hg commit</command> 5.325 + command.</para> 5.326 + </listitem> 5.327 + <listitem><para>The commit message is any text from the patch 5.328 + file that comes before the first diff header. If there is 5.329 + no such text, a default commit message is used that 5.330 + identifies the name of the patch.</para> 5.331 + </listitem></itemizedlist> 5.332 + <para>If a patch contains a Mercurial patch header (XXX add 5.333 + link), the information in the patch header overrides these 5.334 + defaults.</para> 5.335 + 5.336 + <para>Options:</para> 5.337 + <itemizedlist> 5.338 + <listitem><para><option 5.339 + role="hg-ext-mq-cmd-qpush-opt">-a</option>: Push all 5.340 + unapplied patches from the <filename 5.341 + role="special">series</filename> file until there are 5.342 + none left to push.</para> 5.343 + </listitem> 5.344 + <listitem><para><option 5.345 + role="hg-ext-mq-cmd-qpush-opt">-l</option>: Add the name 5.346 + of the patch to the end of the commit message.</para> 5.347 + </listitem> 5.348 + <listitem><para><option 5.349 + role="hg-ext-mq-cmd-qpush-opt">-m</option>: If a patch 5.350 + fails to apply cleanly, use the entry for the patch in 5.351 + another saved queue to compute the parameters for a 5.352 + three-way merge, and perform a three-way merge using the 5.353 + normal Mercurial merge machinery. Use the resolution of 5.354 + the merge as the new patch content.</para> 5.355 + </listitem> 5.356 + <listitem><para><option 5.357 + role="hg-ext-mq-cmd-qpush-opt">-n</option>: Use the 5.358 + named queue if merging while pushing.</para> 5.359 + </listitem></itemizedlist> 5.360 + 5.361 + <para>The <command role="hg-ext-mq">qpush</command> command 5.362 + reads, but does not modify, the <filename 5.363 + role="special">series</filename> file. It appends one line 5.364 + to the <command role="hg-cmd">hg status</command> file for 5.365 + each patch that it pushes.</para> 5.366 + 5.367 + </sect2> 5.368 + <sect2> 5.369 + <title><command 5.370 + role="hg-ext-mq">qrefresh</command>&emdash;update the 5.371 + topmost applied patch</title> 5.372 + 5.373 + <para>The <command role="hg-ext-mq">qrefresh</command> command 5.374 + updates the topmost applied patch. It modifies the patch, 5.375 + removes the old changeset that represented the patch, and 5.376 + creates a new changeset to represent the modified 5.377 + patch.</para> 5.378 + 5.379 + <para>The <command role="hg-ext-mq">qrefresh</command> command 5.380 + looks for the following modifications:</para> 5.381 + <itemizedlist> 5.382 + <listitem><para>Changes to the commit message, i.e. the text 5.383 + before the first diff header in the patch file, are 5.384 + reflected in the new changeset that represents the 5.385 + patch.</para> 5.386 + </listitem> 5.387 + <listitem><para>Modifications to tracked files in the working 5.388 + directory are added to the patch.</para> 5.389 + </listitem> 5.390 + <listitem><para>Changes to the files tracked using <command 5.391 + role="hg-cmd">hg add</command>, <command 5.392 + role="hg-cmd">hg copy</command>, <command 5.393 + role="hg-cmd">hg remove</command>, or <command 5.394 + role="hg-cmd">hg rename</command>. Added files and copy 5.395 + and rename destinations are added to the patch, while 5.396 + removed files and rename sources are removed.</para> 5.397 + </listitem></itemizedlist> 5.398 + 5.399 + <para>Even if <command role="hg-ext-mq">qrefresh</command> 5.400 + detects no changes, it still recreates the changeset that 5.401 + represents the patch. This causes the identity of the 5.402 + changeset to differ from the previous changeset that 5.403 + identified the patch.</para> 5.404 + 5.405 + <para>Options:</para> 5.406 + <itemizedlist> 5.407 + <listitem><para><option 5.408 + role="hg-ext-mq-cmd-qrefresh-opt">-e</option>: Modify 5.409 + the commit and patch description, using the preferred text 5.410 + editor.</para> 5.411 + </listitem> 5.412 + <listitem><para><option 5.413 + role="hg-ext-mq-cmd-qrefresh-opt">-m</option>: Modify 5.414 + the commit message and patch description, using the given 5.415 + text.</para> 5.416 + </listitem> 5.417 + <listitem><para><option 5.418 + role="hg-ext-mq-cmd-qrefresh-opt">-l</option>: Modify 5.419 + the commit message and patch description, using text from 5.420 + the given file.</para> 5.421 + </listitem></itemizedlist> 5.422 + 5.423 + </sect2> 5.424 + <sect2> 5.425 + <title><command role="hg-ext-mq">qrename</command>&emdash;rename 5.426 + a patch</title> 5.427 + 5.428 + <para>The <command role="hg-ext-mq">qrename</command> command 5.429 + renames a patch, and changes the entry for the patch in the 5.430 + <filename role="special">series</filename> file.</para> 5.431 + 5.432 + <para>With a single argument, <command 5.433 + role="hg-ext-mq">qrename</command> renames the topmost 5.434 + applied patch. With two arguments, it renames its first 5.435 + argument to its second.</para> 5.436 + 5.437 + </sect2> 5.438 + <sect2> 5.439 + <title><command 5.440 + role="hg-ext-mq">qrestore</command>&emdash;restore saved 5.441 + queue state</title> 5.442 + 5.443 + <para>XXX No idea what this does.</para> 5.444 + 5.445 + </sect2> 5.446 + <sect2> 5.447 + <title><command role="hg-ext-mq">qsave</command>&emdash;save 5.448 + current queue state</title> 5.449 + 5.450 + <para>XXX Likewise.</para> 5.451 + 5.452 + </sect2> 5.453 + <sect2> 5.454 + <title><command role="hg-ext-mq">qseries</command>&emdash;print 5.455 + the entire patch series</title> 5.456 + 5.457 + <para>The <command role="hg-ext-mq">qseries</command> command 5.458 + prints the entire patch series from the <filename 5.459 + role="special">series</filename> file. It prints only patch 5.460 + names, not empty lines or comments. It prints in order from 5.461 + first to be applied to last.</para> 5.462 + 5.463 + </sect2> 5.464 + <sect2> 5.465 + <title><command role="hg-ext-mq">qtop</command>&emdash;print the 5.466 + name of the current patch</title> 5.467 + 5.468 + <para>The <command role="hg-ext-mq">qtop</command> prints the 5.469 + name of the topmost currently applied patch.</para> 5.470 + 5.471 + </sect2> 5.472 + <sect2> 5.473 + <title><command 5.474 + role="hg-ext-mq">qunapplied</command>&emdash;print patches 5.475 + not yet applied</title> 5.476 + 5.477 + <para>The <command role="hg-ext-mq">qunapplied</command> command 5.478 + prints the names of patches from the <filename 5.479 + role="special">series</filename> file that are not yet 5.480 + applied. It prints them in order from the next patch that 5.481 + will be pushed to the last.</para> 5.482 + 5.483 + </sect2> 5.484 + <sect2> 5.485 + <title><command role="hg-cmd">hg strip</command>&emdash;remove a 5.486 + revision and descendants</title> 5.487 + 5.488 + <para>The <command role="hg-cmd">hg strip</command> command 5.489 + removes a revision, and all of its descendants, from the 5.490 + repository. It undoes the effects of the removed revisions 5.491 + from the repository, and updates the working directory to the 5.492 + first parent of the removed revision.</para> 5.493 + 5.494 + <para>The <command role="hg-cmd">hg strip</command> command 5.495 + saves a backup of the removed changesets in a bundle, so that 5.496 + they can be reapplied if removed in error.</para> 5.497 + 5.498 + <para>Options:</para> 5.499 + <itemizedlist> 5.500 + <listitem><para><option role="hg-opt-strip">-b</option>: Save 5.501 + unrelated changesets that are intermixed with the stripped 5.502 + changesets in the backup bundle.</para> 5.503 + </listitem> 5.504 + <listitem><para><option role="hg-opt-strip">-f</option>: If a 5.505 + branch has multiple heads, remove all heads. XXX This 5.506 + should be renamed, and use <literal>-f</literal> to strip 5.507 + revs when there are pending changes.</para> 5.508 + </listitem> 5.509 + <listitem><para><option role="hg-opt-strip">-n</option>: Do 5.510 + not save a backup bundle.</para> 5.511 + </listitem></itemizedlist> 5.512 + 5.513 + </sect2> 5.514 + </sect1> 5.515 + <sect1> 5.516 + <title>MQ file reference</title> 5.517 + 5.518 + <sect2> 5.519 + <title>The <filename role="special">series</filename> 5.520 + file</title> 5.521 + 5.522 + <para>The <filename role="special">series</filename> file 5.523 + contains a list of the names of all patches that MQ can apply. 5.524 + It is represented as a list of names, with one name saved per 5.525 + line. Leading and trailing white space in each line are 5.526 + ignored.</para> 5.527 + 5.528 + <para>Lines may contain comments. A comment begins with the 5.529 + <quote><literal>#</literal></quote> character, and extends to 5.530 + the end of the line. Empty lines, and lines that contain only 5.531 + comments, are ignored.</para> 5.532 + 5.533 + <para>You will often need to edit the <filename 5.534 + role="special">series</filename> file by hand, hence the 5.535 + support for comments and empty lines noted above. For 5.536 + example, you can comment out a patch temporarily, and <command 5.537 + role="hg-ext-mq">qpush</command> will skip over that patch 5.538 + when applying patches. You can also change the order in which 5.539 + patches are applied by reordering their entries in the 5.540 + <filename role="special">series</filename> file.</para> 5.541 + 5.542 + <para>Placing the <filename role="special">series</filename> 5.543 + file under revision control is also supported; it is a good 5.544 + idea to place all of the patches that it refers to under 5.545 + revision control, as well. If you create a patch directory 5.546 + using the <option role="hg-ext-mq-cmd-qinit-opt">-c</option> 5.547 + option to <command role="hg-ext-mq">qinit</command>, this will 5.548 + be done for you automatically.</para> 5.549 + 5.550 + </sect2> 5.551 + <sect2> 5.552 + <title>The <filename role="special">status</filename> 5.553 + file</title> 5.554 + 5.555 + <para>The <filename role="special">status</filename> file 5.556 + contains the names and changeset hashes of all patches that MQ 5.557 + currently has applied. Unlike the <filename 5.558 + role="special">series</filename> file, this file is not 5.559 + intended for editing. You should not place this file under 5.560 + revision control, or modify it in any way. It is used by MQ 5.561 + strictly for internal book-keeping.</para> 5.562 + 5.563 + </sect2> 5.564 + </sect1> 5.565 +</appendix> 5.566 + 5.567 +<!-- 5.568 +local variables: 5.569 +sgml-parent-document: ("00book.xml" "book" "appendix") 5.570 +end: 5.571 +-->
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/en/appC-srcinstall.xml Wed Feb 18 00:22:09 2009 -0800 6.3 @@ -0,0 +1,65 @@ 6.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 6.5 + 6.6 +<appendix id="chap:srcinstall"> 6.7 + <title>Installing Mercurial from source</title> 6.8 + 6.9 + <sect1 id="sec:srcinstall:unixlike"> 6.10 + <title>On a Unix-like system</title> 6.11 + 6.12 + <para>If you are using a Unix-like system that has a sufficiently 6.13 + recent version of Python (2.3 or newer) available, it is easy to 6.14 + install Mercurial from source.</para> 6.15 + <orderedlist> 6.16 + <listitem><para>Download a recent source tarball from <ulink 6.17 + url="http://www.selenic.com/mercurial/download">http://www.selenic.com/mercurial/download</ulink>.</para> 6.18 + </listitem> 6.19 + <listitem><para>Unpack the tarball:</para> 6.20 + <programlisting>gzip -dc mercurial-MYVERSION.tar.gz | tar xf -</programlisting> 6.21 + </listitem> 6.22 + <listitem><para>Go into the source directory and run the 6.23 + installer script. This will build Mercurial and install it 6.24 + in your home directory.</para> 6.25 + <programlisting>cd mercurial-MYVERSION 6.26 +python setup.py install --force --home=$HOME</programlisting> 6.27 + </listitem> 6.28 + </orderedlist> 6.29 + <para>Once the install finishes, Mercurial will be in the 6.30 + <literal>bin</literal> subdirectory of your home directory. 6.31 + Don't forget to make sure that this directory is present in your 6.32 + shell's search path.</para> 6.33 + 6.34 + <para>You will probably need to set the <envar>PYTHONPATH</envar> 6.35 + environment variable so that the Mercurial executable can find 6.36 + the rest of the Mercurial packages. For example, on my laptop, 6.37 + I have set it to <literal>/home/bos/lib/python</literal>. The 6.38 + exact path that you will need to use depends on how Python was 6.39 + built for your system, but should be easy to figure out. If 6.40 + you're uncertain, look through the output of the installer 6.41 + script above, and see where the contents of the 6.42 + <literal>mercurial</literal> directory were installed to.</para> 6.43 + 6.44 + </sect1> 6.45 + <sect1> 6.46 + <title>On Windows</title> 6.47 + 6.48 + <para>Building and installing Mercurial on Windows requires a 6.49 + variety of tools, a fair amount of technical knowledge, and 6.50 + considerable patience. I very much <emphasis>do not 6.51 + recommend</emphasis> this route if you are a <quote>casual 6.52 + user</quote>. Unless you intend to hack on Mercurial, I 6.53 + strongly suggest that you use a binary package instead.</para> 6.54 + 6.55 + <para>If you are intent on building Mercurial from source on 6.56 + Windows, follow the <quote>hard way</quote> directions on the 6.57 + Mercurial wiki at <ulink 6.58 + url="http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall">http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall</ulink>, 6.59 + and expect the process to involve a lot of fiddly work.</para> 6.60 + 6.61 + </sect1> 6.62 +</appendix> 6.63 + 6.64 +<!-- 6.65 +local variables: 6.66 +sgml-parent-document: ("00book.xml" "book" "appendix") 6.67 +end: 6.68 +-->
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/en/appD-license.xml Wed Feb 18 00:22:09 2009 -0800 7.3 @@ -0,0 +1,178 @@ 7.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 7.5 + 7.6 +<appendix id="cha:opl"> 7.7 + <title>Open Publication License</title> 7.8 + 7.9 + <para>Version 1.0, 8 June 1999</para> 7.10 + 7.11 + <sect1> 7.12 + <title>Requirements on both unmodified and modified 7.13 + versions</title> 7.14 + 7.15 + <para>The Open Publication works may be reproduced and distributed 7.16 + in whole or in part, in any medium physical or electronic, 7.17 + provided that the terms of this license are adhered to, and that 7.18 + this license or an incorporation of it by reference (with any 7.19 + options elected by the author(s) and/or publisher) is displayed 7.20 + in the reproduction.</para> 7.21 + 7.22 + <para>Proper form for an incorporation by reference is as 7.23 + follows:</para> 7.24 + 7.25 + <blockquote> 7.26 + <para> Copyright (c) <emphasis>year</emphasis> by 7.27 + <emphasis>author's name or designee</emphasis>. This material 7.28 + may be distributed only subject to the terms and conditions 7.29 + set forth in the Open Publication License, 7.30 + v<emphasis>x.y</emphasis> or later (the latest version is 7.31 + presently available at <ulink 7.32 + url="http://www.opencontent.org/openpub/">http://www.opencontent.org/openpub/</ulink>).</para> 7.33 + </blockquote> 7.34 + 7.35 + <para>The reference must be immediately followed with any options 7.36 + elected by the author(s) and/or publisher of the document (see 7.37 + section <xref linkend="sec:opl:options"/>).</para> 7.38 + 7.39 + <para>Commercial redistribution of Open Publication-licensed 7.40 + material is permitted.</para> 7.41 + 7.42 + <para>Any publication in standard (paper) book form shall require 7.43 + the citation of the original publisher and author. The publisher 7.44 + and author's names shall appear on all outer surfaces of the 7.45 + book. On all outer surfaces of the book the original publisher's 7.46 + name shall be as large as the title of the work and cited as 7.47 + possessive with respect to the title.</para> 7.48 + 7.49 + </sect1> 7.50 + <sect1> 7.51 + <title>Copyright</title> 7.52 + 7.53 + <para>The copyright to each Open Publication is owned by its 7.54 + author(s) or designee.</para> 7.55 + 7.56 + </sect1> 7.57 + <sect1> 7.58 + <title>Scope of license</title> 7.59 + 7.60 + <para>The following license terms apply to all Open Publication 7.61 + works, unless otherwise explicitly stated in the 7.62 + document.</para> 7.63 + 7.64 + <para>Mere aggregation of Open Publication works or a portion of 7.65 + an Open Publication work with other works or programs on the 7.66 + same media shall not cause this license to apply to those other 7.67 + works. The aggregate work shall contain a notice specifying the 7.68 + inclusion of the Open Publication material and appropriate 7.69 + copyright notice.</para> 7.70 + 7.71 + <para><emphasis role="bold">Severability</emphasis>. If any part 7.72 + of this license is found to be unenforceable in any 7.73 + jurisdiction, the remaining portions of the license remain in 7.74 + force.</para> 7.75 + 7.76 + <para><emphasis role="bold">No warranty</emphasis>. Open 7.77 + Publication works are licensed and provided <quote>as is</quote> 7.78 + without warranty of any kind, express or implied, including, but 7.79 + not limited to, the implied warranties of merchantability and 7.80 + fitness for a particular purpose or a warranty of 7.81 + non-infringement.</para> 7.82 + 7.83 + </sect1> 7.84 + <sect1> 7.85 + <title>Requirements on modified works</title> 7.86 + 7.87 + <para>All modified versions of documents covered by this license, 7.88 + including translations, anthologies, compilations and partial 7.89 + documents, must meet the following requirements:</para> 7.90 + 7.91 + <orderedlist> 7.92 + <listitem><para>The modified version must be labeled as 7.93 + such.</para> 7.94 + </listitem> 7.95 + <listitem><para>The person making the modifications must be 7.96 + identified and the modifications dated.</para> 7.97 + </listitem> 7.98 + <listitem><para>Acknowledgement of the original author and 7.99 + publisher if applicable must be retained according to normal 7.100 + academic citation practices.</para> 7.101 + </listitem> 7.102 + <listitem><para>The location of the original unmodified document 7.103 + must be identified.</para> 7.104 + </listitem> 7.105 + <listitem><para>The original author's (or authors') name(s) may 7.106 + not be used to assert or imply endorsement of the resulting 7.107 + document without the original author's (or authors') 7.108 + permission.</para> 7.109 + </listitem></orderedlist> 7.110 + 7.111 + </sect1> 7.112 + <sect1> 7.113 + <title>Good-practice recommendations</title> 7.114 + 7.115 + <para>In addition to the requirements of this license, it is 7.116 + requested from and strongly recommended of redistributors 7.117 + that:</para> 7.118 + 7.119 + <orderedlist> 7.120 + <listitem><para>If you are distributing Open Publication works 7.121 + on hardcopy or CD-ROM, you provide email notification to the 7.122 + authors of your intent to redistribute at least thirty days 7.123 + before your manuscript or media freeze, to give the authors 7.124 + time to provide updated documents. This notification should 7.125 + describe modifications, if any, made to the document.</para> 7.126 + </listitem> 7.127 + <listitem><para>All substantive modifications (including 7.128 + deletions) be either clearly marked up in the document or 7.129 + else described in an attachment to the document.</para> 7.130 + </listitem> 7.131 + <listitem><para>Finally, while it is not mandatory under this 7.132 + license, it is considered good form to offer a free copy of 7.133 + any hardcopy and CD-ROM expression of an Open 7.134 + Publication-licensed work to its author(s).</para> 7.135 + </listitem></orderedlist> 7.136 + 7.137 + </sect1> 7.138 + <sect1 id="sec:opl:options"> 7.139 + <title>License options</title> 7.140 + 7.141 + <para>The author(s) and/or publisher of an Open 7.142 + Publication-licensed document may elect certain options by 7.143 + appending language to the reference to or copy of the license. 7.144 + These options are considered part of the license instance and 7.145 + must be included with the license (or its incorporation by 7.146 + reference) in derived works.</para> 7.147 + 7.148 + <orderedlist> 7.149 + <listitem><para>To prohibit distribution of substantively 7.150 + modified versions without the explicit permission of the 7.151 + author(s). <quote>Substantive modification</quote> is 7.152 + defined as a change to the semantic content of the document, 7.153 + and excludes mere changes in format or typographical 7.154 + corrections.</para> 7.155 + </listitem> 7.156 + <listitem><para> To accomplish this, add the phrase 7.157 + <quote>Distribution of substantively modified versions of 7.158 + this document is prohibited without the explicit 7.159 + permission of the copyright holder.</quote> to the license 7.160 + reference or copy.</para> 7.161 + </listitem> 7.162 + <listitem><para>To prohibit any publication of this work or 7.163 + derivative works in whole or in part in standard (paper) 7.164 + book form for commercial purposes is prohibited unless prior 7.165 + permission is obtained from the copyright holder.</para> 7.166 + </listitem> 7.167 + <listitem><para>To accomplish this, add the phrase 7.168 + <quote>Distribution of the work or derivative of the work in 7.169 + any standard (paper) book form is prohibited unless prior 7.170 + permission is obtained from the copyright holder.</quote> 7.171 + to the license reference or copy.</para> 7.172 + </listitem></orderedlist> 7.173 + 7.174 + </sect1> 7.175 +</appendix> 7.176 + 7.177 +<!-- 7.178 +local variables: 7.179 +sgml-parent-document: ("00book.xml" "book" "appendix") 7.180 +end: 7.181 +-->
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/en/ch00-preface.xml Wed Feb 18 00:22:09 2009 -0800 8.3 @@ -0,0 +1,80 @@ 8.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 8.5 + 8.6 +<preface id="chap:preface"> 8.7 + <title>Preface</title> 8.8 + 8.9 + <para>Distributed revision control is a relatively new territory, 8.10 + and has thus far grown due to people's willingness to strike out 8.11 + into ill-charted territory.</para> 8.12 + 8.13 + <para>I am writing a book about distributed revision control because 8.14 + I believe that it is an important subject that deserves a field 8.15 + guide. I chose to write about Mercurial because it is the easiest 8.16 + tool to learn the terrain with, and yet it scales to the demands 8.17 + of real, challenging environments where many other revision 8.18 + control tools fail.</para> 8.19 + 8.20 + <sect1> 8.21 + <title>This book is a work in progress</title> 8.22 + 8.23 + <para>I am releasing this book while I am still writing it, in the 8.24 + hope that it will prove useful to others. I also hope that 8.25 + readers will contribute as they see fit.</para> 8.26 + 8.27 + </sect1> 8.28 + <sect1> 8.29 + <title>About the examples in this book</title> 8.30 + 8.31 + <para>This book takes an unusual approach to code samples. Every 8.32 + example is <quote>live</quote>---each one is actually the result 8.33 + of a shell script that executes the Mercurial commands you see. 8.34 + Every time an image of the book is built from its sources, all 8.35 + the example scripts are automatically run, and their current 8.36 + results compared against their expected results.</para> 8.37 + 8.38 + <para>The advantage of this approach is that the examples are 8.39 + always accurate; they describe <emphasis>exactly</emphasis> the 8.40 + behaviour of the version of Mercurial that's mentioned at the 8.41 + front of the book. If I update the version of Mercurial that 8.42 + I'm documenting, and the output of some command changes, the 8.43 + build fails.</para> 8.44 + 8.45 + <para>There is a small disadvantage to this approach, which is 8.46 + that the dates and times you'll see in examples tend to be 8.47 + <quote>squashed</quote> together in a way that they wouldn't be 8.48 + if the same commands were being typed by a human. Where a human 8.49 + can issue no more than one command every few seconds, with any 8.50 + resulting timestamps correspondingly spread out, my automated 8.51 + example scripts run many commands in one second.</para> 8.52 + 8.53 + <para>As an instance of this, several consecutive commits in an 8.54 + example can show up as having occurred during the same second. 8.55 + You can see this occur in the <literal 8.56 + role="hg-ext">bisect</literal> example in section <xref 8.57 + id="sec:undo:bisect"/>, for instance.</para> 8.58 + 8.59 + <para>So when you're reading examples, don't place too much weight 8.60 + on the dates or times you see in the output of commands. But 8.61 + <emphasis>do</emphasis> be confident that the behaviour you're 8.62 + seeing is consistent and reproducible.</para> 8.63 + 8.64 + </sect1> 8.65 + <sect1> 8.66 + <title>Colophon---this book is Free</title> 8.67 + 8.68 + <para>This book is licensed under the Open Publication License, 8.69 + and is produced entirely using Free Software tools. It is 8.70 + typeset with \LaTeX{}; illustrations are drawn and rendered with 8.71 + <ulink url="http://www.inkscape.org/">Inkscape</ulink>.</para> 8.72 + 8.73 + <para>The complete source code for this book is published as a 8.74 + Mercurial repository, at <ulink 8.75 + url="http://hg.serpentine.com/mercurial/book">http://hg.serpentine.com/mercurial/book</ulink>.</para> 8.76 + 8.77 + </sect1> 8.78 +</preface> 8.79 +<!-- 8.80 +local variables: 8.81 +sgml-parent-document: ("00book.xml" "book" "preface") 8.82 +end: 8.83 +-->
9.1 --- a/en/ch02-tour-basic.xml Mon Feb 09 23:25:40 2009 -0800 9.2 +++ b/en/ch02-tour-basic.xml Wed Feb 18 00:22:09 2009 -0800 9.3 @@ -1,12 +1,10 @@ 9.4 <!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 9.5 9.6 -<chapter> 9.7 +<chapter id="chap:tour-basic"> 9.8 <title>A tour of Mercurial: the basics</title> 9.9 - <para>\label{chap:tour-basic}</para> 9.10 - 9.11 - <sect1> 9.12 + 9.13 + <sect1 id="sec:tour:install"> 9.14 <title>Installing Mercurial on your system</title> 9.15 - <para>\label{sec:tour:install}</para> 9.16 9.17 <para>Prebuilt binary packages of Mercurial are available for 9.18 every popular operating system. These make it easy to start 9.19 @@ -65,10 +63,10 @@ 9.20 <para>Lee Cantey publishes an installer of Mercurial for Mac OS 9.21 X at <ulink 9.22 url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>. 9.23 - This package works on both Intel- and Power-based Macs. 9.24 - Before you can use it, you must install a compatible version 9.25 - of Universal MacPython <citation>web:macpython</citation>. 9.26 - This is easy to do; simply follow the instructions on Lee's 9.27 + This package works on both Intel- and Power-based Macs. Before 9.28 + you can use it, you must install a compatible version of 9.29 + Universal MacPython <citation>web:macpython</citation>. This 9.30 + is easy to do; simply follow the instructions on Lee's 9.31 site.</para> 9.32 9.33 <para>It's also possible to install Mercurial using Fink or 9.34 @@ -104,26 +102,31 @@ 9.35 version</command> command to find out whether Mercurial is 9.36 actually installed properly. The actual version information 9.37 that it prints isn't so important; it's whether it prints 9.38 - anything at all that we care about. <!-- 9.39 - &interaction.tour.version; --></para> 9.40 + anything at all that we care about.</para> 9.41 + 9.42 + <!-- &interaction.tour.version; --> 9.43 9.44 <sect2> 9.45 <title>Built-in help</title> 9.46 9.47 <para>Mercurial provides a built-in help system. This is 9.48 - invaluable for those times when you find yourself stuck trying 9.49 - to remember how to run a command. If you are completely 9.50 - stuck, simply run <command role="hg-cmd">hg help</command>; it 9.51 - will print a brief list of commands, along with a description 9.52 - of what each does. If you ask for help on a specific command 9.53 - (as below), it prints more detailed information. <!-- 9.54 - &interaction.tour.help; --> For a more impressive level of 9.55 - detail (which you won't usually need) run <command 9.56 - role="hg-cmd">hg help <option 9.57 - role="hg-opt-global">-v</option></command>. The <option 9.58 - role="hg-opt-global">-v</option> option is short for <option 9.59 - role="hg-opt-global">--verbose</option>, and tells Mercurial 9.60 - to print more information than it usually would.</para> 9.61 + invaluable for those times when you find yourself stuck 9.62 + trying to remember how to run a command. If you are 9.63 + completely stuck, simply run <command role="hg-cmd">hg 9.64 + help</command>; it will print a brief list of commands, 9.65 + along with a description of what each does. If you ask for 9.66 + help on a specific command (as below), it prints more 9.67 + detailed information.</para> 9.68 + 9.69 + <!-- &interaction.tour.help; --> 9.70 + 9.71 + <para>For a more impressive level of detail (which you won't 9.72 + usually need) run <command role="hg-cmd">hg help <option 9.73 + role="hg-opt-global">-v</option></command>. The <option 9.74 + role="hg-opt-global">-v</option> option is short for 9.75 + <option role="hg-opt-global">--verbose</option>, and tells 9.76 + Mercurial to print more information than it usually 9.77 + would.</para> 9.78 9.79 </sect2> 9.80 </sect1> 9.81 @@ -150,13 +153,18 @@ 9.82 command to make a copy of a repository, it's best to use a 9.83 built-in command that Mercurial provides. This command is 9.84 called <command role="hg-cmd">hg clone</command>, because it 9.85 - creates an identical copy of an existing repository. <!-- 9.86 - &interaction.tour.clone; --> If our clone succeeded, we should 9.87 - now have a local directory called <filename 9.88 - class="directory">hello</filename>. This directory will 9.89 - contain some files. <!-- &interaction.tour.ls; --> These files 9.90 - have the same contents and history in our repository as they 9.91 - do in the repository we cloned.</para> 9.92 + creates an identical copy of an existing repository.</para> 9.93 + 9.94 + <!-- &interaction.tour.clone; --> 9.95 + 9.96 + <para>If our clone succeeded, we should now have a local 9.97 + directory called <filename class="directory">hello</filename>. 9.98 + This directory will contain some files.</para> 9.99 + 9.100 + <!-- &interaction.tour.ls; --> 9.101 + 9.102 + <para>These files have the same contents and history in our 9.103 + repository as they do in the repository we cloned.</para> 9.104 9.105 <para>Every Mercurial repository is complete, self-contained, 9.106 and independent. It contains its own private copy of a 9.107 @@ -176,8 +184,9 @@ 9.108 <para>When we take a more detailed look inside a repository, we 9.109 can see that it contains a directory named <filename 9.110 class="directory">.hg</filename>. This is where Mercurial 9.111 - keeps all of its metadata for the repository. <!-- 9.112 - &interaction.tour.ls-a; --></para> 9.113 + keeps all of its metadata for the repository.</para> 9.114 + 9.115 + <!-- &interaction.tour.ls-a; --> 9.116 9.117 <para>The contents of the <filename 9.118 class="directory">.hg</filename> directory and its 9.119 @@ -205,10 +214,13 @@ 9.120 <para>One of the first things we might want to do with a new, 9.121 unfamiliar repository is understand its history. The <command 9.122 role="hg-cmd">hg log</command> command gives us a view of 9.123 - history. <!-- &interaction.tour.log; --> By default, this 9.124 - command prints a brief paragraph of output for each change to 9.125 - the project that was recorded. In Mercurial terminology, we 9.126 - call each of these recorded events a 9.127 + history.</para> 9.128 + 9.129 + <!-- &interaction.tour.log; --> 9.130 + 9.131 + <para>By default, this command prints a brief paragraph of output 9.132 + for each change to the project that was recorded. In Mercurial 9.133 + terminology, we call each of these recorded events a 9.134 <emphasis>changeset</emphasis>, because it can contain a record 9.135 of changes to several files.</para> 9.136 9.137 @@ -310,18 +322,22 @@ 9.138 role="hg-opt-log">-r</option> (or <option 9.139 role="hg-opt-log">--rev</option>) option. You can use 9.140 either a revision number or a long-form changeset identifier, 9.141 - and you can provide as many revisions as you want. <!-- 9.142 - &interaction.tour.log-r; --></para> 9.143 + and you can provide as many revisions as you want.</para> 9.144 + 9.145 + <!-- &interaction.tour.log-r; --> 9.146 9.147 <para>If you want to see the history of several revisions 9.148 without having to list each one, you can use <emphasis>range 9.149 notation</emphasis>; this lets you express the idea <quote>I 9.150 - want all revisions between $a$ and $b$, inclusive</quote>. 9.151 - <!-- &interaction.tour.log.range; --> Mercurial also honours 9.152 - the order in which you specify revisions, so <command 9.153 - role="hg-cmd">hg log -r 2:4</command> prints $2,3,4$ while 9.154 - <command role="hg-cmd">hg log -r 4:2</command> prints 9.155 - $4,3,2$.</para> 9.156 + want all revisions between <literal>abc</literal> and 9.157 + <literal>def</literal>, inclusive</quote>.</para> 9.158 + 9.159 + <!-- &interaction.tour.log.range; --> 9.160 + 9.161 + <para>Mercurial also honours the order in which you specify 9.162 + revisions, so <command role="hg-cmd">hg log -r 2:4</command> 9.163 + prints 2, 3, and 4. while <command role="hg-cmd">hg log -r 9.164 + 4:2</command> prints 4, 3, and 2.</para> 9.165 9.166 </sect2> 9.167 <sect2> 9.168 @@ -335,7 +351,9 @@ 9.169 looking for. The <command role="hg-cmd">hg log</command> 9.170 command's <option role="hg-opt-global">-v</option> (or <option 9.171 role="hg-opt-global">--verbose</option>) option gives you 9.172 - this extra detail. <!-- &interaction.tour.log-v; --></para> 9.173 + this extra detail.</para> 9.174 + 9.175 + <!-- &interaction.tour.log-v; --> 9.176 9.177 <para>If you want to see both the description and content of a 9.178 change, add the <option role="hg-opt-log">-p</option> (or 9.179 @@ -343,7 +361,9 @@ 9.180 displays the content of a change as a <emphasis>unified 9.181 diff</emphasis> (if you've never seen a unified diff before, 9.182 see section <xref linkend="sec:mq:patch"/> for an 9.183 - overview). <!-- &interaction.tour.log-vp; --></para> 9.184 + overview).</para> 9.185 + 9.186 + <!-- &interaction.tour.log-vp; --> 9.187 9.188 </sect2> 9.189 </sect1> 9.190 @@ -402,16 +422,18 @@ 9.191 the remote repository. Since we already have a copy of it 9.192 locally, we can just clone that instead. This is much faster 9.193 than cloning over the network, and cloning a local repository 9.194 - uses less disk space in most cases, too. <!-- 9.195 - &interaction.tour.reclone; --> As an aside, it's often good 9.196 - practice to keep a <quote>pristine</quote> copy of a remote 9.197 - repository around, which you can then make temporary clones of 9.198 - to create sandboxes for each task you want to work on. This 9.199 - lets you work on multiple tasks in parallel, each isolated from 9.200 - the others until it's complete and you're ready to integrate it 9.201 - back. Because local clones are so cheap, there's almost no 9.202 - overhead to cloning and destroying repositories whenever you 9.203 - want.</para> 9.204 + uses less disk space in most cases, too.</para> 9.205 + 9.206 + <!-- &interaction.tour.reclone; --> 9.207 + 9.208 + <para>As an aside, it's often good practice to keep a 9.209 + <quote>pristine</quote> copy of a remote repository around, 9.210 + which you can then make temporary clones of to create sandboxes 9.211 + for each task you want to work on. This lets you work on 9.212 + multiple tasks in parallel, each isolated from the others until 9.213 + it's complete and you're ready to integrate it back. Because 9.214 + local clones are so cheap, there's almost no overhead to cloning 9.215 + and destroying repositories whenever you want.</para> 9.216 9.217 <para>In our <filename class="directory">my-hello</filename> 9.218 repository, we have a file <filename>hello.c</filename> that 9.219 @@ -422,13 +444,18 @@ 9.220 to write a scripted example this way. Since you're not under 9.221 the same constraint, you probably won't want to use 9.222 <command>sed</command>; simply use your preferred text editor to 9.223 - do the same thing.) <!-- &interaction.tour.sed; --></para> 9.224 + do the same thing.)</para> 9.225 + 9.226 + <!-- &interaction.tour.sed; --> 9.227 9.228 <para>Mercurial's <command role="hg-cmd">hg status</command> 9.229 command will tell us what Mercurial knows about the files in the 9.230 - repository. <!-- &interaction.tour.status; --> The <command 9.231 - role="hg-cmd">hg status</command> command prints no output for 9.232 - some files, but a line starting with 9.233 + repository.</para> 9.234 + 9.235 + <!-- &interaction.tour.status; --> 9.236 + 9.237 + <para>The <command role="hg-cmd">hg status</command> command 9.238 + prints no output for some files, but a line starting with 9.239 <quote><literal>M</literal></quote> for 9.240 <filename>hello.c</filename>. Unless you tell it to, <command 9.241 role="hg-cmd">hg status</command> will not print any output 9.242 @@ -446,7 +473,9 @@ 9.243 <filename>hello.c</filename>, but we might prefer to know 9.244 exactly <emphasis>what</emphasis> changes we've made to it. To 9.245 do this, we use the <command role="hg-cmd">hg diff</command> 9.246 - command. <!-- &interaction.tour.diff; --></para> 9.247 + command.</para> 9.248 + 9.249 + <!-- &interaction.tour.diff; --> 9.250 9.251 </sect1> 9.252 <sect1> 9.253 @@ -701,67 +730,70 @@ 9.254 <sect2> 9.255 <title>Updating the working directory</title> 9.256 9.257 - <para>We have so far glossed over the relationship 9.258 - between a repository and its working directory. The 9.259 - <command role="hg-cmd">hg pull</command> command that we ran 9.260 - in section <xref linkend="sec:tour:pull"/> brought changes into 9.261 - the 9.262 - repository, but if we check, there's no sign of those 9.263 - changes in the working directory. This is because <command 9.264 - role="hg-cmd">hg pull</command> does not (by default) 9.265 - touch the working directory. Instead, we use the <command 9.266 - role="hg-cmd">hg update</command> command to do this. <!-- 9.267 - &interaction.tour.update; --></para> 9.268 - <para>It might seem a bit strange that <command 9.269 - role="hg-cmd">hg pull</command> doesn't update the working 9.270 - directory automatically. There's actually a good reason for 9.271 - this: you can use <command role="hg-cmd">hg update</command> 9.272 - to update the working directory to the state it was in at 9.273 - <emphasis>any revision</emphasis> in the history of the 9.274 - repository. If you had the working directory updated to an 9.275 - old revision---to hunt down the origin of a bug, say---and 9.276 - ran a <command role="hg-cmd">hg pull</command> which 9.277 - automatically updated the working directory to a new 9.278 - revision, you might not be terribly happy.</para> 9.279 - <para>However, since pull-then-update is such a common 9.280 - thing to do, Mercurial lets you combine the two by passing 9.281 - the <option role="hg-opt-pull">-u</option> option to 9.282 - <command role="hg-cmd">hg 9.283 - pull</command>.</para> 9.284 + <para>We have so far glossed over the relationship between a 9.285 + repository and its working directory. The <command 9.286 + role="hg-cmd">hg pull</command> command that we ran in 9.287 + section <xref linkend="sec:tour:pull"/> brought changes 9.288 + into the repository, but if we check, there's no sign of those 9.289 + changes in the working directory. This is because <command 9.290 + role="hg-cmd">hg pull</command> does not (by default) touch 9.291 + the working directory. Instead, we use the <command 9.292 + role="hg-cmd">hg update</command> command to do this.</para> 9.293 + 9.294 + <!-- &interaction.tour.update; --> 9.295 + 9.296 + <para>It might seem a bit strange that <command role="hg-cmd">hg 9.297 + pull</command> doesn't update the working directory 9.298 + automatically. There's actually a good reason for this: you 9.299 + can use <command role="hg-cmd">hg update</command> to update 9.300 + the working directory to the state it was in at <emphasis>any 9.301 + revision</emphasis> in the history of the repository. If 9.302 + you had the working directory updated to an old revision---to 9.303 + hunt down the origin of a bug, say---and ran a <command 9.304 + role="hg-cmd">hg pull</command> which automatically updated 9.305 + the working directory to a new revision, you might not be 9.306 + terribly happy.</para> 9.307 + <para>However, since pull-then-update is such a common thing to 9.308 + do, Mercurial lets you combine the two by passing the <option 9.309 + role="hg-opt-pull">-u</option> option to <command 9.310 + role="hg-cmd">hg pull</command>.</para> 9.311 9.312 <para>If you look back at the output of <command 9.313 - role="hg-cmd">hg pull</command> in section <xref 9.314 + role="hg-cmd">hg pull</command> in section <xref 9.315 linkend="sec:tour:pull"/> when we ran it without <option 9.316 - role="hg-opt-pull">-u</option>, you can see that it 9.317 - printed a helpful reminder that we'd have to take an 9.318 - explicit step to update the working 9.319 - directory:</para> 9.320 + role="hg-opt-pull">-u</option>, you can see that it printed 9.321 + a helpful reminder that we'd have to take an explicit step to 9.322 + update the working directory:</para> 9.323 9.324 <!-- &interaction.xxx.fixme; --> 9.325 9.326 - <para>To find out what revision the working directory 9.327 - is at, use the <command role="hg-cmd">hg parents</command> 9.328 - command.</para> 9.329 + <para>To find out what revision the working directory is at, use 9.330 + the <command role="hg-cmd">hg parents</command> 9.331 + command.</para> 9.332 9.333 <!-- &interaction.tour.parents; --> 9.334 9.335 - <para>If you look 9.336 - back at figure <xref linkend="fig:tour-basic:history"/>, you'll 9.337 - see arrows connecting each changeset. The node that the 9.338 - arrow leads <emphasis>from</emphasis> in each case is a 9.339 - parent, and the node that the arrow leads 9.340 - <emphasis>to</emphasis> is its child. The working directory 9.341 - has a parent in just the same way; this is the changeset 9.342 - that the working directory currently 9.343 - contains.</para> 9.344 - <para>To update the working directory to a particular 9.345 - revision, give a revision number or changeset ID to the 9.346 - <command role="hg-cmd">hg update</command> command. <!-- 9.347 - &interaction.tour.older; --> If you omit an explicit 9.348 - revision, <command role="hg-cmd">hg update</command> will 9.349 - update to the tip revision, as shown by the second call to 9.350 - <command role="hg-cmd">hg update</command> in the example 9.351 - above.</para> 9.352 + <para>If you look back at figure <xref 9.353 + linkend="fig:tour-basic:history"/>, 9.354 + you'll see arrows connecting each changeset. The node that 9.355 + the arrow leads <emphasis>from</emphasis> in each case is a 9.356 + parent, and the node that the arrow leads 9.357 + <emphasis>to</emphasis> is its child. The working directory 9.358 + has a parent in just the same way; this is the changeset that 9.359 + the working directory currently contains.</para> 9.360 + 9.361 + <para>To update the working directory to a particular revision, 9.362 + 9.363 + give a revision number or changeset ID to the <command 9.364 + role="hg-cmd">hg update</command> command.</para> 9.365 + 9.366 + <!-- &interaction.tour.older; --> 9.367 + 9.368 + <para>If you omit an explicit revision, <command 9.369 + role="hg-cmd">hg update</command> will update to the tip 9.370 + revision, as shown by the second call to <command 9.371 + role="hg-cmd">hg update</command> in the example 9.372 + above.</para> 9.373 </sect2> 9.374 9.375 <sect2>
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/en/ch03-tour-merge.xml Wed Feb 18 00:22:09 2009 -0800 10.3 @@ -0,0 +1,394 @@ 10.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 10.5 + 10.6 +<chapter id="chap:tour-merge"> 10.7 + <title>A tour of Mercurial: merging work</title> 10.8 + 10.9 + <para>We've now covered cloning a repository, making changes in a 10.10 + repository, and pulling or pushing changes from one repository 10.11 + into another. Our next step is <emphasis>merging</emphasis> 10.12 + changes from separate repositories.</para> 10.13 + 10.14 + <sect1> 10.15 + <title>Merging streams of work</title> 10.16 + 10.17 + <para>Merging is a fundamental part of working with a distributed 10.18 + revision control tool.</para> 10.19 + <itemizedlist> 10.20 + <listitem><para>Alice and Bob each have a personal copy of a 10.21 + repository for a project they're collaborating on. Alice 10.22 + fixes a bug in her repository; Bob adds a new feature in 10.23 + his. They want the shared repository to contain both the 10.24 + bug fix and the new feature.</para> 10.25 + </listitem> 10.26 + <listitem><para>I frequently work on several different tasks for 10.27 + a single project at once, each safely isolated in its own 10.28 + repository. Working this way means that I often need to 10.29 + merge one piece of my own work with another.</para> 10.30 + </listitem></itemizedlist> 10.31 + 10.32 + <para>Because merging is such a common thing to need to do, 10.33 + Mercurial makes it easy. Let's walk through the process. We'll 10.34 + begin by cloning yet another repository (see how often they 10.35 + spring up?) and making a change in it.</para> 10.36 + 10.37 + <!-- &interaction.tour.merge.clone; --> 10.38 + 10.39 + <para>We should now have two copies of 10.40 + <filename>hello.c</filename> with different contents. The 10.41 + histories of the two repositories have also diverged, as 10.42 + illustrated in figure <xref 10.43 + linkend="fig:tour-merge:sep-repos"/>.</para> 10.44 + 10.45 + <!-- &interaction.tour.merge.cat; --> 10.46 + 10.47 + <informalfigure id="fig:tour-merge:sep-repos"> 10.48 + <mediaobject> 10.49 + <imageobject><imagedata fileref="tour-merge-sep-repos"/></imageobject> 10.50 + <textobject><phrase>XXX add text</phrase></textobject> 10.51 + <caption><para>Divergent recent histories of the <filename 10.52 + class="directory">my-hello</filename> and <filename 10.53 + class="directory">my-new-hello</filename> 10.54 + repositories</para></caption> 10.55 + </mediaobject> 10.56 + </informalfigure> 10.57 + 10.58 + <para>We already know that pulling changes from our <filename 10.59 + class="directory">my-hello</filename> repository will have no 10.60 + effect on the working directory.</para> 10.61 + 10.62 + <!-- &interaction.tour.merge.pull; --> 10.63 + 10.64 + <para>However, the <command role="hg-cmd">hg pull</command> 10.65 + command says something about <quote>heads</quote>.</para> 10.66 + 10.67 + <sect2> 10.68 + <title>Head changesets</title> 10.69 + 10.70 + <para>A head is a change that has no descendants, or children, 10.71 + as they're also known. The tip revision is thus a head, 10.72 + because the newest revision in a repository doesn't have any 10.73 + children, but a repository can contain more than one 10.74 + head.</para> 10.75 + 10.76 + <informalfigure id="fig:tour-merge:pull"> 10.77 + <mediaobject><imageobject><imagedata 10.78 + fileref="tour-merge-pull"/></imageobject><textobject><phrase>XXX 10.79 + add text</phrase></textobject> 10.80 + <caption><para>Repository contents after pulling from 10.81 + <filename class="directory">my-hello</filename> into 10.82 + <filename 10.83 + class="directory">my-new-hello</filename></para></caption> 10.84 + </mediaobject> 10.85 + </informalfigure> 10.86 + 10.87 + <para>In figure <xref linkend="fig:tour-merge:pull"/>, you can 10.88 + see the effect of the pull from <filename 10.89 + class="directory">my-hello</filename> into <filename 10.90 + class="directory">my-new-hello</filename>. The history that 10.91 + was already present in <filename 10.92 + class="directory">my-new-hello</filename> is untouched, but 10.93 + a new revision has been added. By referring to figure <xref 10.94 + linkend="fig:tour-merge:sep-repos"/>, we can see that the 10.95 + <emphasis>changeset ID</emphasis> remains the same in the new 10.96 + repository, but the <emphasis>revision number</emphasis> has 10.97 + changed. (This, incidentally, is a fine example of why it's 10.98 + not safe to use revision numbers when discussing changesets.) 10.99 + We can view the heads in a repository using the <command 10.100 + role="hg-cmd">hg heads</command> command.</para> 10.101 + 10.102 + <!-- &interaction.tour.merge.heads; --> 10.103 + 10.104 + </sect2> 10.105 + <sect2> 10.106 + <title>Performing the merge</title> 10.107 + 10.108 + <para>What happens if we try to use the normal <command 10.109 + role="hg-cmd">hg update</command> command to update to the 10.110 + new tip?</para> 10.111 + 10.112 + <!-- &interaction.tour.merge.update; --> 10.113 + 10.114 + <para>Mercurial is telling us that the <command role="hg-cmd">hg 10.115 + update</command> command won't do a merge; it won't update 10.116 + the working directory when it thinks we might be wanting to do 10.117 + a merge, unless we force it to do so. Instead, we use the 10.118 + <command role="hg-cmd">hg merge</command> command to merge the 10.119 + two heads.</para> 10.120 + 10.121 + <!-- &interaction.tour.merge.merge; --> 10.122 + 10.123 + <informalfigure id="fig:tour-merge:merge"> 10.124 + 10.125 + <mediaobject><imageobject><imagedata 10.126 + fileref="tour-merge-merge"/></imageobject><textobject><phrase>XXX 10.127 + add text</phrase></textobject> 10.128 + <caption><para>Working directory and repository during 10.129 + merge, and following commit</para></caption> 10.130 + </mediaobject> 10.131 + </informalfigure> 10.132 + 10.133 + <para>This updates the working directory so that it contains 10.134 + changes from <emphasis>both</emphasis> heads, which is 10.135 + reflected in both the output of <command role="hg-cmd">hg 10.136 + parents</command> and the contents of 10.137 + <filename>hello.c</filename>.</para> 10.138 + 10.139 + <!-- &interaction.tour.merge.parents; --> 10.140 + 10.141 + </sect2> 10.142 + <sect2> 10.143 + <title>Committing the results of the merge</title> 10.144 + 10.145 + <para>Whenever we've done a merge, <command role="hg-cmd">hg 10.146 + parents</command> will display two parents until we <command 10.147 + role="hg-cmd">hg commit</command> the results of the 10.148 + merge.</para> 10.149 + 10.150 + <!-- &interaction.tour.merge.commit; --> 10.151 + 10.152 + <para>We now have a new tip revision; notice that it has 10.153 + <emphasis>both</emphasis> of our former heads as its parents. 10.154 + These are the same revisions that were previously displayed by 10.155 + <command role="hg-cmd">hg parents</command>.</para> 10.156 + 10.157 + <!-- &interaction.tour.merge.tip; --> 10.158 + 10.159 + <para>In figure <xref 10.160 + linkend="fig:tour-merge:merge"/>, you can see a 10.161 + representation of what happens to the working directory during 10.162 + the merge, and how this affects the repository when the commit 10.163 + happens. During the merge, the working directory has two 10.164 + parent changesets, and these become the parents of the new 10.165 + changeset.</para> 10.166 + 10.167 + </sect2> 10.168 + </sect1> 10.169 + <sect1> 10.170 + <title>Merging conflicting changes</title> 10.171 + 10.172 + <para>Most merges are simple affairs, but sometimes you'll find 10.173 + yourself merging changes where each modifies the same portions 10.174 + of the same files. Unless both modifications are identical, 10.175 + this results in a <emphasis>conflict</emphasis>, where you have 10.176 + to decide how to reconcile the different changes into something 10.177 + coherent.</para> 10.178 + 10.179 + <informalfigure> 10.180 + 10.181 + <mediaobject id="fig:tour-merge:conflict"> 10.182 + <imageobject><imagedata fileref="tour-merge-conflict"/></imageobject> 10.183 + <textobject><phrase>XXX add text</phrase></textobject> 10.184 + <caption><para>Conflicting changes to a 10.185 + document</para></caption> </mediaobject> 10.186 + </informalfigure> 10.187 + 10.188 + <para>Figure <xref linkend="fig:tour-merge:conflict"/> illustrates 10.189 + an instance of two conflicting changes to a document. We 10.190 + started with a single version of the file; then we made some 10.191 + changes; while someone else made different changes to the same 10.192 + text. Our task in resolving the conflicting changes is to 10.193 + decide what the file should look like.</para> 10.194 + 10.195 + <para>Mercurial doesn't have a built-in facility for handling 10.196 + conflicts. Instead, it runs an external program called 10.197 + <command>hgmerge</command>. This is a shell script that is 10.198 + bundled with Mercurial; you can change it to behave however you 10.199 + please. What it does by default is try to find one of several 10.200 + different merging tools that are likely to be installed on your 10.201 + system. It first tries a few fully automatic merging tools; if 10.202 + these don't succeed (because the resolution process requires 10.203 + human guidance) or aren't present, the script tries a few 10.204 + different graphical merging tools.</para> 10.205 + 10.206 + <para>It's also possible to get Mercurial to run another program 10.207 + or script instead of <command>hgmerge</command>, by setting the 10.208 + <envar>HGMERGE</envar> environment variable to the name of your 10.209 + preferred program.</para> 10.210 + 10.211 + <sect2> 10.212 + <title>Using a graphical merge tool</title> 10.213 + 10.214 + <para>My preferred graphical merge tool is 10.215 + <command>kdiff3</command>, which I'll use to describe the 10.216 + features that are common to graphical file merging tools. You 10.217 + can see a screenshot of <command>kdiff3</command> in action in 10.218 + figure <xref linkend="fig:tour-merge:kdiff3"/>. The kind of 10.219 + merge it is performing is called a <emphasis>three-way 10.220 + merge</emphasis>, because there are three different versions 10.221 + of the file of interest to us. The tool thus splits the upper 10.222 + portion of the window into three panes:</para> 10.223 + <itemizedlist> 10.224 + <listitem><para>At the left is the <emphasis>base</emphasis> 10.225 + version of the file, i.e. the most recent version from 10.226 + which the two versions we're trying to merge are 10.227 + descended.</para> 10.228 + </listitem> 10.229 + <listitem><para>In the middle is <quote>our</quote> version of 10.230 + the file, with the contents that we modified.</para> 10.231 + </listitem> 10.232 + <listitem><para>On the right is <quote>their</quote> version 10.233 + of the file, the one that from the changeset that we're 10.234 + trying to merge with.</para> 10.235 + </listitem></itemizedlist> 10.236 + <para>In the pane below these is the current 10.237 + <emphasis>result</emphasis> of the merge. Our task is to 10.238 + replace all of the red text, which indicates unresolved 10.239 + conflicts, with some sensible merger of the 10.240 + <quote>ours</quote> and <quote>theirs</quote> versions of the 10.241 + file.</para> 10.242 + 10.243 + <para>All four of these panes are <emphasis>locked 10.244 + together</emphasis>; if we scroll vertically or horizontally 10.245 + in any of them, the others are updated to display the 10.246 + corresponding sections of their respective files.</para> 10.247 + 10.248 + <informalfigure id="fig:tour-merge:kdiff3"> 10.249 + <mediaobject><imageobject><imagedata 10.250 + fileref="kdiff3"/></imageobject><textobject><phrase>XXX 10.251 + add text</phrase></textobject> 10.252 + <caption><para>Using <command>kdiff3</command> to merge 10.253 + versions of a file</para></caption> 10.254 + </mediaobject> 10.255 + </informalfigure> 10.256 + 10.257 + <para>For each conflicting portion of the file, we can choose to 10.258 + resolve the conflict using some combination of text from the 10.259 + base version, ours, or theirs. We can also manually edit the 10.260 + merged file at any time, in case we need to make further 10.261 + modifications.</para> 10.262 + 10.263 + <para>There are <emphasis>many</emphasis> file merging tools 10.264 + available, too many to cover here. They vary in which 10.265 + platforms they are available for, and in their particular 10.266 + strengths and weaknesses. Most are tuned for merging files 10.267 + containing plain text, while a few are aimed at specialised 10.268 + file formats (generally XML).</para> 10.269 + 10.270 + </sect2> 10.271 + <sect2> 10.272 + <title>A worked example</title> 10.273 + 10.274 + <para>In this example, we will reproduce the file modification 10.275 + history of figure <xref linkend="fig:tour-merge:conflict"/> 10.276 + above. Let's begin by creating a repository with a base 10.277 + version of our document.</para> 10.278 + 10.279 + <!-- &interaction.tour-merge-conflict.wife; --> 10.280 + 10.281 + <para>We'll clone the repository and make a change to the 10.282 + file.</para> 10.283 + 10.284 + <!-- &interaction.tour-merge-conflict.cousin; --> 10.285 + 10.286 + <para>And another clone, to simulate someone else making a 10.287 + change to the file. (This hints at the idea that it's not all 10.288 + that unusual to merge with yourself when you isolate tasks in 10.289 + separate repositories, and indeed to find and resolve 10.290 + conflicts while doing so.)</para> 10.291 + 10.292 + <!-- &interaction.tour-merge-conflict.son; --> 10.293 + 10.294 + <para>Having created two 10.295 + different versions of the file, we'll set up an environment 10.296 + suitable for running our merge.</para> 10.297 + 10.298 + <!-- &interaction.tour-merge-conflict.pull; --> 10.299 + 10.300 + <para>In this example, I won't use Mercurial's normal 10.301 + <command>hgmerge</command> program to do the merge, because it 10.302 + would drop my nice automated example-running tool into a 10.303 + graphical user interface. Instead, I'll set 10.304 + <envar>HGMERGE</envar> to tell Mercurial to use the 10.305 + non-interactive <command>merge</command> command. This is 10.306 + bundled with many Unix-like systems. If you're following this 10.307 + example on your computer, don't bother setting 10.308 + <envar>HGMERGE</envar>.</para> 10.309 + 10.310 + <para><emphasis role="bold">XXX FIX THIS 10.311 + EXAMPLE.</emphasis></para> 10.312 + 10.313 + <!-- &interaction.tour-merge-conflict.merge; --> 10.314 + 10.315 + <para>Because <command>merge</command> can't resolve the 10.316 + conflicting changes, it leaves <emphasis>merge 10.317 + markers</emphasis> inside the file that has conflicts, 10.318 + indicating which lines have conflicts, and whether they came 10.319 + from our version of the file or theirs.</para> 10.320 + 10.321 + <para>Mercurial can tell from the way <command>merge</command> 10.322 + exits that it wasn't able to merge successfully, so it tells 10.323 + us what commands we'll need to run if we want to redo the 10.324 + merging operation. This could be useful if, for example, we 10.325 + were running a graphical merge tool and quit because we were 10.326 + confused or realised we had made a mistake.</para> 10.327 + 10.328 + <para>If automatic or manual merges fail, there's nothing to 10.329 + prevent us from <quote>fixing up</quote> the affected files 10.330 + ourselves, and committing the results of our merge:</para> 10.331 + 10.332 + <!-- &interaction.tour-merge-conflict.commit; --> 10.333 + 10.334 + </sect2> 10.335 + </sect1> 10.336 + <sect1 id="sec:tour-merge:fetch"> 10.337 + <title>Simplifying the pull-merge-commit sequence</title> 10.338 + 10.339 + <para>The process of merging changes as outlined above is 10.340 + straightforward, but requires running three commands in 10.341 + sequence.</para> 10.342 + <programlisting> 10.343 + hg pull hg merge hg commit -m 'Merged remote changes' 10.344 + </programlisting> 10.345 + <para>In the case of the final commit, you also need to enter a 10.346 + commit message, which is almost always going to be a piece of 10.347 + uninteresting <quote>boilerplate</quote> text.</para> 10.348 + 10.349 + <para>It would be nice to reduce the number of steps needed, if 10.350 + this were possible. Indeed, Mercurial is distributed with an 10.351 + extension called <literal role="hg-ext">fetch</literal> that 10.352 + does just this.</para> 10.353 + 10.354 + <para>Mercurial provides a flexible extension mechanism that lets 10.355 + people extend its functionality, while keeping the core of 10.356 + Mercurial small and easy to deal with. Some extensions add new 10.357 + commands that you can use from the command line, while others 10.358 + work <quote>behind the scenes,</quote> for example adding 10.359 + capabilities to the server.</para> 10.360 + 10.361 + <para>The <literal role="hg-ext">fetch</literal> extension adds a 10.362 + new command called, not surprisingly, <command role="hg-cmd">hg 10.363 + fetch</command>. This extension acts as a combination of 10.364 + <command role="hg-cmd">hg pull</command>, <command 10.365 + role="hg-cmd">hg update</command> and <command 10.366 + role="hg-cmd">hg merge</command>. It begins by pulling 10.367 + changes from another repository into the current repository. If 10.368 + it finds that the changes added a new head to the repository, it 10.369 + begins a merge, then commits the result of the merge with an 10.370 + automatically-generated commit message. If no new heads were 10.371 + added, it updates the working directory to the new tip 10.372 + changeset.</para> 10.373 + 10.374 + <para>Enabling the <literal role="hg-ext">fetch</literal> 10.375 + extension is easy. Edit your <filename 10.376 + role="special">.hgrc</filename>, and either go to the <literal 10.377 + role="rc-extensions">extensions</literal> section or create an 10.378 + <literal role="rc-extensions">extensions</literal> section. Then 10.379 + add a line that simply reads <quote><literal>fetch 10.380 + </literal></quote>.</para> 10.381 + <programlisting> 10.382 + [extensions] fetch = 10.383 + </programlisting> 10.384 + <para>(Normally, on the right-hand side of the 10.385 + <quote><literal>=</literal></quote> would appear the location of 10.386 + the extension, but since the <literal 10.387 + role="hg-ext">fetch</literal> extension is in the standard 10.388 + distribution, Mercurial knows where to search for it.)</para> 10.389 + 10.390 + </sect1> 10.391 +</chapter> 10.392 + 10.393 +<!-- 10.394 +local variables: 10.395 +sgml-parent-document: ("00book.xml" "book" "chapter") 10.396 +end: 10.397 +-->
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/en/ch04-concepts.xml Wed Feb 18 00:22:09 2009 -0800 11.3 @@ -0,0 +1,725 @@ 11.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 11.5 + 11.6 +<chapter id="chap:concepts"> 11.7 + <title>Behind the scenes</title> 11.8 + 11.9 + <para>Unlike many revision control systems, the concepts upon which 11.10 + Mercurial is built are simple enough that it's easy to understand 11.11 + how the software really works. Knowing this certainly isn't 11.12 + necessary, but I find it useful to have a <quote>mental 11.13 + model</quote> of what's going on.</para> 11.14 + 11.15 + <para>This understanding gives me confidence that Mercurial has been 11.16 + carefully designed to be both <emphasis>safe</emphasis> and 11.17 + <emphasis>efficient</emphasis>. And just as importantly, if it's 11.18 + easy for me to retain a good idea of what the software is doing 11.19 + when I perform a revision control task, I'm less likely to be 11.20 + surprised by its behaviour.</para> 11.21 + 11.22 + <para>In this chapter, we'll initially cover the core concepts 11.23 + behind Mercurial's design, then continue to discuss some of the 11.24 + interesting details of its implementation.</para> 11.25 + 11.26 + <sect1> 11.27 + <title>Mercurial's historical record</title> 11.28 + 11.29 + <sect2> 11.30 + <title>Tracking the history of a single file</title> 11.31 + 11.32 + <para>When Mercurial tracks modifications to a file, it stores 11.33 + the history of that file in a metadata object called a 11.34 + <emphasis>filelog</emphasis>. Each entry in the filelog 11.35 + contains enough information to reconstruct one revision of the 11.36 + file that is being tracked. Filelogs are stored as files in 11.37 + the <filename role="special" 11.38 + class="directory">.hg/store/data</filename> directory. A 11.39 + filelog contains two kinds of information: revision data, and 11.40 + an index to help Mercurial to find a revision 11.41 + efficiently.</para> 11.42 + 11.43 + <para>A file that is large, or has a lot of history, has its 11.44 + filelog stored in separate data 11.45 + (<quote><literal>.d</literal></quote> suffix) and index 11.46 + (<quote><literal>.i</literal></quote> suffix) files. For 11.47 + small files without much history, the revision data and index 11.48 + are combined in a single <quote><literal>.i</literal></quote> 11.49 + file. The correspondence between a file in the working 11.50 + directory and the filelog that tracks its history in the 11.51 + repository is illustrated in figure <xref 11.52 + linkend="fig:concepts:filelog"/>.</para> 11.53 + 11.54 + <informalfigure id="fig:concepts:filelog"> 11.55 + <mediaobject><imageobject><imagedata 11.56 + fileref="filelog"/></imageobject><textobject><phrase>XXX 11.57 + add text</phrase></textobject> 11.58 + <caption><para>Relationships between files in working 11.59 + directory and filelogs in 11.60 + repository</para></caption></mediaobject> 11.61 + </informalfigure> 11.62 + 11.63 + </sect2> 11.64 + <sect2> 11.65 + <title>Managing tracked files</title> 11.66 + 11.67 + <para>Mercurial uses a structure called a 11.68 + <emphasis>manifest</emphasis> to collect together information 11.69 + about the files that it tracks. Each entry in the manifest 11.70 + contains information about the files present in a single 11.71 + changeset. An entry records which files are present in the 11.72 + changeset, the revision of each file, and a few other pieces 11.73 + of file metadata.</para> 11.74 + 11.75 + </sect2> 11.76 + <sect2> 11.77 + <title>Recording changeset information</title> 11.78 + 11.79 + <para>The <emphasis>changelog</emphasis> contains information 11.80 + about each changeset. Each revision records who committed a 11.81 + change, the changeset comment, other pieces of 11.82 + changeset-related information, and the revision of the 11.83 + manifest to use.</para> 11.84 + 11.85 + </sect2> 11.86 + <sect2> 11.87 + <title>Relationships between revisions</title> 11.88 + 11.89 + <para>Within a changelog, a manifest, or a filelog, each 11.90 + revision stores a pointer to its immediate parent (or to its 11.91 + two parents, if it's a merge revision). As I mentioned above, 11.92 + there are also relationships between revisions 11.93 + <emphasis>across</emphasis> these structures, and they are 11.94 + hierarchical in nature.</para> 11.95 + 11.96 + <para>For every changeset in a repository, there is exactly one 11.97 + revision stored in the changelog. Each revision of the 11.98 + changelog contains a pointer to a single revision of the 11.99 + manifest. A revision of the manifest stores a pointer to a 11.100 + single revision of each filelog tracked when that changeset 11.101 + was created. These relationships are illustrated in figure 11.102 + <xref linkend="fig:concepts:metadata"/>.</para> 11.103 + 11.104 + <informalfigure id="fig:concepts:metadata"> 11.105 + <mediaobject><imageobject><imagedata 11.106 + fileref="metadata"/></imageobject><textobject><phrase>XXX 11.107 + add text</phrase></textobject><caption><para>Metadata 11.108 + relationships</para></caption> 11.109 + </mediaobject> 11.110 + </informalfigure> 11.111 + 11.112 + <para>As the illustration shows, there is 11.113 + <emphasis>not</emphasis> a <quote>one to one</quote> 11.114 + relationship between revisions in the changelog, manifest, or 11.115 + filelog. If the manifest hasn't changed between two 11.116 + changesets, the changelog entries for those changesets will 11.117 + point to the same revision of the manifest. If a file that 11.118 + Mercurial tracks hasn't changed between two changesets, the 11.119 + entry for that file in the two revisions of the manifest will 11.120 + point to the same revision of its filelog.</para> 11.121 + 11.122 + </sect2> 11.123 + </sect1> 11.124 + <sect1> 11.125 + <title>Safe, efficient storage</title> 11.126 + 11.127 + <para>The underpinnings of changelogs, manifests, and filelogs are 11.128 + provided by a single structure called the 11.129 + <emphasis>revlog</emphasis>.</para> 11.130 + 11.131 + <sect2> 11.132 + <title>Efficient storage</title> 11.133 + 11.134 + <para>The revlog provides efficient storage of revisions using a 11.135 + <emphasis>delta</emphasis> mechanism. Instead of storing a 11.136 + complete copy of a file for each revision, it stores the 11.137 + changes needed to transform an older revision into the new 11.138 + revision. For many kinds of file data, these deltas are 11.139 + typically a fraction of a percent of the size of a full copy 11.140 + of a file.</para> 11.141 + 11.142 + <para>Some obsolete revision control systems can only work with 11.143 + deltas of text files. They must either store binary files as 11.144 + complete snapshots or encoded into a text representation, both 11.145 + of which are wasteful approaches. Mercurial can efficiently 11.146 + handle deltas of files with arbitrary binary contents; it 11.147 + doesn't need to treat text as special.</para> 11.148 + 11.149 + </sect2> 11.150 + <sect2 id="sec:concepts:txn"> 11.151 + <title>Safe operation</title> 11.152 + 11.153 + <para>Mercurial only ever <emphasis>appends</emphasis> data to 11.154 + the end of a revlog file. It never modifies a section of a 11.155 + file after it has written it. This is both more robust and 11.156 + efficient than schemes that need to modify or rewrite 11.157 + data.</para> 11.158 + 11.159 + <para>In addition, Mercurial treats every write as part of a 11.160 + <emphasis>transaction</emphasis> that can span a number of 11.161 + files. A transaction is <emphasis>atomic</emphasis>: either 11.162 + the entire transaction succeeds and its effects are all 11.163 + visible to readers in one go, or the whole thing is undone. 11.164 + This guarantee of atomicity means that if you're running two 11.165 + copies of Mercurial, where one is reading data and one is 11.166 + writing it, the reader will never see a partially written 11.167 + result that might confuse it.</para> 11.168 + 11.169 + <para>The fact that Mercurial only appends to files makes it 11.170 + easier to provide this transactional guarantee. The easier it 11.171 + is to do stuff like this, the more confident you should be 11.172 + that it's done correctly.</para> 11.173 + 11.174 + </sect2> 11.175 + <sect2> 11.176 + <title>Fast retrieval</title> 11.177 + 11.178 + <para>Mercurial cleverly avoids a pitfall common to all earlier 11.179 + revision control systems: the problem of <emphasis>inefficient 11.180 + retrieval</emphasis>. Most revision control systems store 11.181 + the contents of a revision as an incremental series of 11.182 + modifications against a <quote>snapshot</quote>. To 11.183 + reconstruct a specific revision, you must first read the 11.184 + snapshot, and then every one of the revisions between the 11.185 + snapshot and your target revision. The more history that a 11.186 + file accumulates, the more revisions you must read, hence the 11.187 + longer it takes to reconstruct a particular revision.</para> 11.188 + 11.189 + <informalfigure id="fig:concepts:snapshot"> 11.190 + <mediaobject><imageobject><imagedata 11.191 + fileref="snapshot"/></imageobject><textobject><phrase>XXX 11.192 + add text</phrase></textobject><caption><para>Snapshot of 11.193 + a revlog, with incremental 11.194 + deltas</para></caption></mediaobject> 11.195 + </informalfigure> 11.196 + 11.197 + <para>The innovation that Mercurial applies to this problem is 11.198 + simple but effective. Once the cumulative amount of delta 11.199 + information stored since the last snapshot exceeds a fixed 11.200 + threshold, it stores a new snapshot (compressed, of course), 11.201 + instead of another delta. This makes it possible to 11.202 + reconstruct <emphasis>any</emphasis> revision of a file 11.203 + quickly. This approach works so well that it has since been 11.204 + copied by several other revision control systems.</para> 11.205 + 11.206 + <para>Figure <xref linkend="fig:concepts:snapshot"/> illustrates 11.207 + the idea. In an entry in a revlog's index file, Mercurial 11.208 + stores the range of entries from the data file that it must 11.209 + read to reconstruct a particular revision.</para> 11.210 + 11.211 + <sect3> 11.212 + <title>Aside: the influence of video compression</title> 11.213 + 11.214 + <para>If you're familiar with video compression or have ever 11.215 + watched a TV feed through a digital cable or satellite 11.216 + service, you may know that most video compression schemes 11.217 + store each frame of video as a delta against its predecessor 11.218 + frame. In addition, these schemes use <quote>lossy</quote> 11.219 + compression techniques to increase the compression ratio, so 11.220 + visual errors accumulate over the course of a number of 11.221 + inter-frame deltas.</para> 11.222 + 11.223 + <para>Because it's possible for a video stream to <quote>drop 11.224 + out</quote> occasionally due to signal glitches, and to 11.225 + limit the accumulation of artefacts introduced by the lossy 11.226 + compression process, video encoders periodically insert a 11.227 + complete frame (called a <quote>key frame</quote>) into the 11.228 + video stream; the next delta is generated against that 11.229 + frame. This means that if the video signal gets 11.230 + interrupted, it will resume once the next key frame is 11.231 + received. Also, the accumulation of encoding errors 11.232 + restarts anew with each key frame.</para> 11.233 + 11.234 + </sect3> 11.235 + </sect2> 11.236 + <sect2> 11.237 + <title>Identification and strong integrity</title> 11.238 + 11.239 + <para>Along with delta or snapshot information, a revlog entry 11.240 + contains a cryptographic hash of the data that it represents. 11.241 + This makes it difficult to forge the contents of a revision, 11.242 + and easy to detect accidental corruption.</para> 11.243 + 11.244 + <para>Hashes provide more than a mere check against corruption; 11.245 + they are used as the identifiers for revisions. The changeset 11.246 + identification hashes that you see as an end user are from 11.247 + revisions of the changelog. Although filelogs and the 11.248 + manifest also use hashes, Mercurial only uses these behind the 11.249 + scenes.</para> 11.250 + 11.251 + <para>Mercurial verifies that hashes are correct when it 11.252 + retrieves file revisions and when it pulls changes from 11.253 + another repository. If it encounters an integrity problem, it 11.254 + will complain and stop whatever it's doing.</para> 11.255 + 11.256 + <para>In addition to the effect it has on retrieval efficiency, 11.257 + Mercurial's use of periodic snapshots makes it more robust 11.258 + against partial data corruption. If a revlog becomes partly 11.259 + corrupted due to a hardware error or system bug, it's often 11.260 + possible to reconstruct some or most revisions from the 11.261 + uncorrupted sections of the revlog, both before and after the 11.262 + corrupted section. This would not be possible with a 11.263 + delta-only storage model.</para> 11.264 + 11.265 + </sect2> 11.266 + </sect1> 11.267 + <sect1> 11.268 + <title>Revision history, branching, and merging</title> 11.269 + 11.270 + <para>Every entry in a Mercurial revlog knows the identity of its 11.271 + immediate ancestor revision, usually referred to as its 11.272 + <emphasis>parent</emphasis>. In fact, a revision contains room 11.273 + for not one parent, but two. Mercurial uses a special hash, 11.274 + called the <quote>null ID</quote>, to represent the idea 11.275 + <quote>there is no parent here</quote>. This hash is simply a 11.276 + string of zeroes.</para> 11.277 + 11.278 + <para>In figure <xref linkend="fig:concepts:revlog"/>, you can see 11.279 + an example of the conceptual structure of a revlog. Filelogs, 11.280 + manifests, and changelogs all have this same structure; they 11.281 + differ only in the kind of data stored in each delta or 11.282 + snapshot.</para> 11.283 + 11.284 + <para>The first revision in a revlog (at the bottom of the image) 11.285 + has the null ID in both of its parent slots. For a 11.286 + <quote>normal</quote> revision, its first parent slot contains 11.287 + the ID of its parent revision, and its second contains the null 11.288 + ID, indicating that the revision has only one real parent. Any 11.289 + two revisions that have the same parent ID are branches. A 11.290 + revision that represents a merge between branches has two normal 11.291 + revision IDs in its parent slots.</para> 11.292 + 11.293 + <informalfigure id="fig:concepts:revlog"> 11.294 + <mediaobject><imageobject><imagedata 11.295 + fileref="revlog"/></imageobject><textobject><phrase>XXX 11.296 + add text</phrase></textobject></mediaobject> 11.297 + </informalfigure> 11.298 + 11.299 + </sect1> 11.300 + <sect1> 11.301 + <title>The working directory</title> 11.302 + 11.303 + <para>In the working directory, Mercurial stores a snapshot of the 11.304 + files from the repository as of a particular changeset.</para> 11.305 + 11.306 + <para>The working directory <quote>knows</quote> which changeset 11.307 + it contains. When you update the working directory to contain a 11.308 + particular changeset, Mercurial looks up the appropriate 11.309 + revision of the manifest to find out which files it was tracking 11.310 + at the time that changeset was committed, and which revision of 11.311 + each file was then current. It then recreates a copy of each of 11.312 + those files, with the same contents it had when the changeset 11.313 + was committed.</para> 11.314 + 11.315 + <para>The <emphasis>dirstate</emphasis> contains Mercurial's 11.316 + knowledge of the working directory. This details which 11.317 + changeset the working directory is updated to, and all of the 11.318 + files that Mercurial is tracking in the working 11.319 + directory.</para> 11.320 + 11.321 + <para>Just as a revision of a revlog has room for two parents, so 11.322 + that it can represent either a normal revision (with one parent) 11.323 + or a merge of two earlier revisions, the dirstate has slots for 11.324 + two parents. When you use the <command role="hg-cmd">hg 11.325 + update</command> command, the changeset that you update to is 11.326 + stored in the <quote>first parent</quote> slot, and the null ID 11.327 + in the second. When you <command role="hg-cmd">hg 11.328 + merge</command> with another changeset, the first parent 11.329 + remains unchanged, and the second parent is filled in with the 11.330 + changeset you're merging with. The <command role="hg-cmd">hg 11.331 + parents</command> command tells you what the parents of the 11.332 + dirstate are.</para> 11.333 + 11.334 + <sect2> 11.335 + <title>What happens when you commit</title> 11.336 + 11.337 + <para>The dirstate stores parent information for more than just 11.338 + book-keeping purposes. Mercurial uses the parents of the 11.339 + dirstate as <emphasis>the parents of a new 11.340 + changeset</emphasis> when you perform a commit.</para> 11.341 + 11.342 + <informalfigure id="fig:concepts:wdir"> 11.343 + <mediaobject><imageobject><imagedata 11.344 + fileref="wdir"/></imageobject><textobject><phrase>XXX 11.345 + add text</phrase></textobject><caption><para>The working 11.346 + directory can have two 11.347 + parents</para></caption></mediaobject> 11.348 + </informalfigure> 11.349 + 11.350 + <para>Figure <xref linkend="fig:concepts:wdir"/> shows the 11.351 + normal state of the working directory, where it has a single 11.352 + changeset as parent. That changeset is the 11.353 + <emphasis>tip</emphasis>, the newest changeset in the 11.354 + repository that has no children.</para> 11.355 + 11.356 + <informalfigure id="fig:concepts:wdir-after-commit"> 11.357 + <mediaobject><imageobject><imagedata 11.358 + fileref="wdir-after-commit"/></imageobject><textobject><phrase>XXX 11.359 + add text</phrase></textobject><caption><para>The working 11.360 + directory gains new parents after a 11.361 + commit</para></caption></mediaobject> 11.362 + </informalfigure> 11.363 + 11.364 + <para>It's useful to think of the working directory as 11.365 + <quote>the changeset I'm about to commit</quote>. Any files 11.366 + that you tell Mercurial that you've added, removed, renamed, 11.367 + or copied will be reflected in that changeset, as will 11.368 + modifications to any files that Mercurial is already tracking; 11.369 + the new changeset will have the parents of the working 11.370 + directory as its parents.</para> 11.371 + 11.372 + <para>After a commit, Mercurial will update the parents of the 11.373 + working directory, so that the first parent is the ID of the 11.374 + new changeset, and the second is the null ID. This is shown 11.375 + in figure <xref linkend="fig:concepts:wdir-after-commit"/>. 11.376 + Mercurial 11.377 + doesn't touch any of the files in the working directory when 11.378 + you commit; it just modifies the dirstate to note its new 11.379 + parents.</para> 11.380 + 11.381 + </sect2> 11.382 + <sect2> 11.383 + <title>Creating a new head</title> 11.384 + 11.385 + <para>It's perfectly normal to update the working directory to a 11.386 + changeset other than the current tip. For example, you might 11.387 + want to know what your project looked like last Tuesday, or 11.388 + you could be looking through changesets to see which one 11.389 + introduced a bug. In cases like this, the natural thing to do 11.390 + is update the working directory to the changeset you're 11.391 + interested in, and then examine the files in the working 11.392 + directory directly to see their contents as they were when you 11.393 + committed that changeset. The effect of this is shown in 11.394 + figure <xref linkend="fig:concepts:wdir-pre-branch"/>.</para> 11.395 + 11.396 + <informalfigure id="fig:concepts:wdir-pre-branch"> 11.397 + <mediaobject><imageobject><imagedata 11.398 + fileref="wdir-pre-branch"/></imageobject><textobject><phrase>XXX 11.399 + add text</phrase></textobject><caption><para>The working 11.400 + directory, updated to an older 11.401 + changeset</para></caption></mediaobject> 11.402 + </informalfigure> 11.403 + 11.404 + <para>Having updated the working directory to an older 11.405 + changeset, what happens if you make some changes, and then 11.406 + commit? Mercurial behaves in the same way as I outlined 11.407 + above. The parents of the working directory become the 11.408 + parents of the new changeset. This new changeset has no 11.409 + children, so it becomes the new tip. And the repository now 11.410 + contains two changesets that have no children; we call these 11.411 + <emphasis>heads</emphasis>. You can see the structure that 11.412 + this creates in figure <xref 11.413 + linkend="fig:concepts:wdir-branch"/>.</para> 11.414 + 11.415 + <informalfigure id="fig:concepts:wdir-branch"> 11.416 + <mediaobject><imageobject><imagedata 11.417 + fileref="wdir-branch"/></imageobject><textobject><phrase>XXX 11.418 + add text</phrase></textobject><caption><para>After a 11.419 + commit made while synced to an older 11.420 + changeset</para></caption></mediaobject> 11.421 + </informalfigure> 11.422 + 11.423 + <note> 11.424 + <para> If you're new to Mercurial, you should keep in mind a 11.425 + common <quote>error</quote>, which is to use the <command 11.426 + role="hg-cmd">hg pull</command> command without any 11.427 + options. By default, the <command role="hg-cmd">hg 11.428 + pull</command> command <emphasis>does not</emphasis> 11.429 + update the working directory, so you'll bring new changesets 11.430 + into your repository, but the working directory will stay 11.431 + synced at the same changeset as before the pull. If you 11.432 + make some changes and commit afterwards, you'll thus create 11.433 + a new head, because your working directory isn't synced to 11.434 + whatever the current tip is.</para> 11.435 + 11.436 + <para> I put the word <quote>error</quote> in quotes because 11.437 + all that you need to do to rectify this situation is 11.438 + <command role="hg-cmd">hg merge</command>, then <command 11.439 + role="hg-cmd">hg commit</command>. In other words, this 11.440 + almost never has negative consequences; it just surprises 11.441 + people. I'll discuss other ways to avoid this behaviour, 11.442 + and why Mercurial behaves in this initially surprising way, 11.443 + later on.</para> 11.444 + </note> 11.445 + 11.446 + </sect2> 11.447 + <sect2> 11.448 + <title>Merging heads</title> 11.449 + 11.450 + <para>When you run the <command role="hg-cmd">hg merge</command> 11.451 + command, Mercurial leaves the first parent of the working 11.452 + directory unchanged, and sets the second parent to the 11.453 + changeset you're merging with, as shown in figure <xref 11.454 + linkend="fig:concepts:wdir-merge"/>.</para> 11.455 + 11.456 + <informalfigure id="fig:concepts:wdir-merge"> 11.457 + <mediaobject><imageobject><imagedata 11.458 + fileref="wdir-merge"/></imageobject><textobject><phrase>XXX 11.459 + add text</phrase></textobject><caption><para>Merging two 11.460 + heads</para></caption></mediaobject> 11.461 + </informalfigure> 11.462 + 11.463 + <para>Mercurial also has to modify the working directory, to 11.464 + merge the files managed in the two changesets. Simplified a 11.465 + little, the merging process goes like this, for every file in 11.466 + the manifests of both changesets.</para> 11.467 + <itemizedlist> 11.468 + <listitem><para>If neither changeset has modified a file, do 11.469 + nothing with that file.</para> 11.470 + </listitem> 11.471 + <listitem><para>If one changeset has modified a file, and the 11.472 + other hasn't, create the modified copy of the file in the 11.473 + working directory.</para> 11.474 + </listitem> 11.475 + <listitem><para>If one changeset has removed a file, and the 11.476 + other hasn't (or has also deleted it), delete the file 11.477 + from the working directory.</para> 11.478 + </listitem> 11.479 + <listitem><para>If one changeset has removed a file, but the 11.480 + other has modified the file, ask the user what to do: keep 11.481 + the modified file, or remove it?</para> 11.482 + </listitem> 11.483 + <listitem><para>If both changesets have modified a file, 11.484 + invoke an external merge program to choose the new 11.485 + contents for the merged file. This may require input from 11.486 + the user.</para> 11.487 + </listitem> 11.488 + <listitem><para>If one changeset has modified a file, and the 11.489 + other has renamed or copied the file, make sure that the 11.490 + changes follow the new name of the file.</para> 11.491 + </listitem></itemizedlist> 11.492 + <para>There are more details&emdash;merging has plenty of corner 11.493 + cases&emdash;but these are the most common choices that are 11.494 + involved in a merge. As you can see, most cases are 11.495 + completely automatic, and indeed most merges finish 11.496 + automatically, without requiring your input to resolve any 11.497 + conflicts.</para> 11.498 + 11.499 + <para>When you're thinking about what happens when you commit 11.500 + after a merge, once again the working directory is <quote>the 11.501 + changeset I'm about to commit</quote>. After the <command 11.502 + role="hg-cmd">hg merge</command> command completes, the 11.503 + working directory has two parents; these will become the 11.504 + parents of the new changeset.</para> 11.505 + 11.506 + <para>Mercurial lets you perform multiple merges, but you must 11.507 + commit the results of each individual merge as you go. This 11.508 + is necessary because Mercurial only tracks two parents for 11.509 + both revisions and the working directory. While it would be 11.510 + technically possible to merge multiple changesets at once, the 11.511 + prospect of user confusion and making a terrible mess of a 11.512 + merge immediately becomes overwhelming.</para> 11.513 + 11.514 + </sect2> 11.515 + </sect1> 11.516 + <sect1> 11.517 + <title>Other interesting design features</title> 11.518 + 11.519 + <para>In the sections above, I've tried to highlight some of the 11.520 + most important aspects of Mercurial's design, to illustrate that 11.521 + it pays careful attention to reliability and performance. 11.522 + However, the attention to detail doesn't stop there. There are 11.523 + a number of other aspects of Mercurial's construction that I 11.524 + personally find interesting. I'll detail a few of them here, 11.525 + separate from the <quote>big ticket</quote> items above, so that 11.526 + if you're interested, you can gain a better idea of the amount 11.527 + of thinking that goes into a well-designed system.</para> 11.528 + 11.529 + <sect2> 11.530 + <title>Clever compression</title> 11.531 + 11.532 + <para>When appropriate, Mercurial will store both snapshots and 11.533 + deltas in compressed form. It does this by always 11.534 + <emphasis>trying to</emphasis> compress a snapshot or delta, 11.535 + but only storing the compressed version if it's smaller than 11.536 + the uncompressed version.</para> 11.537 + 11.538 + <para>This means that Mercurial does <quote>the right 11.539 + thing</quote> when storing a file whose native form is 11.540 + compressed, such as a <literal>zip</literal> archive or a JPEG 11.541 + image. When these types of files are compressed a second 11.542 + time, the resulting file is usually bigger than the 11.543 + once-compressed form, and so Mercurial will store the plain 11.544 + <literal>zip</literal> or JPEG.</para> 11.545 + 11.546 + <para>Deltas between revisions of a compressed file are usually 11.547 + larger than snapshots of the file, and Mercurial again does 11.548 + <quote>the right thing</quote> in these cases. It finds that 11.549 + such a delta exceeds the threshold at which it should store a 11.550 + complete snapshot of the file, so it stores the snapshot, 11.551 + again saving space compared to a naive delta-only 11.552 + approach.</para> 11.553 + 11.554 + <sect3> 11.555 + <title>Network recompression</title> 11.556 + 11.557 + <para>When storing revisions on disk, Mercurial uses the 11.558 + <quote>deflate</quote> compression algorithm (the same one 11.559 + used by the popular <literal>zip</literal> archive format), 11.560 + which balances good speed with a respectable compression 11.561 + ratio. However, when transmitting revision data over a 11.562 + network connection, Mercurial uncompresses the compressed 11.563 + revision data.</para> 11.564 + 11.565 + <para>If the connection is over HTTP, Mercurial recompresses 11.566 + the entire stream of data using a compression algorithm that 11.567 + gives a better compression ratio (the Burrows-Wheeler 11.568 + algorithm from the widely used <literal>bzip2</literal> 11.569 + compression package). This combination of algorithm and 11.570 + compression of the entire stream (instead of a revision at a 11.571 + time) substantially reduces the number of bytes to be 11.572 + transferred, yielding better network performance over almost 11.573 + all kinds of network.</para> 11.574 + 11.575 + <para>(If the connection is over <command>ssh</command>, 11.576 + Mercurial <emphasis>doesn't</emphasis> recompress the 11.577 + stream, because <command>ssh</command> can already do this 11.578 + itself.)</para> 11.579 + 11.580 + </sect3> 11.581 + </sect2> 11.582 + <sect2> 11.583 + <title>Read/write ordering and atomicity</title> 11.584 + 11.585 + <para>Appending to files isn't the whole story when it comes to 11.586 + guaranteeing that a reader won't see a partial write. If you 11.587 + recall figure <xref linkend="fig:concepts:metadata"/>, 11.588 + revisions in the 11.589 + changelog point to revisions in the manifest, and revisions in 11.590 + the manifest point to revisions in filelogs. This hierarchy 11.591 + is deliberate.</para> 11.592 + 11.593 + <para>A writer starts a transaction by writing filelog and 11.594 + manifest data, and doesn't write any changelog data until 11.595 + those are finished. A reader starts by reading changelog 11.596 + data, then manifest data, followed by filelog data.</para> 11.597 + 11.598 + <para>Since the writer has always finished writing filelog and 11.599 + manifest data before it writes to the changelog, a reader will 11.600 + never read a pointer to a partially written manifest revision 11.601 + from the changelog, and it will never read a pointer to a 11.602 + partially written filelog revision from the manifest.</para> 11.603 + 11.604 + </sect2> 11.605 + <sect2> 11.606 + <title>Concurrent access</title> 11.607 + 11.608 + <para>The read/write ordering and atomicity guarantees mean that 11.609 + Mercurial never needs to <emphasis>lock</emphasis> a 11.610 + repository when it's reading data, even if the repository is 11.611 + being written to while the read is occurring. This has a big 11.612 + effect on scalability; you can have an arbitrary number of 11.613 + Mercurial processes safely reading data from a repository 11.614 + safely all at once, no matter whether it's being written to or 11.615 + not.</para> 11.616 + 11.617 + <para>The lockless nature of reading means that if you're 11.618 + sharing a repository on a multi-user system, you don't need to 11.619 + grant other local users permission to 11.620 + <emphasis>write</emphasis> to your repository in order for 11.621 + them to be able to clone it or pull changes from it; they only 11.622 + need <emphasis>read</emphasis> permission. (This is 11.623 + <emphasis>not</emphasis> a common feature among revision 11.624 + control systems, so don't take it for granted! Most require 11.625 + readers to be able to lock a repository to access it safely, 11.626 + and this requires write permission on at least one directory, 11.627 + which of course makes for all kinds of nasty and annoying 11.628 + security and administrative problems.)</para> 11.629 + 11.630 + <para>Mercurial uses locks to ensure that only one process can 11.631 + write to a repository at a time (the locking mechanism is safe 11.632 + even over filesystems that are notoriously hostile to locking, 11.633 + such as NFS). If a repository is locked, a writer will wait 11.634 + for a while to retry if the repository becomes unlocked, but 11.635 + if the repository remains locked for too long, the process 11.636 + attempting to write will time out after a while. This means 11.637 + that your daily automated scripts won't get stuck forever and 11.638 + pile up if a system crashes unnoticed, for example. (Yes, the 11.639 + timeout is configurable, from zero to infinity.)</para> 11.640 + 11.641 + <sect3> 11.642 + <title>Safe dirstate access</title> 11.643 + 11.644 + <para>As with revision data, Mercurial doesn't take a lock to 11.645 + read the dirstate file; it does acquire a lock to write it. 11.646 + To avoid the possibility of reading a partially written copy 11.647 + of the dirstate file, Mercurial writes to a file with a 11.648 + unique name in the same directory as the dirstate file, then 11.649 + renames the temporary file atomically to 11.650 + <filename>dirstate</filename>. The file named 11.651 + <filename>dirstate</filename> is thus guaranteed to be 11.652 + complete, not partially written.</para> 11.653 + 11.654 + </sect3> 11.655 + </sect2> 11.656 + <sect2> 11.657 + <title>Avoiding seeks</title> 11.658 + 11.659 + <para>Critical to Mercurial's performance is the avoidance of 11.660 + seeks of the disk head, since any seek is far more expensive 11.661 + than even a comparatively large read operation.</para> 11.662 + 11.663 + <para>This is why, for example, the dirstate is stored in a 11.664 + single file. If there were a dirstate file per directory that 11.665 + Mercurial tracked, the disk would seek once per directory. 11.666 + Instead, Mercurial reads the entire single dirstate file in 11.667 + one step.</para> 11.668 + 11.669 + <para>Mercurial also uses a <quote>copy on write</quote> scheme 11.670 + when cloning a repository on local storage. Instead of 11.671 + copying every revlog file from the old repository into the new 11.672 + repository, it makes a <quote>hard link</quote>, which is a 11.673 + shorthand way to say <quote>these two names point to the same 11.674 + file</quote>. When Mercurial is about to write to one of a 11.675 + revlog's files, it checks to see if the number of names 11.676 + pointing at the file is greater than one. If it is, more than 11.677 + one repository is using the file, so Mercurial makes a new 11.678 + copy of the file that is private to this repository.</para> 11.679 + 11.680 + <para>A few revision control developers have pointed out that 11.681 + this idea of making a complete private copy of a file is not 11.682 + very efficient in its use of storage. While this is true, 11.683 + storage is cheap, and this method gives the highest 11.684 + performance while deferring most book-keeping to the operating 11.685 + system. An alternative scheme would most likely reduce 11.686 + performance and increase the complexity of the software, each 11.687 + of which is much more important to the <quote>feel</quote> of 11.688 + day-to-day use.</para> 11.689 + 11.690 + </sect2> 11.691 + <sect2> 11.692 + <title>Other contents of the dirstate</title> 11.693 + 11.694 + <para>Because Mercurial doesn't force you to tell it when you're 11.695 + modifying a file, it uses the dirstate to store some extra 11.696 + information so it can determine efficiently whether you have 11.697 + modified a file. For each file in the working directory, it 11.698 + stores the time that it last modified the file itself, and the 11.699 + size of the file at that time.</para> 11.700 + 11.701 + <para>When you explicitly <command role="hg-cmd">hg 11.702 + add</command>, <command role="hg-cmd">hg remove</command>, 11.703 + <command role="hg-cmd">hg rename</command> or <command 11.704 + role="hg-cmd">hg copy</command> files, Mercurial updates the 11.705 + dirstate so that it knows what to do with those files when you 11.706 + commit.</para> 11.707 + 11.708 + <para>When Mercurial is checking the states of files in the 11.709 + working directory, it first checks a file's modification time. 11.710 + If that has not changed, the file must not have been modified. 11.711 + If the file's size has changed, the file must have been 11.712 + modified. If the modification time has changed, but the size 11.713 + has not, only then does Mercurial need to read the actual 11.714 + contents of the file to see if they've changed. Storing these 11.715 + few extra pieces of information dramatically reduces the 11.716 + amount of data that Mercurial needs to read, which yields 11.717 + large performance improvements compared to other revision 11.718 + control systems.</para> 11.719 + 11.720 + </sect2> 11.721 + </sect1> 11.722 +</chapter> 11.723 + 11.724 +<!-- 11.725 +local variables: 11.726 +sgml-parent-document: ("00book.xml" "book" "chapter") 11.727 +end: 11.728 +-->
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/en/ch05-daily.xml Wed Feb 18 00:22:09 2009 -0800 12.3 @@ -0,0 +1,490 @@ 12.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 12.5 + 12.6 +<chapter id="chap:daily"> 12.7 + <title>Mercurial in daily use</title> 12.8 + 12.9 + <sect1> 12.10 + <title>Telling Mercurial which files to track</title> 12.11 + 12.12 + <para>Mercurial does not work with files in your repository unless 12.13 + you tell it to manage them. The <command role="hg-cmd">hg 12.14 + status</command> command will tell you which files Mercurial 12.15 + doesn't know about; it uses a 12.16 + <quote><literal>?</literal></quote> to display such 12.17 + files.</para> 12.18 + 12.19 + <para>To tell Mercurial to track a file, use the <command 12.20 + role="hg-cmd">hg add</command> command. Once you have added a 12.21 + file, the entry in the output of <command role="hg-cmd">hg 12.22 + status</command> for that file changes from 12.23 + <quote><literal>?</literal></quote> to 12.24 + <quote><literal>A</literal></quote>. <!-- 12.25 + &interaction.daily.files.add; --></para> 12.26 + 12.27 + <para>After you run a <command role="hg-cmd">hg commit</command>, 12.28 + the files that you added before the commit will no longer be 12.29 + listed in the output of <command role="hg-cmd">hg 12.30 + status</command>. The reason for this is that <command 12.31 + role="hg-cmd">hg status</command> only tells you about 12.32 + <quote>interesting</quote> files&emdash;those that you have 12.33 + modified or told Mercurial to do something with&emdash;by 12.34 + default. If you have a repository that contains thousands of 12.35 + files, you will rarely want to know about files that Mercurial 12.36 + is tracking, but that have not changed. (You can still get this 12.37 + information; we'll return to this later.)</para> 12.38 + 12.39 + <para>Once you add a file, Mercurial doesn't do anything with it 12.40 + immediately. Instead, it will take a snapshot of the file's 12.41 + state the next time you perform a commit. It will then continue 12.42 + to track the changes you make to the file every time you commit, 12.43 + until you remove the file.</para> 12.44 + 12.45 + <sect2> 12.46 + <title>Explicit versus implicit file naming</title> 12.47 + 12.48 + <para>A useful behaviour that Mercurial has is that if you pass 12.49 + the name of a directory to a command, every Mercurial command 12.50 + will treat this as <quote>I want to operate on every file in 12.51 + this directory and its subdirectories</quote>. <!-- 12.52 + &interaction.daily.files.add-dir; --> Notice in this example 12.53 + that Mercurial printed the names of the files it added, 12.54 + whereas it didn't do so when we added the file named 12.55 + <filename>a</filename> in the earlier example.</para> 12.56 + 12.57 + <para>What's going on is that in the former case, we explicitly 12.58 + named the file to add on the command line, so the assumption 12.59 + that Mercurial makes in such cases is that you know what you 12.60 + were doing, and it doesn't print any output.</para> 12.61 + 12.62 + <para>However, when we <emphasis>imply</emphasis> the names of 12.63 + files by giving the name of a directory, Mercurial takes the 12.64 + extra step of printing the name of each file that it does 12.65 + something with. This makes it more clear what is happening, 12.66 + and reduces the likelihood of a silent and nasty surprise. 12.67 + This behaviour is common to most Mercurial commands.</para> 12.68 + 12.69 + </sect2> 12.70 + <sect2> 12.71 + <title>Aside: Mercurial tracks files, not directories</title> 12.72 + 12.73 + <para>Mercurial does not track directory information. Instead, 12.74 + it tracks the path to a file. Before creating a file, it 12.75 + first creates any missing directory components of the path. 12.76 + After it deletes a file, it then deletes any empty directories 12.77 + that were in the deleted file's path. This sounds like a 12.78 + trivial distinction, but it has one minor practical 12.79 + consequence: it is not possible to represent a completely 12.80 + empty directory in Mercurial.</para> 12.81 + 12.82 + <para>Empty directories are rarely useful, and there are 12.83 + unintrusive workarounds that you can use to achieve an 12.84 + appropriate effect. The developers of Mercurial thus felt 12.85 + that the complexity that would be required to manage empty 12.86 + directories was not worth the limited benefit this feature 12.87 + would bring.</para> 12.88 + 12.89 + <para>If you need an empty directory in your repository, there 12.90 + are a few ways to achieve this. One is to create a directory, 12.91 + then <command role="hg-cmd">hg add</command> a 12.92 + <quote>hidden</quote> file to that directory. On Unix-like 12.93 + systems, any file name that begins with a period 12.94 + (<quote><literal>.</literal></quote>) is treated as hidden by 12.95 + most commands and GUI tools. This approach is illustrated 12.96 + below.</para> 12.97 + 12.98 +<!-- &interaction.daily.files.hidden; --> 12.99 + 12.100 + <para>Another way to tackle a need for an empty directory is to 12.101 + simply create one in your automated build scripts before they 12.102 + will need it.</para> 12.103 + 12.104 + </sect2> 12.105 + </sect1> 12.106 + <sect1> 12.107 + <title>How to stop tracking a file</title> 12.108 + 12.109 + <para>Once you decide that a file no longer belongs in your 12.110 + repository, use the <command role="hg-cmd">hg remove</command> 12.111 + command; this deletes the file, and tells Mercurial to stop 12.112 + tracking it. A removed file is represented in the output of 12.113 + <command role="hg-cmd">hg status</command> with a 12.114 + <quote><literal>R</literal></quote>. <!-- 12.115 + &interaction.daily.files.remove; --></para> 12.116 + 12.117 + <para>After you <command role="hg-cmd">hg remove</command> a file, 12.118 + Mercurial will no longer track changes to that file, even if you 12.119 + recreate a file with the same name in your working directory. 12.120 + If you do recreate a file with the same name and want Mercurial 12.121 + to track the new file, simply <command role="hg-cmd">hg 12.122 + add</command> it. Mercurial will know that the newly added 12.123 + file is not related to the old file of the same name.</para> 12.124 + 12.125 + <sect2> 12.126 + <title>Removing a file does not affect its history</title> 12.127 + 12.128 + <para>It is important to understand that removing a file has 12.129 + only two effects.</para> 12.130 + <itemizedlist> 12.131 + <listitem><para>It removes the current version of the file 12.132 + from the working directory.</para> 12.133 + </listitem> 12.134 + <listitem><para>It stops Mercurial from tracking changes to 12.135 + the file, from the time of the next commit.</para> 12.136 + </listitem></itemizedlist> 12.137 + <para>Removing a file <emphasis>does not</emphasis> in any way 12.138 + alter the <emphasis>history</emphasis> of the file.</para> 12.139 + 12.140 + <para>If you update the working directory to a changeset in 12.141 + which a file that you have removed was still tracked, it will 12.142 + reappear in the working directory, with the contents it had 12.143 + when you committed that changeset. If you then update the 12.144 + working directory to a later changeset, in which the file had 12.145 + been removed, Mercurial will once again remove the file from 12.146 + the working directory.</para> 12.147 + 12.148 + </sect2> 12.149 + <sect2> 12.150 + <title>Missing files</title> 12.151 + 12.152 + <para>Mercurial considers a file that you have deleted, but not 12.153 + used <command role="hg-cmd">hg remove</command> to delete, to 12.154 + be <emphasis>missing</emphasis>. A missing file is 12.155 + represented with <quote><literal>!</literal></quote> in the 12.156 + output of <command role="hg-cmd">hg status</command>. 12.157 + Mercurial commands will not generally do anything with missing 12.158 + files. <!-- &interaction.daily.files.missing; --></para> 12.159 + 12.160 + <para>If your repository contains a file that <command 12.161 + role="hg-cmd">hg status</command> reports as missing, and 12.162 + you want the file to stay gone, you can run <command 12.163 + role="hg-cmd">hg remove <option 12.164 + role="hg-opt-remove">--after</option></command> at any 12.165 + time later on, to tell Mercurial that you really did mean to 12.166 + remove the file. <!-- &interaction.daily.files.remove-after; 12.167 + --></para> 12.168 + 12.169 + <para>On the other hand, if you deleted the missing file by 12.170 + accident, give <command role="hg-cmd">hg revert</command> the 12.171 + name of the file to recover. It will reappear, in unmodified 12.172 + form.</para> 12.173 + 12.174 +<!-- &interaction.daily.files.recover-missing; --> 12.175 + 12.176 + </sect2> 12.177 + <sect2> 12.178 + <title>Aside: why tell Mercurial explicitly to remove a 12.179 + file?</title> 12.180 + 12.181 + <para>You might wonder why Mercurial requires you to explicitly 12.182 + tell it that you are deleting a file. Early during the 12.183 + development of Mercurial, it let you delete a file however you 12.184 + pleased; Mercurial would notice the absence of the file 12.185 + automatically when you next ran a <command role="hg-cmd">hg 12.186 + commit</command>, and stop tracking the file. In practice, 12.187 + this made it too easy to accidentally remove a file without 12.188 + noticing.</para> 12.189 + 12.190 + </sect2> 12.191 + <sect2> 12.192 + <title>Useful shorthand&emdash;adding and removing files in one 12.193 + step</title> 12.194 + 12.195 + <para>Mercurial offers a combination command, <command 12.196 + role="hg-cmd">hg addremove</command>, that adds untracked 12.197 + files and marks missing files as removed. <!-- 12.198 + &interaction.daily.files.addremove; --> The <command 12.199 + role="hg-cmd">hg commit</command> command also provides a 12.200 + <option role="hg-opt-commit">-A</option> option that performs 12.201 + this same add-and-remove, immediately followed by a commit. 12.202 + <!-- &interaction.daily.files.commit-addremove; --></para> 12.203 + 12.204 + </sect2> 12.205 + </sect1> 12.206 + <sect1> 12.207 + <title>Copying files</title> 12.208 + 12.209 + <para>Mercurial provides a <command role="hg-cmd">hg 12.210 + copy</command> command that lets you make a new copy of a 12.211 + file. When you copy a file using this command, Mercurial makes 12.212 + a record of the fact that the new file is a copy of the original 12.213 + file. It treats these copied files specially when you merge 12.214 + your work with someone else's.</para> 12.215 + 12.216 + <sect2> 12.217 + <title>The results of copying during a merge</title> 12.218 + 12.219 + <para>What happens during a merge is that changes 12.220 + <quote>follow</quote> a copy. To best illustrate what this 12.221 + means, let's create an example. We'll start with the usual 12.222 + tiny repository that contains a single file. <!-- 12.223 + &interaction.daily.copy.init; --> We need to do some work in 12.224 + parallel, so that we'll have something to merge. So let's 12.225 + clone our repository. <!-- &interaction.daily.copy.clone; --> 12.226 + Back in our initial repository, let's use the <command 12.227 + role="hg-cmd">hg copy</command> command to make a copy of 12.228 + the first file we created. <!-- &interaction.daily.copy.copy; 12.229 + --></para> 12.230 + 12.231 + <para>If we look at the output of the <command role="hg-cmd">hg 12.232 + status</command> command afterwards, the copied file looks 12.233 + just like a normal added file. <!-- 12.234 + &interaction.daily.copy.status; --> But if we pass the <option 12.235 + role="hg-opt-status">-C</option> option to <command 12.236 + role="hg-cmd">hg status</command>, it prints another line of 12.237 + output: this is the file that our newly-added file was copied 12.238 + <emphasis>from</emphasis>. <!-- 12.239 + &interaction.daily.copy.status-copy; --></para> 12.240 + 12.241 + <para>Now, back in the repository we cloned, let's make a change 12.242 + in parallel. We'll add a line of content to the original file 12.243 + that we created. <!-- &interaction.daily.copy.other; --> Now 12.244 + we have a modified <filename>file</filename> in this 12.245 + repository. When we pull the changes from the first 12.246 + repository, and merge the two heads, Mercurial will propagate 12.247 + the changes that we made locally to <filename>file</filename> 12.248 + into its copy, <filename>new-file</filename>. <!-- 12.249 + &interaction.daily.copy.merge; --></para> 12.250 + 12.251 + </sect2> 12.252 + <sect2 id="sec:daily:why-copy"> 12.253 + <title>Why should changes follow copies?</title> 12.254 + 12.255 + <para>This behaviour, of changes to a file propagating out to 12.256 + copies of the file, might seem esoteric, but in most cases 12.257 + it's highly desirable.</para> 12.258 + 12.259 + <para>First of all, remember that this propagation 12.260 + <emphasis>only</emphasis> happens when you merge. So if you 12.261 + <command role="hg-cmd">hg copy</command> a file, and 12.262 + subsequently modify the original file during the normal course 12.263 + of your work, nothing will happen.</para> 12.264 + 12.265 + <para>The second thing to know is that modifications will only 12.266 + propagate across a copy as long as the repository that you're 12.267 + pulling changes from <emphasis>doesn't know</emphasis> about 12.268 + the copy.</para> 12.269 + 12.270 + <para>The reason that Mercurial does this is as follows. Let's 12.271 + say I make an important bug fix in a source file, and commit 12.272 + my changes. Meanwhile, you've decided to <command 12.273 + role="hg-cmd">hg copy</command> the file in your repository, 12.274 + without knowing about the bug or having seen the fix, and you 12.275 + have started hacking on your copy of the file.</para> 12.276 + 12.277 + <para>If you pulled and merged my changes, and Mercurial 12.278 + <emphasis>didn't</emphasis> propagate changes across copies, 12.279 + your source file would now contain the bug, and unless you 12.280 + remembered to propagate the bug fix by hand, the bug would 12.281 + <emphasis>remain</emphasis> in your copy of the file.</para> 12.282 + 12.283 + <para>By automatically propagating the change that fixed the bug 12.284 + from the original file to the copy, Mercurial prevents this 12.285 + class of problem. To my knowledge, Mercurial is the 12.286 + <emphasis>only</emphasis> revision control system that 12.287 + propagates changes across copies like this.</para> 12.288 + 12.289 + <para>Once your change history has a record that the copy and 12.290 + subsequent merge occurred, there's usually no further need to 12.291 + propagate changes from the original file to the copied file, 12.292 + and that's why Mercurial only propagates changes across copies 12.293 + until this point, and no further.</para> 12.294 + 12.295 + </sect2> 12.296 + <sect2> 12.297 + <title>How to make changes <emphasis>not</emphasis> follow a 12.298 + copy</title> 12.299 + 12.300 + <para>If, for some reason, you decide that this business of 12.301 + automatically propagating changes across copies is not for 12.302 + you, simply use your system's normal file copy command (on 12.303 + Unix-like systems, that's <command>cp</command>) to make a 12.304 + copy of a file, then <command role="hg-cmd">hg add</command> 12.305 + the new copy by hand. Before you do so, though, please do 12.306 + reread section <xref linkend="sec:daily:why-copy"/>, and make 12.307 + an informed 12.308 + decision that this behaviour is not appropriate to your 12.309 + specific case.</para> 12.310 + 12.311 + </sect2> 12.312 + <sect2> 12.313 + <title>Behaviour of the <command role="hg-cmd">hg copy</command> 12.314 + command</title> 12.315 + 12.316 + <para>When you use the <command role="hg-cmd">hg copy</command> 12.317 + command, Mercurial makes a copy of each source file as it 12.318 + currently stands in the working directory. This means that if 12.319 + you make some modifications to a file, then <command 12.320 + role="hg-cmd">hg copy</command> it without first having 12.321 + committed those changes, the new copy will also contain the 12.322 + modifications you have made up until that point. (I find this 12.323 + behaviour a little counterintuitive, which is why I mention it 12.324 + here.)</para> 12.325 + 12.326 + <para>The <command role="hg-cmd">hg copy</command> command acts 12.327 + similarly to the Unix <command>cp</command> command (you can 12.328 + use the <command role="hg-cmd">hg cp</command> alias if you 12.329 + prefer). The last argument is the 12.330 + <emphasis>destination</emphasis>, and all prior arguments are 12.331 + <emphasis>sources</emphasis>. If you pass it a single file as 12.332 + the source, and the destination does not exist, it creates a 12.333 + new file with that name. <!-- &interaction.daily.copy.simple; 12.334 + --> If the destination is a directory, Mercurial copies its 12.335 + sources into that directory. <!-- 12.336 + &interaction.daily.copy.dir-dest; --> Copying a directory is 12.337 + recursive, and preserves the directory structure of the 12.338 + source. <!-- &interaction.daily.copy.dir-src; --> If the 12.339 + source and destination are both directories, the source tree 12.340 + is recreated in the destination directory. <!-- 12.341 + &interaction.daily.copy.dir-src-dest; --></para> 12.342 + 12.343 + <para>As with the <command role="hg-cmd">hg rename</command> 12.344 + command, if you copy a file manually and then want Mercurial 12.345 + to know that you've copied the file, simply use the <option 12.346 + role="hg-opt-copy">--after</option> option to <command 12.347 + role="hg-cmd">hg copy</command>. <!-- 12.348 + &interaction.daily.copy.after; --></para> 12.349 + 12.350 + </sect2> 12.351 + </sect1> 12.352 + <sect1> 12.353 + <title>Renaming files</title> 12.354 + 12.355 + <para>It's rather more common to need to rename a file than to 12.356 + make a copy of it. The reason I discussed the <command 12.357 + role="hg-cmd">hg copy</command> command before talking about 12.358 + renaming files is that Mercurial treats a rename in essentially 12.359 + the same way as a copy. Therefore, knowing what Mercurial does 12.360 + when you copy a file tells you what to expect when you rename a 12.361 + file.</para> 12.362 + 12.363 + <para>When you use the <command role="hg-cmd">hg rename</command> 12.364 + command, Mercurial makes a copy of each source file, then 12.365 + deletes it and marks the file as removed. <!-- 12.366 + &interaction.daily.rename.rename; --> The <command 12.367 + role="hg-cmd">hg status</command> command shows the newly 12.368 + copied file as added, and the copied-from file as removed. <!-- 12.369 + &interaction.daily.rename.status; --> As with the results of a 12.370 + <command role="hg-cmd">hg copy</command>, we must use the 12.371 + <option role="hg-opt-status">-C</option> option to <command 12.372 + role="hg-cmd">hg status</command> to see that the added file 12.373 + is really being tracked by Mercurial as a copy of the original, 12.374 + now removed, file. <!-- &interaction.daily.rename.status-copy; 12.375 + --></para> 12.376 + 12.377 + <para>As with <command role="hg-cmd">hg remove</command> and 12.378 + <command role="hg-cmd">hg copy</command>, you can tell Mercurial 12.379 + about a rename after the fact using the <option 12.380 + role="hg-opt-rename">--after</option> option. In most other 12.381 + respects, the behaviour of the <command role="hg-cmd">hg 12.382 + rename</command> command, and the options it accepts, are 12.383 + similar to the <command role="hg-cmd">hg copy</command> 12.384 + command.</para> 12.385 + 12.386 + <sect2> 12.387 + <title>Renaming files and merging changes</title> 12.388 + 12.389 + <para>Since Mercurial's rename is implemented as 12.390 + copy-and-remove, the same propagation of changes happens when 12.391 + you merge after a rename as after a copy.</para> 12.392 + 12.393 + <para>If I modify a file, and you rename it to a new name, and 12.394 + then we merge our respective changes, my modifications to the 12.395 + file under its original name will be propagated into the file 12.396 + under its new name. (This is something you might expect to 12.397 + <quote>simply work,</quote> but not all revision control 12.398 + systems actually do this.)</para> 12.399 + 12.400 + <para>Whereas having changes follow a copy is a feature where 12.401 + you can perhaps nod and say <quote>yes, that might be 12.402 + useful,</quote> it should be clear that having them follow a 12.403 + rename is definitely important. Without this facility, it 12.404 + would simply be too easy for changes to become orphaned when 12.405 + files are renamed.</para> 12.406 + 12.407 + </sect2> 12.408 + <sect2> 12.409 + <title>Divergent renames and merging</title> 12.410 + 12.411 + <para>The case of diverging names occurs when two developers 12.412 + start with a file&emdash;let's call it 12.413 + <filename>foo</filename>&emdash;in their respective 12.414 + repositories.</para> 12.415 + 12.416 + <para><!-- &interaction.rename.divergent.clone; --> Anne renames 12.417 + the file to <filename>bar</filename>. <!-- 12.418 + &interaction.rename.divergent.rename.anne; --> Meanwhile, Bob 12.419 + renames it to <filename>quux</filename>. <!-- 12.420 + &interaction.rename.divergent.rename.bob; --></para> 12.421 + 12.422 + <para>I like to think of this as a conflict because each 12.423 + developer has expressed different intentions about what the 12.424 + file ought to be named.</para> 12.425 + 12.426 + <para>What do you think should happen when they merge their 12.427 + work? Mercurial's actual behaviour is that it always preserves 12.428 + <emphasis>both</emphasis> names when it merges changesets that 12.429 + contain divergent renames. <!-- 12.430 + &interaction.rename.divergent.merge; --></para> 12.431 + 12.432 + <para>Notice that Mercurial does warn about the divergent 12.433 + renames, but it leaves it up to you to do something about the 12.434 + divergence after the merge.</para> 12.435 + 12.436 + </sect2> 12.437 + <sect2> 12.438 + <title>Convergent renames and merging</title> 12.439 + 12.440 + <para>Another kind of rename conflict occurs when two people 12.441 + choose to rename different <emphasis>source</emphasis> files 12.442 + to the same <emphasis>destination</emphasis>. In this case, 12.443 + Mercurial runs its normal merge machinery, and lets you guide 12.444 + it to a suitable resolution.</para> 12.445 + 12.446 + </sect2> 12.447 + <sect2> 12.448 + <title>Other name-related corner cases</title> 12.449 + 12.450 + <para>Mercurial has a longstanding bug in which it fails to 12.451 + handle a merge where one side has a file with a given name, 12.452 + while another has a directory with the same name. This is 12.453 + documented as <ulink role="hg-bug" 12.454 + url="http://www.selenic.com/mercurial/bts/issue29">issue 12.455 + 29</ulink>. <!-- &interaction.issue29.go; --></para> 12.456 + 12.457 + </sect2> 12.458 + </sect1> 12.459 + <sect1> 12.460 + <title>Recovering from mistakes</title> 12.461 + 12.462 + <para>Mercurial has some useful commands that will help you to 12.463 + recover from some common mistakes.</para> 12.464 + 12.465 + <para>The <command role="hg-cmd">hg revert</command> command lets 12.466 + you undo changes that you have made to your working directory. 12.467 + For example, if you <command role="hg-cmd">hg add</command> a 12.468 + file by accident, just run <command role="hg-cmd">hg 12.469 + revert</command> with the name of the file you added, and 12.470 + while the file won't be touched in any way, it won't be tracked 12.471 + for adding by Mercurial any longer, either. You can also use 12.472 + <command role="hg-cmd">hg revert</command> to get rid of 12.473 + erroneous changes to a file.</para> 12.474 + 12.475 + <para>It's useful to remember that the <command role="hg-cmd">hg 12.476 + revert</command> command is useful for changes that you have 12.477 + not yet committed. Once you've committed a change, if you 12.478 + decide it was a mistake, you can still do something about it, 12.479 + though your options may be more limited.</para> 12.480 + 12.481 + <para>For more information about the <command role="hg-cmd">hg 12.482 + revert</command> command, and details about how to deal with 12.483 + changes you have already committed, see chapter <xref 12.484 + linkend="chap:undo"/>.</para> 12.485 + 12.486 + </sect1> 12.487 +</chapter> 12.488 + 12.489 +<!-- 12.490 +local variables: 12.491 +sgml-parent-document: ("00book.xml" "book" "chapter") 12.492 +end: 12.493 +-->
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/en/ch06-collab.xml Wed Feb 18 00:22:09 2009 -0800 13.3 @@ -0,0 +1,1415 @@ 13.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 13.5 + 13.6 +<chapter id="cha:collab"> 13.7 + <title>Collaborating with other people</title> 13.8 + 13.9 + <para>As a completely decentralised tool, Mercurial doesn't impose 13.10 + any policy on how people ought to work with each other. However, 13.11 + if you're new to distributed revision control, it helps to have 13.12 + some tools and examples in mind when you're thinking about 13.13 + possible workflow models.</para> 13.14 + 13.15 + <sect1> 13.16 + <title>Mercurial's web interface</title> 13.17 + 13.18 + <para>Mercurial has a powerful web interface that provides several 13.19 + useful capabilities.</para> 13.20 + 13.21 + <para>For interactive use, the web interface lets you browse a 13.22 + single repository or a collection of repositories. You can view 13.23 + the history of a repository, examine each change (comments and 13.24 + diffs), and view the contents of each directory and file.</para> 13.25 + 13.26 + <para>Also for human consumption, the web interface provides an 13.27 + RSS feed of the changes in a repository. This lets you 13.28 + <quote>subscribe</quote> to a repository using your favourite 13.29 + feed reader, and be automatically notified of activity in that 13.30 + repository as soon as it happens. I find this capability much 13.31 + more convenient than the model of subscribing to a mailing list 13.32 + to which notifications are sent, as it requires no additional 13.33 + configuration on the part of whoever is serving the 13.34 + repository.</para> 13.35 + 13.36 + <para>The web interface also lets remote users clone a repository, 13.37 + pull changes from it, and (when the server is configured to 13.38 + permit it) push changes back to it. Mercurial's HTTP tunneling 13.39 + protocol aggressively compresses data, so that it works 13.40 + efficiently even over low-bandwidth network connections.</para> 13.41 + 13.42 + <para>The easiest way to get started with the web interface is to 13.43 + use your web browser to visit an existing repository, such as 13.44 + the master Mercurial repository at <ulink 13.45 + url="http://www.selenic.com/repo/hg?style=gitweb">http://www.selenic.com/repo/hg?style=gitweb</ulink>.</para> 13.46 + 13.47 + <para>If you're interested in providing a web interface to your 13.48 + own repositories, Mercurial provides two ways to do this. The 13.49 + first is using the <command role="hg-cmd">hg serve</command> 13.50 + command, which is best suited to short-term 13.51 + <quote>lightweight</quote> serving. See section <xref 13.52 + linkend="sec:collab:serve"/> below for details of how to use 13.53 + this command. If you have a long-lived repository that you'd 13.54 + like to make permanently available, Mercurial has built-in 13.55 + support for the CGI (Common Gateway Interface) standard, which 13.56 + all common web servers support. See section <xref 13.57 + linkend="sec:collab:cgi"/> for details of CGI 13.58 + configuration.</para> 13.59 + 13.60 + </sect1> 13.61 + <sect1> 13.62 + <title>Collaboration models</title> 13.63 + 13.64 + <para>With a suitably flexible tool, making decisions about 13.65 + workflow is much more of a social engineering challenge than a 13.66 + technical one. Mercurial imposes few limitations on how you can 13.67 + structure the flow of work in a project, so it's up to you and 13.68 + your group to set up and live with a model that matches your own 13.69 + particular needs.</para> 13.70 + 13.71 + <sect2> 13.72 + <title>Factors to keep in mind</title> 13.73 + 13.74 + <para>The most important aspect of any model that you must keep 13.75 + in mind is how well it matches the needs and capabilities of 13.76 + the people who will be using it. This might seem 13.77 + self-evident; even so, you still can't afford to forget it for 13.78 + a moment.</para> 13.79 + 13.80 + <para>I once put together a workflow model that seemed to make 13.81 + perfect sense to me, but that caused a considerable amount of 13.82 + consternation and strife within my development team. In spite 13.83 + of my attempts to explain why we needed a complex set of 13.84 + branches, and how changes ought to flow between them, a few 13.85 + team members revolted. Even though they were smart people, 13.86 + they didn't want to pay attention to the constraints we were 13.87 + operating under, or face the consequences of those constraints 13.88 + in the details of the model that I was advocating.</para> 13.89 + 13.90 + <para>Don't sweep foreseeable social or technical problems under 13.91 + the rug. Whatever scheme you put into effect, you should plan 13.92 + for mistakes and problem scenarios. Consider adding automated 13.93 + machinery to prevent, or quickly recover from, trouble that 13.94 + you can anticipate. As an example, if you intend to have a 13.95 + branch with not-for-release changes in it, you'd do well to 13.96 + think early about the possibility that someone might 13.97 + accidentally merge those changes into a release branch. You 13.98 + could avoid this particular problem by writing a hook that 13.99 + prevents changes from being merged from an inappropriate 13.100 + branch.</para> 13.101 + 13.102 + </sect2> 13.103 + <sect2> 13.104 + <title>Informal anarchy</title> 13.105 + 13.106 + <para>I wouldn't suggest an <quote>anything goes</quote> 13.107 + approach as something sustainable, but it's a model that's 13.108 + easy to grasp, and it works perfectly well in a few unusual 13.109 + situations.</para> 13.110 + 13.111 + <para>As one example, many projects have a loose-knit group of 13.112 + collaborators who rarely physically meet each other. Some 13.113 + groups like to overcome the isolation of working at a distance 13.114 + by organising occasional <quote>sprints</quote>. In a sprint, 13.115 + a number of people get together in a single location (a 13.116 + company's conference room, a hotel meeting room, that kind of 13.117 + place) and spend several days more or less locked in there, 13.118 + hacking intensely on a handful of projects.</para> 13.119 + 13.120 + <para>A sprint is the perfect place to use the <command 13.121 + role="hg-cmd">hg serve</command> command, since <command 13.122 + role="hg-cmd">hg serve</command> does not requires any fancy 13.123 + server infrastructure. You can get started with <command 13.124 + role="hg-cmd">hg serve</command> in moments, by reading 13.125 + section <xref linkend="sec:collab:serve"/> below. Then simply 13.126 + tell 13.127 + the person next to you that you're running a server, send the 13.128 + URL to them in an instant message, and you immediately have a 13.129 + quick-turnaround way to work together. They can type your URL 13.130 + into their web browser and quickly review your changes; or 13.131 + they can pull a bugfix from you and verify it; or they can 13.132 + clone a branch containing a new feature and try it out.</para> 13.133 + 13.134 + <para>The charm, and the problem, with doing things in an ad hoc 13.135 + fashion like this is that only people who know about your 13.136 + changes, and where they are, can see them. Such an informal 13.137 + approach simply doesn't scale beyond a handful people, because 13.138 + each individual needs to know about $n$ different repositories 13.139 + to pull from.</para> 13.140 + 13.141 + </sect2> 13.142 + <sect2> 13.143 + <title>A single central repository</title> 13.144 + 13.145 + <para>For smaller projects migrating from a centralised revision 13.146 + control tool, perhaps the easiest way to get started is to 13.147 + have changes flow through a single shared central repository. 13.148 + This is also the most common <quote>building block</quote> for 13.149 + more ambitious workflow schemes.</para> 13.150 + 13.151 + <para>Contributors start by cloning a copy of this repository. 13.152 + They can pull changes from it whenever they need to, and some 13.153 + (perhaps all) developers have permission to push a change back 13.154 + when they're ready for other people to see it.</para> 13.155 + 13.156 + <para>Under this model, it can still often make sense for people 13.157 + to pull changes directly from each other, without going 13.158 + through the central repository. Consider a case in which I 13.159 + have a tentative bug fix, but I am worried that if I were to 13.160 + publish it to the central repository, it might subsequently 13.161 + break everyone else's trees as they pull it. To reduce the 13.162 + potential for damage, I can ask you to clone my repository 13.163 + into a temporary repository of your own and test it. This 13.164 + lets us put off publishing the potentially unsafe change until 13.165 + it has had a little testing.</para> 13.166 + 13.167 + <para>In this kind of scenario, people usually use the 13.168 + <command>ssh</command> protocol to securely push changes to 13.169 + the central repository, as documented in section <xref 13.170 + linkend="sec:collab:ssh"/>. It's also 13.171 + usual to publish a read-only copy of the repository over HTTP 13.172 + using CGI, as in section <xref linkend="sec:collab:cgi"/>. 13.173 + Publishing over HTTP 13.174 + satisfies the needs of people who don't have push access, and 13.175 + those who want to use web browsers to browse the repository's 13.176 + history.</para> 13.177 + 13.178 + </sect2> 13.179 + <sect2> 13.180 + <title>Working with multiple branches</title> 13.181 + 13.182 + <para>Projects of any significant size naturally tend to make 13.183 + progress on several fronts simultaneously. In the case of 13.184 + software, it's common for a project to go through periodic 13.185 + official releases. A release might then go into 13.186 + <quote>maintenance mode</quote> for a while after its first 13.187 + publication; maintenance releases tend to contain only bug 13.188 + fixes, not new features. In parallel with these maintenance 13.189 + releases, one or more future releases may be under 13.190 + development. People normally use the word 13.191 + <quote>branch</quote> to refer to one of these many slightly 13.192 + different directions in which development is 13.193 + proceeding.</para> 13.194 + 13.195 + <para>Mercurial is particularly well suited to managing a number 13.196 + of simultaneous, but not identical, branches. Each 13.197 + <quote>development direction</quote> can live in its own 13.198 + central repository, and you can merge changes from one to 13.199 + another as the need arises. Because repositories are 13.200 + independent of each other, unstable changes in a development 13.201 + branch will never affect a stable branch unless someone 13.202 + explicitly merges those changes in.</para> 13.203 + 13.204 + <para>Here's an example of how this can work in practice. Let's 13.205 + say you have one <quote>main branch</quote> on a central 13.206 + server. <!-- &interaction.branching.init; --> People clone it, 13.207 + make changes locally, test them, and push them back.</para> 13.208 + 13.209 + <para>Once the main branch reaches a release milestone, you can 13.210 + use the <command role="hg-cmd">hg tag</command> command to 13.211 + give a permanent name to the milestone revision. <!-- 13.212 + &interaction.branching.tag; --> Let's say some ongoing 13.213 + development occurs on the main branch. <!-- 13.214 + &interaction.branching.main; --> Using the tag that was 13.215 + recorded at the milestone, people who clone that repository at 13.216 + any time in the future can use <command role="hg-cmd">hg 13.217 + update</command> to get a copy of the working directory 13.218 + exactly as it was when that tagged revision was committed. 13.219 + <!-- &interaction.branching.update; --></para> 13.220 + 13.221 + <para>In addition, immediately after the main branch is tagged, 13.222 + someone can then clone the main branch on the server to a new 13.223 + <quote>stable</quote> branch, also on the server. <!-- 13.224 + &interaction.branching.clone; --></para> 13.225 + 13.226 + <para>Someone who needs to make a change to the stable branch 13.227 + can then clone <emphasis>that</emphasis> repository, make 13.228 + their changes, commit, and push their changes back there. <!-- 13.229 + &interaction.branching.stable; --> Because Mercurial 13.230 + repositories are independent, and Mercurial doesn't move 13.231 + changes around automatically, the stable and main branches are 13.232 + <emphasis>isolated</emphasis> from each other. The changes 13.233 + that you made on the main branch don't <quote>leak</quote> to 13.234 + the stable branch, and vice versa.</para> 13.235 + 13.236 + <para>You'll often want all of your bugfixes on the stable 13.237 + branch to show up on the main branch, too. Rather than 13.238 + rewrite a bugfix on the main branch, you can simply pull and 13.239 + merge changes from the stable to the main branch, and 13.240 + Mercurial will bring those bugfixes in for you. <!-- 13.241 + &interaction.branching.merge; --> The main branch will still 13.242 + contain changes that are not on the stable branch, but it will 13.243 + also contain all of the bugfixes from the stable branch. The 13.244 + stable branch remains unaffected by these changes.</para> 13.245 + 13.246 + </sect2> 13.247 + <sect2> 13.248 + <title>Feature branches</title> 13.249 + 13.250 + <para>For larger projects, an effective way to manage change is 13.251 + to break up a team into smaller groups. Each group has a 13.252 + shared branch of its own, cloned from a single 13.253 + <quote>master</quote> branch used by the entire project. 13.254 + People working on an individual branch are typically quite 13.255 + isolated from developments on other branches.</para> 13.256 + 13.257 + <informalfigure id="fig:collab:feature-branches"> 13.258 + <mediaobject><imageobject><imagedata 13.259 + fileref="feature-branches"/></imageobject><textobject><phrase>XXX 13.260 + add text</phrase></textobject><caption><para>Feature 13.261 + branches</para></caption></mediaobject> 13.262 + </informalfigure> 13.263 + 13.264 + <para>When a particular feature is deemed to be in suitable 13.265 + shape, someone on that feature team pulls and merges from the 13.266 + master branch into the feature branch, then pushes back up to 13.267 + the master branch.</para> 13.268 + 13.269 + </sect2> 13.270 + <sect2> 13.271 + <title>The release train</title> 13.272 + 13.273 + <para>Some projects are organised on a <quote>train</quote> 13.274 + basis: a release is scheduled to happen every few months, and 13.275 + whatever features are ready when the <quote>train</quote> is 13.276 + ready to leave are allowed in.</para> 13.277 + 13.278 + <para>This model resembles working with feature branches. The 13.279 + difference is that when a feature branch misses a train, 13.280 + someone on the feature team pulls and merges the changes that 13.281 + went out on that train release into the feature branch, and 13.282 + the team continues its work on top of that release so that 13.283 + their feature can make the next release.</para> 13.284 + 13.285 + </sect2> 13.286 + <sect2> 13.287 + <title>The Linux kernel model</title> 13.288 + 13.289 + <para>The development of the Linux kernel has a shallow 13.290 + hierarchical structure, surrounded by a cloud of apparent 13.291 + chaos. Because most Linux developers use 13.292 + <command>git</command>, a distributed revision control tool 13.293 + with capabilities similar to Mercurial, it's useful to 13.294 + describe the way work flows in that environment; if you like 13.295 + the ideas, the approach translates well across tools.</para> 13.296 + 13.297 + <para>At the center of the community sits Linus Torvalds, the 13.298 + creator of Linux. He publishes a single source repository 13.299 + that is considered the <quote>authoritative</quote> current 13.300 + tree by the entire developer community. Anyone can clone 13.301 + Linus's tree, but he is very choosy about whose trees he pulls 13.302 + from.</para> 13.303 + 13.304 + <para>Linus has a number of <quote>trusted lieutenants</quote>. 13.305 + As a general rule, he pulls whatever changes they publish, in 13.306 + most cases without even reviewing those changes. Some of 13.307 + those lieutenants are generally agreed to be 13.308 + <quote>maintainers</quote>, responsible for specific 13.309 + subsystems within the kernel. If a random kernel hacker wants 13.310 + to make a change to a subsystem that they want to end up in 13.311 + Linus's tree, they must find out who the subsystem's 13.312 + maintainer is, and ask that maintainer to take their change. 13.313 + If the maintainer reviews their changes and agrees to take 13.314 + them, they'll pass them along to Linus in due course.</para> 13.315 + 13.316 + <para>Individual lieutenants have their own approaches to 13.317 + reviewing, accepting, and publishing changes; and for deciding 13.318 + when to feed them to Linus. In addition, there are several 13.319 + well known branches that people use for different purposes. 13.320 + For example, a few people maintain <quote>stable</quote> 13.321 + repositories of older versions of the kernel, to which they 13.322 + apply critical fixes as needed. Some maintainers publish 13.323 + multiple trees: one for experimental changes; one for changes 13.324 + that they are about to feed upstream; and so on. Others just 13.325 + publish a single tree.</para> 13.326 + 13.327 + <para>This model has two notable features. The first is that 13.328 + it's <quote>pull only</quote>. You have to ask, convince, or 13.329 + beg another developer to take a change from you, because there 13.330 + are almost no trees to which more than one person can push, 13.331 + and there's no way to push changes into a tree that someone 13.332 + else controls.</para> 13.333 + 13.334 + <para>The second is that it's based on reputation and acclaim. 13.335 + If you're an unknown, Linus will probably ignore changes from 13.336 + you without even responding. But a subsystem maintainer will 13.337 + probably review them, and will likely take them if they pass 13.338 + their criteria for suitability. The more <quote>good</quote> 13.339 + changes you contribute to a maintainer, the more likely they 13.340 + are to trust your judgment and accept your changes. If you're 13.341 + well-known and maintain a long-lived branch for something 13.342 + Linus hasn't yet accepted, people with similar interests may 13.343 + pull your changes regularly to keep up with your work.</para> 13.344 + 13.345 + <para>Reputation and acclaim don't necessarily cross subsystem 13.346 + or <quote>people</quote> boundaries. If you're a respected 13.347 + but specialised storage hacker, and you try to fix a 13.348 + networking bug, that change will receive a level of scrutiny 13.349 + from a network maintainer comparable to a change from a 13.350 + complete stranger.</para> 13.351 + 13.352 + <para>To people who come from more orderly project backgrounds, 13.353 + the comparatively chaotic Linux kernel development process 13.354 + often seems completely insane. It's subject to the whims of 13.355 + individuals; people make sweeping changes whenever they deem 13.356 + it appropriate; and the pace of development is astounding. 13.357 + And yet Linux is a highly successful, well-regarded piece of 13.358 + software.</para> 13.359 + 13.360 + </sect2> 13.361 + <sect2> 13.362 + <title>Pull-only versus shared-push collaboration</title> 13.363 + 13.364 + <para>A perpetual source of heat in the open source community is 13.365 + whether a development model in which people only ever pull 13.366 + changes from others is <quote>better than</quote> one in which 13.367 + multiple people can push changes to a shared 13.368 + repository.</para> 13.369 + 13.370 + <para>Typically, the backers of the shared-push model use tools 13.371 + that actively enforce this approach. If you're using a 13.372 + centralised revision control tool such as Subversion, there's 13.373 + no way to make a choice over which model you'll use: the tool 13.374 + gives you shared-push, and if you want to do anything else, 13.375 + you'll have to roll your own approach on top (such as applying 13.376 + a patch by hand).</para> 13.377 + 13.378 + <para>A good distributed revision control tool, such as 13.379 + Mercurial, will support both models. You and your 13.380 + collaborators can then structure how you work together based 13.381 + on your own needs and preferences, not on what contortions 13.382 + your tools force you into.</para> 13.383 + 13.384 + </sect2> 13.385 + <sect2> 13.386 + <title>Where collaboration meets branch management</title> 13.387 + 13.388 + <para>Once you and your team set up some shared repositories and 13.389 + start propagating changes back and forth between local and 13.390 + shared repos, you begin to face a related, but slightly 13.391 + different challenge: that of managing the multiple directions 13.392 + in which your team may be moving at once. Even though this 13.393 + subject is intimately related to how your team collaborates, 13.394 + it's dense enough to merit treatment of its own, in chapter 13.395 + <xref linkend="chap:branch"/>.</para> 13.396 + 13.397 + </sect2> 13.398 + </sect1> 13.399 + <sect1> 13.400 + <title>The technical side of sharing</title> 13.401 + 13.402 + <para>The remainder of this chapter is devoted to the question of 13.403 + serving data to your collaborators.</para> 13.404 + 13.405 + </sect1> 13.406 + <sect1 id="sec:collab:serve"> 13.407 + <title>Informal sharing with <command role="hg-cmd">hg 13.408 + serve</command></title> 13.409 + 13.410 + <para>Mercurial's <command role="hg-cmd">hg serve</command> 13.411 + command is wonderfully suited to small, tight-knit, and 13.412 + fast-paced group environments. It also provides a great way to 13.413 + get a feel for using Mercurial commands over a network.</para> 13.414 + 13.415 + <para>Run <command role="hg-cmd">hg serve</command> inside a 13.416 + repository, and in under a second it will bring up a specialised 13.417 + HTTP server; this will accept connections from any client, and 13.418 + serve up data for that repository until you terminate it. 13.419 + Anyone who knows the URL of the server you just started, and can 13.420 + talk to your computer over the network, can then use a web 13.421 + browser or Mercurial to read data from that repository. A URL 13.422 + for a <command role="hg-cmd">hg serve</command> instance running 13.423 + on a laptop is likely to look something like 13.424 + <literal>http://my-laptop.local:8000/</literal>.</para> 13.425 + 13.426 + <para>The <command role="hg-cmd">hg serve</command> command is 13.427 + <emphasis>not</emphasis> a general-purpose web server. It can do 13.428 + only two things:</para> 13.429 + <itemizedlist> 13.430 + <listitem><para>Allow people to browse the history of the 13.431 + repository it's serving, from their normal web 13.432 + browsers.</para> 13.433 + </listitem> 13.434 + <listitem><para>Speak Mercurial's wire protocol, so that people 13.435 + can <command role="hg-cmd">hg clone</command> or <command 13.436 + role="hg-cmd">hg pull</command> changes from that 13.437 + repository.</para> 13.438 + </listitem></itemizedlist> 13.439 + <para>In particular, <command role="hg-cmd">hg serve</command> 13.440 + won't allow remote users to <emphasis>modify</emphasis> your 13.441 + repository. It's intended for read-only use.</para> 13.442 + 13.443 + <para>If you're getting started with Mercurial, there's nothing to 13.444 + prevent you from using <command role="hg-cmd">hg serve</command> 13.445 + to serve up a repository on your own computer, then use commands 13.446 + like <command role="hg-cmd">hg clone</command>, <command 13.447 + role="hg-cmd">hg incoming</command>, and so on to talk to that 13.448 + server as if the repository was hosted remotely. This can help 13.449 + you to quickly get acquainted with using commands on 13.450 + network-hosted repositories.</para> 13.451 + 13.452 + <sect2> 13.453 + <title>A few things to keep in mind</title> 13.454 + 13.455 + <para>Because it provides unauthenticated read access to all 13.456 + clients, you should only use <command role="hg-cmd">hg 13.457 + serve</command> in an environment where you either don't 13.458 + care, or have complete control over, who can access your 13.459 + network and pull data from your repository.</para> 13.460 + 13.461 + <para>The <command role="hg-cmd">hg serve</command> command 13.462 + knows nothing about any firewall software you might have 13.463 + installed on your system or network. It cannot detect or 13.464 + control your firewall software. If other people are unable to 13.465 + talk to a running <command role="hg-cmd">hg serve</command> 13.466 + instance, the second thing you should do 13.467 + (<emphasis>after</emphasis> you make sure that they're using 13.468 + the correct URL) is check your firewall configuration.</para> 13.469 + 13.470 + <para>By default, <command role="hg-cmd">hg serve</command> 13.471 + listens for incoming connections on port 8000. If another 13.472 + process is already listening on the port you want to use, you 13.473 + can specify a different port to listen on using the <option 13.474 + role="hg-opt-serve">-p</option> option.</para> 13.475 + 13.476 + <para>Normally, when <command role="hg-cmd">hg serve</command> 13.477 + starts, it prints no output, which can be a bit unnerving. If 13.478 + you'd like to confirm that it is indeed running correctly, and 13.479 + find out what URL you should send to your collaborators, start 13.480 + it with the <option role="hg-opt-global">-v</option> 13.481 + option.</para> 13.482 + 13.483 + </sect2> 13.484 + </sect1> 13.485 + <sect1 id="sec:collab:ssh"> 13.486 + <title>Using the Secure Shell (ssh) protocol</title> 13.487 + 13.488 + <para>You can pull and push changes securely over a network 13.489 + connection using the Secure Shell (<literal>ssh</literal>) 13.490 + protocol. To use this successfully, you may have to do a little 13.491 + bit of configuration on the client or server sides.</para> 13.492 + 13.493 + <para>If you're not familiar with ssh, it's a network protocol 13.494 + that lets you securely communicate with another computer. To 13.495 + use it with Mercurial, you'll be setting up one or more user 13.496 + accounts on a server so that remote users can log in and execute 13.497 + commands.</para> 13.498 + 13.499 + <para>(If you <emphasis>are</emphasis> familiar with ssh, you'll 13.500 + probably find some of the material that follows to be elementary 13.501 + in nature.)</para> 13.502 + 13.503 + <sect2> 13.504 + <title>How to read and write ssh URLs</title> 13.505 + 13.506 + <para>An ssh URL tends to look like this:</para> 13.507 + <programlisting>ssh://bos@hg.serpentine.com:22/hg/hgbook</programlisting> 13.508 + <orderedlist> 13.509 + <listitem><para>The <quote><literal>ssh://</literal></quote> 13.510 + part tells Mercurial to use the ssh protocol.</para> 13.511 + </listitem> 13.512 + <listitem><para>The <quote><literal>bos@</literal></quote> 13.513 + component indicates what username to log into the server 13.514 + as. You can leave this out if the remote username is the 13.515 + same as your local username.</para> 13.516 + </listitem> 13.517 + <listitem><para>The 13.518 + <quote><literal>hg.serpentine.com</literal></quote> gives 13.519 + the hostname of the server to log into.</para> 13.520 + </listitem> 13.521 + <listitem><para>The <quote>:22</quote> identifies the port 13.522 + number to connect to the server on. The default port is 13.523 + 22, so you only need to specify this part if you're 13.524 + <emphasis>not</emphasis> using port 22.</para> 13.525 + </listitem> 13.526 + <listitem><para>The remainder of the URL is the local path to 13.527 + the repository on the server.</para> 13.528 + </listitem></orderedlist> 13.529 + 13.530 + <para>There's plenty of scope for confusion with the path 13.531 + component of ssh URLs, as there is no standard way for tools 13.532 + to interpret it. Some programs behave differently than others 13.533 + when dealing with these paths. This isn't an ideal situation, 13.534 + but it's unlikely to change. Please read the following 13.535 + paragraphs carefully.</para> 13.536 + 13.537 + <para>Mercurial treats the path to a repository on the server as 13.538 + relative to the remote user's home directory. For example, if 13.539 + user <literal>foo</literal> on the server has a home directory 13.540 + of <filename class="directory">/home/foo</filename>, then an 13.541 + ssh URL that contains a path component of <filename 13.542 + class="directory">bar</filename> <emphasis>really</emphasis> 13.543 + refers to the directory <filename 13.544 + class="directory">/home/foo/bar</filename>.</para> 13.545 + 13.546 + <para>If you want to specify a path relative to another user's 13.547 + home directory, you can use a path that starts with a tilde 13.548 + character followed by the user's name (let's call them 13.549 + <literal>otheruser</literal>), like this.</para> 13.550 + <programlisting>ssh://server/~otheruser/hg/repo</programlisting> 13.551 + 13.552 + <para>And if you really want to specify an 13.553 + <emphasis>absolute</emphasis> path on the server, begin the 13.554 + path component with two slashes, as in this example.</para> 13.555 + <programlisting>ssh://server//absolute/path</programlisting> 13.556 + 13.557 + </sect2> 13.558 + <sect2> 13.559 + <title>Finding an ssh client for your system</title> 13.560 + 13.561 + <para>Almost every Unix-like system comes with OpenSSH 13.562 + preinstalled. If you're using such a system, run 13.563 + <literal>which ssh</literal> to find out if the 13.564 + <command>ssh</command> command is installed (it's usually in 13.565 + <filename class="directory">/usr/bin</filename>). In the 13.566 + unlikely event that it isn't present, take a look at your 13.567 + system documentation to figure out how to install it.</para> 13.568 + 13.569 + <para>On Windows, you'll first need to download a suitable ssh 13.570 + client. There are two alternatives.</para> 13.571 + <itemizedlist> 13.572 + <listitem><para>Simon Tatham's excellent PuTTY package 13.573 + <citation>web:putty</citation> provides a complete suite 13.574 + of ssh client commands.</para> 13.575 + </listitem> 13.576 + <listitem><para>If you have a high tolerance for pain, you can 13.577 + use the Cygwin port of OpenSSH.</para> 13.578 + </listitem></itemizedlist> 13.579 + <para>In either case, you'll need to edit your \hgini\ file to 13.580 + tell Mercurial where to find the actual client command. For 13.581 + example, if you're using PuTTY, you'll need to use the 13.582 + <command>plink</command> command as a command-line ssh 13.583 + client.</para> 13.584 + <programlisting>[ui] ssh = C:/path/to/plink.exe -ssh -i 13.585 + "C:/path/to/my/private/key"</programlisting> 13.586 + 13.587 + <note> 13.588 + <para> The path to <command>plink</command> shouldn't contain 13.589 + any whitespace characters, or Mercurial may not be able to 13.590 + run it correctly (so putting it in <filename 13.591 + class="directory">C:\\Program Files</filename> is probably 13.592 + not a good idea).</para> 13.593 + </note> 13.594 + 13.595 + </sect2> 13.596 + <sect2> 13.597 + <title>Generating a key pair</title> 13.598 + 13.599 + <para>To avoid the need to repetitively type a password every 13.600 + time you need to use your ssh client, I recommend generating a 13.601 + key pair. On a Unix-like system, the 13.602 + <command>ssh-keygen</command> command will do the trick. On 13.603 + Windows, if you're using PuTTY, the 13.604 + <command>puttygen</command> command is what you'll 13.605 + need.</para> 13.606 + 13.607 + <para>When you generate a key pair, it's usually 13.608 + <emphasis>highly</emphasis> advisable to protect it with a 13.609 + passphrase. (The only time that you might not want to do this 13.610 + is when you're using the ssh protocol for automated tasks on a 13.611 + secure network.)</para> 13.612 + 13.613 + <para>Simply generating a key pair isn't enough, however. 13.614 + You'll need to add the public key to the set of authorised 13.615 + keys for whatever user you're logging in remotely as. For 13.616 + servers using OpenSSH (the vast majority), this will mean 13.617 + adding the public key to a list in a file called <filename 13.618 + role="special">authorized_keys</filename> in their <filename 13.619 + role="special" class="directory">.ssh</filename> 13.620 + directory.</para> 13.621 + 13.622 + <para>On a Unix-like system, your public key will have a 13.623 + <filename>.pub</filename> extension. If you're using 13.624 + <command>puttygen</command> on Windows, you can save the 13.625 + public key to a file of your choosing, or paste it from the 13.626 + window it's displayed in straight into the <filename 13.627 + role="special">authorized_keys</filename> file.</para> 13.628 + 13.629 + </sect2> 13.630 + <sect2> 13.631 + <title>Using an authentication agent</title> 13.632 + 13.633 + <para>An authentication agent is a daemon that stores 13.634 + passphrases in memory (so it will forget passphrases if you 13.635 + log out and log back in again). An ssh client will notice if 13.636 + it's running, and query it for a passphrase. If there's no 13.637 + authentication agent running, or the agent doesn't store the 13.638 + necessary passphrase, you'll have to type your passphrase 13.639 + every time Mercurial tries to communicate with a server on 13.640 + your behalf (e.g. whenever you pull or push changes).</para> 13.641 + 13.642 + <para>The downside of storing passphrases in an agent is that 13.643 + it's possible for a well-prepared attacker to recover the 13.644 + plain text of your passphrases, in some cases even if your 13.645 + system has been power-cycled. You should make your own 13.646 + judgment as to whether this is an acceptable risk. It 13.647 + certainly saves a lot of repeated typing.</para> 13.648 + 13.649 + <para>On Unix-like systems, the agent is called 13.650 + <command>ssh-agent</command>, and it's often run automatically 13.651 + for you when you log in. You'll need to use the 13.652 + <command>ssh-add</command> command to add passphrases to the 13.653 + agent's store. On Windows, if you're using PuTTY, the 13.654 + <command>pageant</command> command acts as the agent. It adds 13.655 + an icon to your system tray that will let you manage stored 13.656 + passphrases.</para> 13.657 + 13.658 + </sect2> 13.659 + <sect2> 13.660 + <title>Configuring the server side properly</title> 13.661 + 13.662 + <para>Because ssh can be fiddly to set up if you're new to it, 13.663 + there's a variety of things that can go wrong. Add Mercurial 13.664 + on top, and there's plenty more scope for head-scratching. 13.665 + Most of these potential problems occur on the server side, not 13.666 + the client side. The good news is that once you've gotten a 13.667 + configuration working, it will usually continue to work 13.668 + indefinitely.</para> 13.669 + 13.670 + <para>Before you try using Mercurial to talk to an ssh server, 13.671 + it's best to make sure that you can use the normal 13.672 + <command>ssh</command> or <command>putty</command> command to 13.673 + talk to the server first. If you run into problems with using 13.674 + these commands directly, Mercurial surely won't work. Worse, 13.675 + it will obscure the underlying problem. Any time you want to 13.676 + debug ssh-related Mercurial problems, you should drop back to 13.677 + making sure that plain ssh client commands work first, 13.678 + <emphasis>before</emphasis> you worry about whether there's a 13.679 + problem with Mercurial.</para> 13.680 + 13.681 + <para>The first thing to be sure of on the server side is that 13.682 + you can actually log in from another machine at all. If you 13.683 + can't use <command>ssh</command> or <command>putty</command> 13.684 + to log in, the error message you get may give you a few hints 13.685 + as to what's wrong. The most common problems are as 13.686 + follows.</para> 13.687 + <itemizedlist> 13.688 + <listitem><para>If you get a <quote>connection refused</quote> 13.689 + error, either there isn't an SSH daemon running on the 13.690 + server at all, or it's inaccessible due to firewall 13.691 + configuration.</para> 13.692 + </listitem> 13.693 + <listitem><para>If you get a <quote>no route to host</quote> 13.694 + error, you either have an incorrect address for the server 13.695 + or a seriously locked down firewall that won't admit its 13.696 + existence at all.</para> 13.697 + </listitem> 13.698 + <listitem><para>If you get a <quote>permission denied</quote> 13.699 + error, you may have mistyped the username on the server, 13.700 + or you could have mistyped your key's passphrase or the 13.701 + remote user's password.</para> 13.702 + </listitem></itemizedlist> 13.703 + <para>In summary, if you're having trouble talking to the 13.704 + server's ssh daemon, first make sure that one is running at 13.705 + all. On many systems it will be installed, but disabled, by 13.706 + default. Once you're done with this step, you should then 13.707 + check that the server's firewall is configured to allow 13.708 + incoming connections on the port the ssh daemon is listening 13.709 + on (usually 22). Don't worry about more exotic possibilities 13.710 + for misconfiguration until you've checked these two 13.711 + first.</para> 13.712 + 13.713 + <para>If you're using an authentication agent on the client side 13.714 + to store passphrases for your keys, you ought to be able to 13.715 + log into the server without being prompted for a passphrase or 13.716 + a password. If you're prompted for a passphrase, there are a 13.717 + few possible culprits.</para> 13.718 + <itemizedlist> 13.719 + <listitem><para>You might have forgotten to use 13.720 + <command>ssh-add</command> or <command>pageant</command> 13.721 + to store the passphrase.</para> 13.722 + </listitem> 13.723 + <listitem><para>You might have stored the passphrase for the 13.724 + wrong key.</para> 13.725 + </listitem></itemizedlist> 13.726 + <para>If you're being prompted for the remote user's password, 13.727 + there are another few possible problems to check.</para> 13.728 + <itemizedlist> 13.729 + <listitem><para>Either the user's home directory or their 13.730 + <filename role="special" class="directory">.ssh</filename> 13.731 + directory might have excessively liberal permissions. As 13.732 + a result, the ssh daemon will not trust or read their 13.733 + <filename role="special">authorized_keys</filename> file. 13.734 + For example, a group-writable home or <filename 13.735 + role="special" class="directory">.ssh</filename> 13.736 + directory will often cause this symptom.</para> 13.737 + </listitem> 13.738 + <listitem><para>The user's <filename 13.739 + role="special">authorized_keys</filename> file may have 13.740 + a problem. If anyone other than the user owns or can write 13.741 + to that file, the ssh daemon will not trust or read 13.742 + it.</para> 13.743 + </listitem></itemizedlist> 13.744 + 13.745 + <para>In the ideal world, you should be able to run the 13.746 + following command successfully, and it should print exactly 13.747 + one line of output, the current date and time.</para> 13.748 + <programlisting>ssh myserver date</programlisting> 13.749 + 13.750 + <para>If, on your server, you have login scripts that print 13.751 + banners or other junk even when running non-interactive 13.752 + commands like this, you should fix them before you continue, 13.753 + so that they only print output if they're run interactively. 13.754 + Otherwise these banners will at least clutter up Mercurial's 13.755 + output. Worse, they could potentially cause problems with 13.756 + running Mercurial commands remotely. Mercurial makes tries to 13.757 + detect and ignore banners in non-interactive 13.758 + <command>ssh</command> sessions, but it is not foolproof. (If 13.759 + you're editing your login scripts on your server, the usual 13.760 + way to see if a login script is running in an interactive 13.761 + shell is to check the return code from the command 13.762 + <literal>tty -s</literal>.)</para> 13.763 + 13.764 + <para>Once you've verified that plain old ssh is working with 13.765 + your server, the next step is to ensure that Mercurial runs on 13.766 + the server. The following command should run 13.767 + successfully:</para> 13.768 + <programlisting>ssh myserver hg version</programlisting> 13.769 + <para>If you see an error message instead of normal <command 13.770 + role="hg-cmd">hg version</command> output, this is usually 13.771 + because you haven't installed Mercurial to <filename 13.772 + class="directory">/usr/bin</filename>. Don't worry if this 13.773 + is the case; you don't need to do that. But you should check 13.774 + for a few possible problems.</para> 13.775 + <itemizedlist> 13.776 + <listitem><para>Is Mercurial really installed on the server at 13.777 + all? I know this sounds trivial, but it's worth 13.778 + checking!</para> 13.779 + </listitem> 13.780 + <listitem><para>Maybe your shell's search path (usually set 13.781 + via the <envar>PATH</envar> environment variable) is 13.782 + simply misconfigured.</para> 13.783 + </listitem> 13.784 + <listitem><para>Perhaps your <envar>PATH</envar> environment 13.785 + variable is only being set to point to the location of the 13.786 + <command>hg</command> executable if the login session is 13.787 + interactive. This can happen if you're setting the path 13.788 + in the wrong shell login script. See your shell's 13.789 + documentation for details.</para> 13.790 + </listitem> 13.791 + <listitem><para>The <envar>PYTHONPATH</envar> environment 13.792 + variable may need to contain the path to the Mercurial 13.793 + Python modules. It might not be set at all; it could be 13.794 + incorrect; or it may be set only if the login is 13.795 + interactive.</para> 13.796 + </listitem></itemizedlist> 13.797 + 13.798 + <para>If you can run <command role="hg-cmd">hg version</command> 13.799 + over an ssh connection, well done! You've got the server and 13.800 + client sorted out. You should now be able to use Mercurial to 13.801 + access repositories hosted by that username on that server. 13.802 + If you run into problems with Mercurial and ssh at this point, 13.803 + try using the <option role="hg-opt-global">--debug</option> 13.804 + option to get a clearer picture of what's going on.</para> 13.805 + 13.806 + </sect2> 13.807 + <sect2> 13.808 + <title>Using compression with ssh</title> 13.809 + 13.810 + <para>Mercurial does not compress data when it uses the ssh 13.811 + protocol, because the ssh protocol can transparently compress 13.812 + data. However, the default behaviour of ssh clients is 13.813 + <emphasis>not</emphasis> to request compression.</para> 13.814 + 13.815 + <para>Over any network other than a fast LAN (even a wireless 13.816 + network), using compression is likely to significantly speed 13.817 + up Mercurial's network operations. For example, over a WAN, 13.818 + someone measured compression as reducing the amount of time 13.819 + required to clone a particularly large repository from 51 13.820 + minutes to 17 minutes.</para> 13.821 + 13.822 + <para>Both <command>ssh</command> and <command>plink</command> 13.823 + accept a <option role="cmd-opt-ssh">-C</option> option which 13.824 + turns on compression. You can easily edit your <filename 13.825 + role="special"> /.hgrc</filename>\ to enable compression for 13.826 + all of Mercurial's uses of the ssh protocol.</para> 13.827 + <programlisting>[ui] ssh = ssh -C</programlisting> 13.828 + 13.829 + <para>If you use <command>ssh</command>, you can configure it to 13.830 + always use compression when talking to your server. To do 13.831 + this, edit your <filename 13.832 + role="special">.ssh/config</filename> file (which may not 13.833 + yet exist), as follows.</para> 13.834 + <programlisting>Host hg Compression yes HostName 13.835 + hg.example.com</programlisting> 13.836 + <para>This defines an alias, <literal>hg</literal>. When you 13.837 + use it on the <command>ssh</command> command line or in a 13.838 + Mercurial <literal>ssh</literal>-protocol URL, it will cause 13.839 + <command>ssh</command> to connect to 13.840 + <literal>hg.example.com</literal> and use compression. This 13.841 + gives you both a shorter name to type and compression, each of 13.842 + which is a good thing in its own right.</para> 13.843 + 13.844 + </sect2> 13.845 + </sect1> 13.846 + <sect1 id="sec:collab:cgi"> 13.847 + <title>Serving over HTTP using CGI</title> 13.848 + 13.849 + <para>Depending on how ambitious you are, configuring Mercurial's 13.850 + CGI interface can take anything from a few moments to several 13.851 + hours.</para> 13.852 + 13.853 + <para>We'll begin with the simplest of examples, and work our way 13.854 + towards a more complex configuration. Even for the most basic 13.855 + case, you're almost certainly going to need to read and modify 13.856 + your web server's configuration.</para> 13.857 + 13.858 + <note> 13.859 + <para> Configuring a web server is a complex, fiddly, and 13.860 + highly system-dependent activity. I can't possibly give you 13.861 + instructions that will cover anything like all of the cases 13.862 + you will encounter. Please use your discretion and judgment in 13.863 + following the sections below. Be prepared to make plenty of 13.864 + mistakes, and to spend a lot of time reading your server's 13.865 + error logs.</para> 13.866 + </note> 13.867 + 13.868 + <sect2> 13.869 + <title>Web server configuration checklist</title> 13.870 + 13.871 + <para>Before you continue, do take a few moments to check a few 13.872 + aspects of your system's setup.</para> 13.873 + 13.874 + <orderedlist> 13.875 + <listitem><para>Do you have a web server installed at all? 13.876 + Mac OS X ships with Apache, but many other systems may not 13.877 + have a web server installed.</para> 13.878 + </listitem> 13.879 + <listitem><para>If you have a web server installed, is it 13.880 + actually running? On most systems, even if one is 13.881 + present, it will be disabled by default.</para> 13.882 + </listitem> 13.883 + <listitem><para>Is your server configured to allow you to run 13.884 + CGI programs in the directory where you plan to do so? 13.885 + Most servers default to explicitly disabling the ability 13.886 + to run CGI programs.</para> 13.887 + </listitem></orderedlist> 13.888 + 13.889 + <para>If you don't have a web server installed, and don't have 13.890 + substantial experience configuring Apache, you should consider 13.891 + using the <literal>lighttpd</literal> web server instead of 13.892 + Apache. Apache has a well-deserved reputation for baroque and 13.893 + confusing configuration. While <literal>lighttpd</literal> is 13.894 + less capable in some ways than Apache, most of these 13.895 + capabilities are not relevant to serving Mercurial 13.896 + repositories. And <literal>lighttpd</literal> is undeniably 13.897 + <emphasis>much</emphasis> easier to get started with than 13.898 + Apache.</para> 13.899 + 13.900 + </sect2> 13.901 + <sect2> 13.902 + <title>Basic CGI configuration</title> 13.903 + 13.904 + <para>On Unix-like systems, it's common for users to have a 13.905 + subdirectory named something like <filename 13.906 + class="directory">public_html</filename> in their home 13.907 + directory, from which they can serve up web pages. A file 13.908 + named <filename>foo</filename> in this directory will be 13.909 + accessible at a URL of the form 13.910 + <literal>http://www.example.com/\ 13.911 + {</literal>username/foo}.</para> 13.912 + 13.913 + <para>To get started, find the <filename 13.914 + role="special">hgweb.cgi</filename> script that should be 13.915 + present in your Mercurial installation. If you can't quickly 13.916 + find a local copy on your system, simply download one from the 13.917 + master Mercurial repository at <ulink 13.918 + url="http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi</ulink>.</para> 13.919 + 13.920 + <para>You'll need to copy this script into your <filename 13.921 + class="directory">public_html</filename> directory, and 13.922 + ensure that it's executable.</para> 13.923 + <programlisting>cp .../hgweb.cgi ~/public_html chmod 755 13.924 + ~/public_html/hgweb.cgi</programlisting> 13.925 + <para>The <literal>755</literal> argument to 13.926 + <command>chmod</command> is a little more general than just 13.927 + making the script executable: it ensures that the script is 13.928 + executable by anyone, and that <quote>group</quote> and 13.929 + <quote>other</quote> write permissions are 13.930 + <emphasis>not</emphasis> set. If you were to leave those 13.931 + write permissions enabled, Apache's <literal>suexec</literal> 13.932 + subsystem would likely refuse to execute the script. In fact, 13.933 + <literal>suexec</literal> also insists that the 13.934 + <emphasis>directory</emphasis> in which the script resides 13.935 + must not be writable by others.</para> 13.936 + <programlisting>chmod 755 ~/public_html</programlisting> 13.937 + 13.938 + <sect3 id="sec:collab:wtf"> 13.939 + <title>What could <emphasis>possibly</emphasis> go 13.940 + wrong?</title> 13.941 + 13.942 + <para>Once you've copied the CGI script into place, go into a 13.943 + web browser, and try to open the URL <ulink 13.944 + url="http://myhostname/ 13.945 + myuser/hgweb.cgi">http://myhostname/ 13.946 + myuser/hgweb.cgi</ulink>, <emphasis>but</emphasis> brace 13.947 + yourself for instant failure. There's a high probability 13.948 + that trying to visit this URL will fail, and there are many 13.949 + possible reasons for this. In fact, you're likely to 13.950 + stumble over almost every one of the possible errors below, 13.951 + so please read carefully. The following are all of the 13.952 + problems I ran into on a system running Fedora 7, with a 13.953 + fresh installation of Apache, and a user account that I 13.954 + created specially to perform this exercise.</para> 13.955 + 13.956 + <para>Your web server may have per-user directories disabled. 13.957 + If you're using Apache, search your config file for a 13.958 + <literal>UserDir</literal> directive. If there's none 13.959 + present, per-user directories will be disabled. If one 13.960 + exists, but its value is <literal>disabled</literal>, then 13.961 + per-user directories will be disabled. Otherwise, the 13.962 + string after <literal>UserDir</literal> gives the name of 13.963 + the subdirectory that Apache will look in under your home 13.964 + directory, for example <filename 13.965 + class="directory">public_html</filename>.</para> 13.966 + 13.967 + <para>Your file access permissions may be too restrictive. 13.968 + The web server must be able to traverse your home directory 13.969 + and directories under your <filename 13.970 + class="directory">public_html</filename> directory, and 13.971 + read files under the latter too. Here's a quick recipe to 13.972 + help you to make your permissions more appropriate.</para> 13.973 + <programlisting>chmod 755 ~ find ~/public_html -type d -print0 13.974 + | xargs -0r chmod 755 find ~/public_html -type f -print0 | 13.975 + xargs -0r chmod 644</programlisting> 13.976 + 13.977 + <para>The other possibility with permissions is that you might 13.978 + get a completely empty window when you try to load the 13.979 + script. In this case, it's likely that your access 13.980 + permissions are \emph{too permissive}. Apache's 13.981 + <literal>suexec</literal> subsystem won't execute a script 13.982 + that's group- or world-writable, for example.</para> 13.983 + 13.984 + <para>Your web server may be configured to disallow execution 13.985 + of CGI programs in your per-user web directory. Here's 13.986 + Apache's default per-user configuration from my Fedora 13.987 + system.</para> 13.988 + <programlisting><Directory /home/*/public_html> 13.989 + AllowOverride FileInfo AuthConfig Limit Options MultiViews 13.990 + Indexes SymLinksIfOwnerMatch IncludesNoExec <Limit GET 13.991 + POST OPTIONS> Order allow,deny Allow from all 13.992 + </Limit> <LimitExcept GET POST OPTIONS> Order 13.993 + deny,allow Deny from all </LimitExcept> 13.994 + </Directory></programlisting> 13.995 + <para>If you find a similar-looking 13.996 + <literal>Directory</literal> group in your Apache 13.997 + configuration, the directive to look at inside it is 13.998 + <literal>Options</literal>. Add <literal>ExecCGI</literal> 13.999 + to the end of this list if it's missing, and restart the web 13.1000 + server.</para> 13.1001 + 13.1002 + <para>If you find that Apache serves you the text of the CGI 13.1003 + script instead of executing it, you may need to either 13.1004 + uncomment (if already present) or add a directive like 13.1005 + this.</para> 13.1006 + <programlisting>AddHandler cgi-script .cgi</programlisting> 13.1007 + 13.1008 + <para>The next possibility is that you might be served with a 13.1009 + colourful Python backtrace claiming that it can't import a 13.1010 + <literal>mercurial</literal>-related module. This is 13.1011 + actually progress! The server is now capable of executing 13.1012 + your CGI script. This error is only likely to occur if 13.1013 + you're running a private installation of Mercurial, instead 13.1014 + of a system-wide version. Remember that the web server runs 13.1015 + the CGI program without any of the environment variables 13.1016 + that you take for granted in an interactive session. If 13.1017 + this error happens to you, edit your copy of <filename 13.1018 + role="special">hgweb.cgi</filename> and follow the 13.1019 + directions inside it to correctly set your 13.1020 + <envar>PYTHONPATH</envar> environment variable.</para> 13.1021 + 13.1022 + <para>Finally, you are <emphasis>certain</emphasis> to by 13.1023 + served with another colourful Python backtrace: this one 13.1024 + will complain that it can't find <filename 13.1025 + class="directory">/path/to/repository</filename>. Edit 13.1026 + your <filename role="special">hgweb.cgi</filename> script 13.1027 + and replace the <filename 13.1028 + class="directory">/path/to/repository</filename> string 13.1029 + with the complete path to the repository you want to serve 13.1030 + up.</para> 13.1031 + 13.1032 + <para>At this point, when you try to reload the page, you 13.1033 + should be presented with a nice HTML view of your 13.1034 + repository's history. Whew!</para> 13.1035 + 13.1036 + </sect3> 13.1037 + <sect3> 13.1038 + <title>Configuring lighttpd</title> 13.1039 + 13.1040 + <para>To be exhaustive in my experiments, I tried configuring 13.1041 + the increasingly popular <literal>lighttpd</literal> web 13.1042 + server to serve the same repository as I described with 13.1043 + Apache above. I had already overcome all of the problems I 13.1044 + outlined with Apache, many of which are not server-specific. 13.1045 + As a result, I was fairly sure that my file and directory 13.1046 + permissions were good, and that my <filename 13.1047 + role="special">hgweb.cgi</filename> script was properly 13.1048 + edited.</para> 13.1049 + 13.1050 + <para>Once I had Apache running, getting 13.1051 + <literal>lighttpd</literal> to serve the repository was a 13.1052 + snap (in other words, even if you're trying to use 13.1053 + <literal>lighttpd</literal>, you should read the Apache 13.1054 + section). I first had to edit the 13.1055 + <literal>mod_access</literal> section of its config file to 13.1056 + enable <literal>mod_cgi</literal> and 13.1057 + <literal>mod_userdir</literal>, both of which were disabled 13.1058 + by default on my system. I then added a few lines to the 13.1059 + end of the config file, to configure these modules.</para> 13.1060 + <programlisting>userdir.path = "public_html" cgi.assign = ( 13.1061 + ".cgi" => "" )</programlisting> 13.1062 + <para>With this done, <literal>lighttpd</literal> ran 13.1063 + immediately for me. If I had configured 13.1064 + <literal>lighttpd</literal> before Apache, I'd almost 13.1065 + certainly have run into many of the same system-level 13.1066 + configuration problems as I did with Apache. However, I 13.1067 + found <literal>lighttpd</literal> to be noticeably easier to 13.1068 + configure than Apache, even though I've used Apache for over 13.1069 + a decade, and this was my first exposure to 13.1070 + <literal>lighttpd</literal>.</para> 13.1071 + 13.1072 + </sect3> 13.1073 + </sect2> 13.1074 + <sect2> 13.1075 + <title>Sharing multiple repositories with one CGI script</title> 13.1076 + 13.1077 + <para>The <filename role="special">hgweb.cgi</filename> script 13.1078 + only lets you publish a single repository, which is an 13.1079 + annoying restriction. If you want to publish more than one 13.1080 + without wracking yourself with multiple copies of the same 13.1081 + script, each with different names, a better choice is to use 13.1082 + the <filename role="special">hgwebdir.cgi</filename> 13.1083 + script.</para> 13.1084 + 13.1085 + <para>The procedure to configure <filename 13.1086 + role="special">hgwebdir.cgi</filename> is only a little more 13.1087 + involved than for <filename 13.1088 + role="special">hgweb.cgi</filename>. First, you must obtain 13.1089 + a copy of the script. If you don't have one handy, you can 13.1090 + download a copy from the master Mercurial repository at <ulink 13.1091 + url="http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi">http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi</ulink>.</para> 13.1092 + 13.1093 + <para>You'll need to copy this script into your <filename 13.1094 + class="directory">public_html</filename> directory, and 13.1095 + ensure that it's executable.</para> 13.1096 + <programlisting>cp .../hgwebdir.cgi ~/public_html chmod 755 13.1097 + ~/public_html ~/public_html/hgwebdir.cgi</programlisting> 13.1098 + <para>With basic configuration out of the way, try to visit 13.1099 + <ulink url="http://myhostname/ 13.1100 + myuser/hgwebdir.cgi">http://myhostname/ 13.1101 + myuser/hgwebdir.cgi</ulink> in your browser. It should 13.1102 + display an empty list of repositories. If you get a blank 13.1103 + window or error message, try walking through the list of 13.1104 + potential problems in section <xref 13.1105 + linkend="sec:collab:wtf"/>.</para> 13.1106 + 13.1107 + <para>The <filename role="special">hgwebdir.cgi</filename> 13.1108 + script relies on an external configuration file. By default, 13.1109 + it searches for a file named <filename 13.1110 + role="special">hgweb.config</filename> in the same directory 13.1111 + as itself. You'll need to create this file, and make it 13.1112 + world-readable. The format of the file is similar to a 13.1113 + Windows <quote>ini</quote> file, as understood by Python's 13.1114 + <literal>ConfigParser</literal> 13.1115 + <citation>web:configparser</citation> module.</para> 13.1116 + 13.1117 + <para>The easiest way to configure <filename 13.1118 + role="special">hgwebdir.cgi</filename> is with a section 13.1119 + named <literal>collections</literal>. This will automatically 13.1120 + publish <emphasis>every</emphasis> repository under the 13.1121 + directories you name. The section should look like 13.1122 + this:</para> 13.1123 + <programlisting>[collections] /my/root = 13.1124 + /my/root</programlisting> 13.1125 + <para>Mercurial interprets this by looking at the directory name 13.1126 + on the <emphasis>right</emphasis> hand side of the 13.1127 + <quote><literal>=</literal></quote> sign; finding repositories 13.1128 + in that directory hierarchy; and using the text on the 13.1129 + <emphasis>left</emphasis> to strip off matching text from the 13.1130 + names it will actually list in the web interface. The 13.1131 + remaining component of a path after this stripping has 13.1132 + occurred is called a <quote>virtual path</quote>.</para> 13.1133 + 13.1134 + <para>Given the example above, if we have a repository whose 13.1135 + local path is <filename 13.1136 + class="directory">/my/root/this/repo</filename>, the CGI 13.1137 + script will strip the leading <filename 13.1138 + class="directory">/my/root</filename> from the name, and 13.1139 + publish the repository with a virtual path of <filename 13.1140 + class="directory">this/repo</filename>. If the base URL for 13.1141 + our CGI script is <ulink url="http://myhostname/ 13.1142 + myuser/hgwebdir.cgi">http://myhostname/ 13.1143 + myuser/hgwebdir.cgi</ulink>, the complete URL for that 13.1144 + repository will be <ulink url="http://myhostname/ 13.1145 + myuser/hgwebdir.cgi/this/repo">http://myhostname/ 13.1146 + myuser/hgwebdir.cgi/this/repo</ulink>.</para> 13.1147 + 13.1148 + <para>If we replace <filename 13.1149 + class="directory">/my/root</filename> on the left hand side 13.1150 + of this example with <filename 13.1151 + class="directory">/my</filename>, then <filename 13.1152 + role="special">hgwebdir.cgi</filename> will only strip off 13.1153 + <filename class="directory">/my</filename> from the repository 13.1154 + name, and will give us a virtual path of <filename 13.1155 + class="directory">root/this/repo</filename> instead of 13.1156 + <filename class="directory">this/repo</filename>.</para> 13.1157 + 13.1158 + <para>The <filename role="special">hgwebdir.cgi</filename> 13.1159 + script will recursively search each directory listed in the 13.1160 + <literal>collections</literal> section of its configuration 13.1161 + file, but it will <literal>not</literal> recurse into the 13.1162 + repositories it finds.</para> 13.1163 + 13.1164 + <para>The <literal>collections</literal> mechanism makes it easy 13.1165 + to publish many repositories in a <quote>fire and 13.1166 + forget</quote> manner. You only need to set up the CGI 13.1167 + script and configuration file one time. Afterwards, you can 13.1168 + publish or unpublish a repository at any time by simply moving 13.1169 + it into, or out of, the directory hierarchy in which you've 13.1170 + configured <filename role="special">hgwebdir.cgi</filename> to 13.1171 + look.</para> 13.1172 + 13.1173 + <sect3> 13.1174 + <title>Explicitly specifying which repositories to 13.1175 + publish</title> 13.1176 + 13.1177 + <para>In addition to the <literal>collections</literal> 13.1178 + mechanism, the <filename 13.1179 + role="special">hgwebdir.cgi</filename> script allows you 13.1180 + to publish a specific list of repositories. To do so, 13.1181 + create a <literal>paths</literal> section, with contents of 13.1182 + the following form.</para> 13.1183 + <programlisting>[paths] repo1 = /my/path/to/some/repo repo2 = 13.1184 + /some/path/to/another</programlisting> 13.1185 + <para>In this case, the virtual path (the component that will 13.1186 + appear in a URL) is on the left hand side of each 13.1187 + definition, while the path to the repository is on the 13.1188 + right. Notice that there does not need to be any 13.1189 + relationship between the virtual path you choose and the 13.1190 + location of a repository in your filesystem.</para> 13.1191 + 13.1192 + <para>If you wish, you can use both the 13.1193 + <literal>collections</literal> and <literal>paths</literal> 13.1194 + mechanisms simultaneously in a single configuration 13.1195 + file.</para> 13.1196 + 13.1197 + <note> 13.1198 + <para> If multiple repositories have the same virtual path, 13.1199 + <filename role="special">hgwebdir.cgi</filename> will not 13.1200 + report an error. Instead, it will behave 13.1201 + unpredictably.</para> 13.1202 + </note> 13.1203 + 13.1204 + </sect3> 13.1205 + </sect2> 13.1206 + <sect2> 13.1207 + <title>Downloading source archives</title> 13.1208 + 13.1209 + <para>Mercurial's web interface lets users download an archive 13.1210 + of any revision. This archive will contain a snapshot of the 13.1211 + working directory as of that revision, but it will not contain 13.1212 + a copy of the repository data.</para> 13.1213 + 13.1214 + <para>By default, this feature is not enabled. To enable it, 13.1215 + you'll need to add an <envar 13.1216 + role="rc-item-web">allow_archive</envar> item to the 13.1217 + <literal role="rc-web">web</literal> section of your <filename 13.1218 + role="special"> /.hgrc</filename>.</para> 13.1219 + 13.1220 + </sect2> 13.1221 + <sect2> 13.1222 + <title>Web configuration options</title> 13.1223 + 13.1224 + <para>Mercurial's web interfaces (the <command role="hg-cmd">hg 13.1225 + serve</command> command, and the <filename 13.1226 + role="special">hgweb.cgi</filename> and <filename 13.1227 + role="special">hgwebdir.cgi</filename> scripts) have a 13.1228 + number of configuration options that you can set. These 13.1229 + belong in a section named <literal 13.1230 + role="rc-web">web</literal>.</para> 13.1231 + <itemizedlist> 13.1232 + <listitem><para><envar 13.1233 + role="rc-item-web">allow_archive</envar>: Determines 13.1234 + which (if any) archive download mechanisms Mercurial 13.1235 + supports. If you enable this feature, users of the web 13.1236 + interface will be able to download an archive of whatever 13.1237 + revision of a repository they are viewing. To enable the 13.1238 + archive feature, this item must take the form of a 13.1239 + sequence of words drawn from the list below.</para> 13.1240 + <itemizedlist> 13.1241 + <listitem><para><literal>bz2</literal>: A 13.1242 + <command>tar</command> archive, compressed using 13.1243 + <literal>bzip2</literal> compression. This has the 13.1244 + best compression ratio, but uses the most CPU time on 13.1245 + the server.</para> 13.1246 + </listitem> 13.1247 + <listitem><para><literal>gz</literal>: A 13.1248 + <command>tar</command> archive, compressed using 13.1249 + <literal>gzip</literal> compression.</para> 13.1250 + </listitem> 13.1251 + <listitem><para><literal>zip</literal>: A 13.1252 + <command>zip</command> archive, compressed using LZW 13.1253 + compression. This format has the worst compression 13.1254 + ratio, but is widely used in the Windows world.</para> 13.1255 + </listitem> 13.1256 + </itemizedlist> 13.1257 + <para> If you provide an empty list, or don't have an 13.1258 + <envar role="rc-item-web">allow_archive</envar> entry at 13.1259 + all, this feature will be disabled. Here is an example of 13.1260 + how to enable all three supported formats.</para> 13.1261 + <programlisting>[web] allow_archive = bz2 gz 13.1262 + zip</programlisting> 13.1263 + </listitem> 13.1264 + <listitem><para><envar role="rc-item-web">allowpull</envar>: 13.1265 + Boolean. Determines whether the web interface allows 13.1266 + remote users to <command role="hg-cmd">hg pull</command> 13.1267 + and <command role="hg-cmd">hg clone</command> this 13.1268 + repository over HTTP. If set to <literal>no</literal> or 13.1269 + <literal>false</literal>, only the 13.1270 + <quote>human-oriented</quote> portion of the web interface 13.1271 + is available.</para> 13.1272 + </listitem> 13.1273 + <listitem><para><envar role="rc-item-web">contact</envar>: 13.1274 + String. A free-form (but preferably brief) string 13.1275 + identifying the person or group in charge of the 13.1276 + repository. This often contains the name and email 13.1277 + address of a person or mailing list. It often makes sense 13.1278 + to place this entry in a repository's own <filename 13.1279 + role="special">.hg/hgrc</filename> file, but it can make 13.1280 + sense to use in a global <filename role="special"> 13.1281 + /.hgrc</filename>\ if every repository has a single 13.1282 + maintainer.</para> 13.1283 + </listitem> 13.1284 + <listitem><para><envar role="rc-item-web">maxchanges</envar>: 13.1285 + Integer. The default maximum number of changesets to 13.1286 + display in a single page of output.</para> 13.1287 + </listitem> 13.1288 + <listitem><para><envar role="rc-item-web">maxfiles</envar>: 13.1289 + Integer. The default maximum number of modified files to 13.1290 + display in a single page of output.</para> 13.1291 + </listitem> 13.1292 + <listitem><para><envar role="rc-item-web">stripes</envar>: 13.1293 + Integer. If the web interface displays alternating 13.1294 + <quote>stripes</quote> to make it easier to visually align 13.1295 + rows when you are looking at a table, this number controls 13.1296 + the number of rows in each stripe.</para> 13.1297 + </listitem> 13.1298 + <listitem><para><envar role="rc-item-web">style</envar>: 13.1299 + Controls the template Mercurial uses to display the web 13.1300 + interface. Mercurial ships with two web templates, named 13.1301 + <literal>default</literal> and <literal>gitweb</literal> 13.1302 + (the latter is much more visually attractive). You can 13.1303 + also specify a custom template of your own; see chapter 13.1304 + <xref linkend="chap:template"/> for details. 13.1305 + Here, you can see how to enable the 13.1306 + <literal>gitweb</literal> style.</para> 13.1307 + <programlisting>[web] style = gitweb</programlisting> 13.1308 + </listitem> 13.1309 + <listitem><para><envar role="rc-item-web">templates</envar>: 13.1310 + Path. The directory in which to search for template 13.1311 + files. By default, Mercurial searches in the directory in 13.1312 + which it was installed.</para> 13.1313 + </listitem></itemizedlist> 13.1314 + <para>If you are using <filename 13.1315 + role="special">hgwebdir.cgi</filename>, you can place a few 13.1316 + configuration items in a <literal role="rc-web">web</literal> 13.1317 + section of the <filename 13.1318 + role="special">hgweb.config</filename> file instead of a 13.1319 + <filename role="special"> /.hgrc</filename>\ file, for 13.1320 + convenience. These items are <envar 13.1321 + role="rc-item-web">motd</envar> and <envar 13.1322 + role="rc-item-web">style</envar>.</para> 13.1323 + 13.1324 + <sect3> 13.1325 + <title>Options specific to an individual repository</title> 13.1326 + 13.1327 + <para>A few <literal role="rc-web">web</literal> configuration 13.1328 + items ought to be placed in a repository's local <filename 13.1329 + role="special">.hg/hgrc</filename>, rather than a user's 13.1330 + or global <filename role="special"> 13.1331 + /.hgrc</filename>.</para> 13.1332 + <itemizedlist> 13.1333 + <listitem><para><envar 13.1334 + role="rc-item-web">description</envar>: String. A 13.1335 + free-form (but preferably brief) string that describes 13.1336 + the contents or purpose of the repository.</para> 13.1337 + </listitem> 13.1338 + <listitem><para><envar role="rc-item-web">name</envar>: 13.1339 + String. The name to use for the repository in the web 13.1340 + interface. This overrides the default name, which is 13.1341 + the last component of the repository's path.</para> 13.1342 + </listitem></itemizedlist> 13.1343 + 13.1344 + </sect3> 13.1345 + <sect3> 13.1346 + <title>Options specific to the <command role="hg-cmd">hg 13.1347 + serve</command> command</title> 13.1348 + 13.1349 + <para>Some of the items in the <literal 13.1350 + role="rc-web">web</literal> section of a <filename 13.1351 + role="special"> /.hgrc</filename>\ file are only for use 13.1352 + with the <command role="hg-cmd">hg serve</command> 13.1353 + command.</para> 13.1354 + <itemizedlist> 13.1355 + <listitem><para><envar role="rc-item-web">accesslog</envar>: 13.1356 + Path. The name of a file into which to write an access 13.1357 + log. By default, the <command role="hg-cmd">hg 13.1358 + serve</command> command writes this information to 13.1359 + standard output, not to a file. Log entries are written 13.1360 + in the standard <quote>combined</quote> file format used 13.1361 + by almost all web servers.</para> 13.1362 + </listitem> 13.1363 + <listitem><para><envar role="rc-item-web">address</envar>: 13.1364 + String. The local address on which the server should 13.1365 + listen for incoming connections. By default, the server 13.1366 + listens on all addresses.</para> 13.1367 + </listitem> 13.1368 + <listitem><para><envar role="rc-item-web">errorlog</envar>: 13.1369 + Path. The name of a file into which to write an error 13.1370 + log. By default, the <command role="hg-cmd">hg 13.1371 + serve</command> command writes this information to 13.1372 + standard error, not to a file.</para> 13.1373 + </listitem> 13.1374 + <listitem><para><envar role="rc-item-web">ipv6</envar>: 13.1375 + Boolean. Whether to use the IPv6 protocol. By default, 13.1376 + IPv6 is not used.</para> 13.1377 + </listitem> 13.1378 + <listitem><para><envar role="rc-item-web">port</envar>: 13.1379 + Integer. The TCP port number on which the server should 13.1380 + listen. The default port number used is 8000.</para> 13.1381 + </listitem></itemizedlist> 13.1382 + 13.1383 + </sect3> 13.1384 + <sect3> 13.1385 + <title>Choosing the right <filename role="special"> 13.1386 + /.hgrc</filename>\ file to add <literal 13.1387 + role="rc-web">web</literal> items to</title> 13.1388 + 13.1389 + <para>It is important to remember that a web server like 13.1390 + Apache or <literal>lighttpd</literal> will run under a user 13.1391 + ID that is different to yours. CGI scripts run by your 13.1392 + server, such as <filename 13.1393 + role="special">hgweb.cgi</filename>, will usually also run 13.1394 + under that user ID.</para> 13.1395 + 13.1396 + <para>If you add <literal role="rc-web">web</literal> items to 13.1397 + your own personal <filename role="special"> 13.1398 + /.hgrc</filename>\ file, CGI scripts won't read that 13.1399 + <filename role="special"> /.hgrc</filename>\ file. Those 13.1400 + settings will thus only affect the behaviour of the <command 13.1401 + role="hg-cmd">hg serve</command> command when you run it. 13.1402 + To cause CGI scripts to see your settings, either create a 13.1403 + <filename role="special"> /.hgrc</filename>\ file in the 13.1404 + home directory of the user ID that runs your web server, or 13.1405 + add those settings to a system-wide <filename 13.1406 + role="special"> /.hgrc</filename>\ file.</para> 13.1407 + 13.1408 + 13.1409 + </sect3> 13.1410 + </sect2> 13.1411 + </sect1> 13.1412 +</chapter> 13.1413 + 13.1414 +<!-- 13.1415 +local variables: 13.1416 +sgml-parent-document: ("00book.xml" "book" "chapter") 13.1417 +end: 13.1418 +-->
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/en/ch07-filenames.xml Wed Feb 18 00:22:09 2009 -0800 14.3 @@ -0,0 +1,392 @@ 14.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 14.5 + 14.6 +<chapter id="chap:names"> 14.7 + <title>File names and pattern matching</title> 14.8 + 14.9 + <para>Mercurial provides mechanisms that let you work with file 14.10 + names in a consistent and expressive way.</para> 14.11 + 14.12 + <sect1> 14.13 + <title>Simple file naming</title> 14.14 + 14.15 + <para>Mercurial uses a unified piece of machinery <quote>under the 14.16 + hood</quote> to handle file names. Every command behaves 14.17 + uniformly with respect to file names. The way in which commands 14.18 + work with file names is as follows.</para> 14.19 + 14.20 + <para>If you explicitly name real files on the command line, 14.21 + Mercurial works with exactly those files, as you would expect. 14.22 + <!-- &interaction.filenames.files; --></para> 14.23 + 14.24 + <para>When you provide a directory name, Mercurial will interpret 14.25 + this as <quote>operate on every file in this directory and its 14.26 + subdirectories</quote>. Mercurial traverses the files and 14.27 + subdirectories in a directory in alphabetical order. When it 14.28 + encounters a subdirectory, it will traverse that subdirectory 14.29 + before continuing with the current directory. <!-- 14.30 + &interaction.filenames.dirs; --></para> 14.31 + 14.32 + </sect1> 14.33 + <sect1> 14.34 + <title>Running commands without any file names</title> 14.35 + 14.36 + <para>Mercurial's commands that work with file names have useful 14.37 + default behaviours when you invoke them without providing any 14.38 + file names or patterns. What kind of behaviour you should 14.39 + expect depends on what the command does. Here are a few rules 14.40 + of thumb you can use to predict what a command is likely to do 14.41 + if you don't give it any names to work with.</para> 14.42 + <itemizedlist> 14.43 + <listitem><para>Most commands will operate on the entire working 14.44 + directory. This is what the <command role="hg-cmd">hg 14.45 + add</command> command does, for example.</para> 14.46 + </listitem> 14.47 + <listitem><para>If the command has effects that are difficult or 14.48 + impossible to reverse, it will force you to explicitly 14.49 + provide at least one name or pattern (see below). This 14.50 + protects you from accidentally deleting files by running 14.51 + <command role="hg-cmd">hg remove</command> with no 14.52 + arguments, for example.</para> 14.53 + </listitem></itemizedlist> 14.54 + 14.55 + <para>It's easy to work around these default behaviours if they 14.56 + don't suit you. If a command normally operates on the whole 14.57 + working directory, you can invoke it on just the current 14.58 + directory and its subdirectories by giving it the name 14.59 + <quote><filename class="directory">.</filename></quote>. <!-- 14.60 + &interaction.filenames.wdir-subdir; --></para> 14.61 + 14.62 + <para>Along the same lines, some commands normally print file 14.63 + names relative to the root of the repository, even if you're 14.64 + invoking them from a subdirectory. Such a command will print 14.65 + file names relative to your subdirectory if you give it explicit 14.66 + names. Here, we're going to run <command role="hg-cmd">hg 14.67 + status</command> from a subdirectory, and get it to operate on 14.68 + the entire working directory while printing file names relative 14.69 + to our subdirectory, by passing it the output of the <command 14.70 + role="hg-cmd">hg root</command> command. <!-- 14.71 + &interaction.filenames.wdir-relname; --></para> 14.72 + 14.73 + </sect1> 14.74 + <sect1> 14.75 + <title>Telling you what's going on</title> 14.76 + 14.77 + <para>The <command role="hg-cmd">hg add</command> example in the 14.78 + preceding section illustrates something else that's helpful 14.79 + about Mercurial commands. If a command operates on a file that 14.80 + you didn't name explicitly on the command line, it will usually 14.81 + print the name of the file, so that you will not be surprised 14.82 + what's going on.</para> 14.83 + 14.84 + <para>The principle here is of <emphasis>least 14.85 + surprise</emphasis>. If you've exactly named a file on the 14.86 + command line, there's no point in repeating it back at you. If 14.87 + Mercurial is acting on a file <emphasis>implicitly</emphasis>, 14.88 + because you provided no names, or a directory, or a pattern (see 14.89 + below), it's safest to tell you what it's doing.</para> 14.90 + 14.91 + <para>For commands that behave this way, you can silence them 14.92 + using the <option role="hg-opt-global">-q</option> option. You 14.93 + can also get them to print the name of every file, even those 14.94 + you've named explicitly, using the <option 14.95 + role="hg-opt-global">-v</option> option.</para> 14.96 + 14.97 + </sect1> 14.98 + <sect1> 14.99 + <title>Using patterns to identify files</title> 14.100 + 14.101 + <para>In addition to working with file and directory names, 14.102 + Mercurial lets you use <emphasis>patterns</emphasis> to identify 14.103 + files. Mercurial's pattern handling is expressive.</para> 14.104 + 14.105 + <para>On Unix-like systems (Linux, MacOS, etc.), the job of 14.106 + matching file names to patterns normally falls to the shell. On 14.107 + these systems, you must explicitly tell Mercurial that a name is 14.108 + a pattern. On Windows, the shell does not expand patterns, so 14.109 + Mercurial will automatically identify names that are patterns, 14.110 + and expand them for you.</para> 14.111 + 14.112 + <para>To provide a pattern in place of a regular name on the 14.113 + command line, the mechanism is simple:</para> 14.114 + <programlisting>syntax:patternbody</programlisting> 14.115 + <para>That is, a pattern is identified by a short text string that 14.116 + says what kind of pattern this is, followed by a colon, followed 14.117 + by the actual pattern.</para> 14.118 + 14.119 + <para>Mercurial supports two kinds of pattern syntax. The most 14.120 + frequently used is called <literal>glob</literal>; this is the 14.121 + same kind of pattern matching used by the Unix shell, and should 14.122 + be familiar to Windows command prompt users, too.</para> 14.123 + 14.124 + <para>When Mercurial does automatic pattern matching on Windows, 14.125 + it uses <literal>glob</literal> syntax. You can thus omit the 14.126 + <quote><literal>glob:</literal></quote> prefix on Windows, but 14.127 + it's safe to use it, too.</para> 14.128 + 14.129 + <para>The <literal>re</literal> syntax is more powerful; it lets 14.130 + you specify patterns using regular expressions, also known as 14.131 + regexps.</para> 14.132 + 14.133 + <para>By the way, in the examples that follow, notice that I'm 14.134 + careful to wrap all of my patterns in quote characters, so that 14.135 + they won't get expanded by the shell before Mercurial sees 14.136 + them.</para> 14.137 + 14.138 + <sect2> 14.139 + <title>Shell-style <literal>glob</literal> patterns</title> 14.140 + 14.141 + <para>This is an overview of the kinds of patterns you can use 14.142 + when you're matching on glob patterns.</para> 14.143 + 14.144 + <para>The <quote><literal>*</literal></quote> character matches 14.145 + any string, within a single directory. <!-- 14.146 + &interaction.filenames.glob.star; --></para> 14.147 + 14.148 + <para>The <quote><literal>**</literal></quote> pattern matches 14.149 + any string, and crosses directory boundaries. It's not a 14.150 + standard Unix glob token, but it's accepted by several popular 14.151 + Unix shells, and is very useful. <!-- 14.152 + &interaction.filenames.glob.starstar; --></para> 14.153 + 14.154 + <para>The <quote><literal>?</literal></quote> pattern matches 14.155 + any single character. <!-- 14.156 + &interaction.filenames.glob.question; --></para> 14.157 + 14.158 + <para>The <quote><literal>[</literal></quote> character begins a 14.159 + <emphasis>character class</emphasis>. This matches any single 14.160 + character within the class. The class ends with a 14.161 + <quote><literal>]</literal></quote> character. A class may 14.162 + contain multiple <emphasis>range</emphasis>s of the form 14.163 + <quote><literal>a-f</literal></quote>, which is shorthand for 14.164 + <quote><literal>abcdef</literal></quote>. <!-- 14.165 + &interaction.filenames.glob.range; --> If the first character 14.166 + after the <quote><literal>[</literal></quote> in a character 14.167 + class is a <quote><literal>!</literal></quote>, it 14.168 + <emphasis>negates</emphasis> the class, making it match any 14.169 + single character not in the class.</para> 14.170 + 14.171 + <para>A <quote><literal>{</literal></quote> begins a group of 14.172 + subpatterns, where the whole group matches if any subpattern 14.173 + in the group matches. The <quote><literal>,</literal></quote> 14.174 + character separates subpatterns, and <quote>\texttt{}}</quote> 14.175 + ends the group. <!-- &interaction.filenames.glob.group; 14.176 + --></para> 14.177 + 14.178 + <sect3> 14.179 + <title>Watch out!</title> 14.180 + 14.181 + <para>Don't forget that if you want to match a pattern in any 14.182 + directory, you should not be using the 14.183 + <quote><literal>*</literal></quote> match-any token, as this 14.184 + will only match within one directory. Instead, use the 14.185 + <quote><literal>**</literal></quote> token. This small 14.186 + example illustrates the difference between the two. <!-- 14.187 + &interaction.filenames.glob.star-starstar; --></para> 14.188 + 14.189 + </sect3> 14.190 + </sect2> 14.191 + <sect2> 14.192 + <title>Regular expression matching with <literal>re</literal> 14.193 + patterns</title> 14.194 + 14.195 + <para>Mercurial accepts the same regular expression syntax as 14.196 + the Python programming language (it uses Python's regexp 14.197 + engine internally). This is based on the Perl language's 14.198 + regexp syntax, which is the most popular dialect in use (it's 14.199 + also used in Java, for example).</para> 14.200 + 14.201 + <para>I won't discuss Mercurial's regexp dialect in any detail 14.202 + here, as regexps are not often used. Perl-style regexps are 14.203 + in any case already exhaustively documented on a multitude of 14.204 + web sites, and in many books. Instead, I will focus here on a 14.205 + few things you should know if you find yourself needing to use 14.206 + regexps with Mercurial.</para> 14.207 + 14.208 + <para>A regexp is matched against an entire file name, relative 14.209 + to the root of the repository. In other words, even if you're 14.210 + already in subbdirectory <filename 14.211 + class="directory">foo</filename>, if you want to match files 14.212 + under this directory, your pattern must start with 14.213 + <quote><literal>foo/</literal></quote>.</para> 14.214 + 14.215 + <para>One thing to note, if you're familiar with Perl-style 14.216 + regexps, is that Mercurial's are <emphasis>rooted</emphasis>. 14.217 + That is, a regexp starts matching against the beginning of a 14.218 + string; it doesn't look for a match anywhere within the 14.219 + string. To match anywhere in a string, start your pattern 14.220 + with <quote><literal>.*</literal></quote>.</para> 14.221 + 14.222 + </sect2> 14.223 + </sect1> 14.224 + <sect1> 14.225 + <title>Filtering files</title> 14.226 + 14.227 + <para>Not only does Mercurial give you a variety of ways to 14.228 + specify files; it lets you further winnow those files using 14.229 + <emphasis>filters</emphasis>. Commands that work with file 14.230 + names accept two filtering options.</para> 14.231 + <itemizedlist> 14.232 + <listitem><para><option role="hg-opt-global">-I</option>, or 14.233 + <option role="hg-opt-global">--include</option>, lets you 14.234 + specify a pattern that file names must match in order to be 14.235 + processed.</para> 14.236 + </listitem> 14.237 + <listitem><para><option role="hg-opt-global">-X</option>, or 14.238 + <option role="hg-opt-global">--exclude</option>, gives you a 14.239 + way to <emphasis>avoid</emphasis> processing files, if they 14.240 + match this pattern.</para> 14.241 + </listitem></itemizedlist> 14.242 + <para>You can provide multiple <option 14.243 + role="hg-opt-global">-I</option> and <option 14.244 + role="hg-opt-global">-X</option> options on the command line, 14.245 + and intermix them as you please. Mercurial interprets the 14.246 + patterns you provide using glob syntax by default (but you can 14.247 + use regexps if you need to).</para> 14.248 + 14.249 + <para>You can read a <option role="hg-opt-global">-I</option> 14.250 + filter as <quote>process only the files that match this 14.251 + filter</quote>. <!-- &interaction.filenames.filter.include; 14.252 + --> The <option role="hg-opt-global">-X</option> filter is best 14.253 + read as <quote>process only the files that don't match this 14.254 + pattern</quote>. <!-- &interaction.filenames.filter.exclude; 14.255 + --></para> 14.256 + 14.257 + </sect1> 14.258 + <sect1> 14.259 + <title>Ignoring unwanted files and directories</title> 14.260 + 14.261 + <para>XXX.</para> 14.262 + 14.263 + </sect1> 14.264 + <sect1 id="sec:names:case"> 14.265 + <title>Case sensitivity</title> 14.266 + 14.267 + <para>If you're working in a mixed development environment that 14.268 + contains both Linux (or other Unix) systems and Macs or Windows 14.269 + systems, you should keep in the back of your mind the knowledge 14.270 + that they treat the case (<quote>N</quote> versus 14.271 + <quote>n</quote>) of file names in incompatible ways. This is 14.272 + not very likely to affect you, and it's easy to deal with if it 14.273 + does, but it could surprise you if you don't know about 14.274 + it.</para> 14.275 + 14.276 + <para>Operating systems and filesystems differ in the way they 14.277 + handle the <emphasis>case</emphasis> of characters in file and 14.278 + directory names. There are three common ways to handle case in 14.279 + names.</para> 14.280 + <itemizedlist> 14.281 + <listitem><para>Completely case insensitive. Uppercase and 14.282 + lowercase versions of a letter are treated as identical, 14.283 + both when creating a file and during subsequent accesses. 14.284 + This is common on older DOS-based systems.</para> 14.285 + </listitem> 14.286 + <listitem><para>Case preserving, but insensitive. When a file 14.287 + or directory is created, the case of its name is stored, and 14.288 + can be retrieved and displayed by the operating system. 14.289 + When an existing file is being looked up, its case is 14.290 + ignored. This is the standard arrangement on Windows and 14.291 + MacOS. The names <filename>foo</filename> and 14.292 + <filename>FoO</filename> identify the same file. This 14.293 + treatment of uppercase and lowercase letters as 14.294 + interchangeable is also referred to as <emphasis>case 14.295 + folding</emphasis>.</para> 14.296 + </listitem> 14.297 + <listitem><para>Case sensitive. The case of a name is 14.298 + significant at all times. The names <filename>foo</filename> 14.299 + and {FoO} identify different files. This is the way Linux 14.300 + and Unix systems normally work.</para> 14.301 + </listitem></itemizedlist> 14.302 + 14.303 + <para>On Unix-like systems, it is possible to have any or all of 14.304 + the above ways of handling case in action at once. For example, 14.305 + if you use a USB thumb drive formatted with a FAT32 filesystem 14.306 + on a Linux system, Linux will handle names on that filesystem in 14.307 + a case preserving, but insensitive, way.</para> 14.308 + 14.309 + <sect2> 14.310 + <title>Safe, portable repository storage</title> 14.311 + 14.312 + <para>Mercurial's repository storage mechanism is <emphasis>case 14.313 + safe</emphasis>. It translates file names so that they can 14.314 + be safely stored on both case sensitive and case insensitive 14.315 + filesystems. This means that you can use normal file copying 14.316 + tools to transfer a Mercurial repository onto, for example, a 14.317 + USB thumb drive, and safely move that drive and repository 14.318 + back and forth between a Mac, a PC running Windows, and a 14.319 + Linux box.</para> 14.320 + 14.321 + </sect2> 14.322 + <sect2> 14.323 + <title>Detecting case conflicts</title> 14.324 + 14.325 + <para>When operating in the working directory, Mercurial honours 14.326 + the naming policy of the filesystem where the working 14.327 + directory is located. If the filesystem is case preserving, 14.328 + but insensitive, Mercurial will treat names that differ only 14.329 + in case as the same.</para> 14.330 + 14.331 + <para>An important aspect of this approach is that it is 14.332 + possible to commit a changeset on a case sensitive (typically 14.333 + Linux or Unix) filesystem that will cause trouble for users on 14.334 + case insensitive (usually Windows and MacOS) users. If a 14.335 + Linux user commits changes to two files, one named 14.336 + <filename>myfile.c</filename> and the other named 14.337 + <filename>MyFile.C</filename>, they will be stored correctly 14.338 + in the repository. And in the working directories of other 14.339 + Linux users, they will be correctly represented as separate 14.340 + files.</para> 14.341 + 14.342 + <para>If a Windows or Mac user pulls this change, they will not 14.343 + initially have a problem, because Mercurial's repository 14.344 + storage mechanism is case safe. However, once they try to 14.345 + <command role="hg-cmd">hg update</command> the working 14.346 + directory to that changeset, or <command role="hg-cmd">hg 14.347 + merge</command> with that changeset, Mercurial will spot the 14.348 + conflict between the two file names that the filesystem would 14.349 + treat as the same, and forbid the update or merge from 14.350 + occurring.</para> 14.351 + 14.352 + </sect2> 14.353 + <sect2> 14.354 + <title>Fixing a case conflict</title> 14.355 + 14.356 + <para>If you are using Windows or a Mac in a mixed environment 14.357 + where some of your collaborators are using Linux or Unix, and 14.358 + Mercurial reports a case folding conflict when you try to 14.359 + <command role="hg-cmd">hg update</command> or <command 14.360 + role="hg-cmd">hg merge</command>, the procedure to fix the 14.361 + problem is simple.</para> 14.362 + 14.363 + <para>Just find a nearby Linux or Unix box, clone the problem 14.364 + repository onto it, and use Mercurial's <command 14.365 + role="hg-cmd">hg rename</command> command to change the 14.366 + names of any offending files or directories so that they will 14.367 + no longer cause case folding conflicts. Commit this change, 14.368 + <command role="hg-cmd">hg pull</command> or <command 14.369 + role="hg-cmd">hg push</command> it across to your Windows or 14.370 + MacOS system, and <command role="hg-cmd">hg update</command> 14.371 + to the revision with the non-conflicting names.</para> 14.372 + 14.373 + <para>The changeset with case-conflicting names will remain in 14.374 + your project's history, and you still won't be able to 14.375 + <command role="hg-cmd">hg update</command> your working 14.376 + directory to that changeset on a Windows or MacOS system, but 14.377 + you can continue development unimpeded.</para> 14.378 + 14.379 + <note> 14.380 + <para> Prior to version 0.9.3, Mercurial did not use a case 14.381 + safe repository storage mechanism, and did not detect case 14.382 + folding conflicts. If you are using an older version of 14.383 + Mercurial on Windows or MacOS, I strongly recommend that you 14.384 + upgrade.</para> 14.385 + </note> 14.386 + 14.387 + </sect2> 14.388 + </sect1> 14.389 +</chapter> 14.390 + 14.391 +<!-- 14.392 +local variables: 14.393 +sgml-parent-document: ("00book.xml" "book" "chapter") 14.394 +end: 14.395 +-->
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/en/ch08-branch.xml Wed Feb 18 00:22:09 2009 -0800 15.3 @@ -0,0 +1,485 @@ 15.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 15.5 + 15.6 +<chapter id="chap:branch"> 15.7 + <title>Managing releases and branchy development</title> 15.8 + 15.9 + <para>Mercurial provides several mechanisms for you to manage a 15.10 + project that is making progress on multiple fronts at once. To 15.11 + understand these mechanisms, let's first take a brief look at a 15.12 + fairly normal software project structure.</para> 15.13 + 15.14 + <para>Many software projects issue periodic <quote>major</quote> 15.15 + releases that contain substantial new features. In parallel, they 15.16 + may issue <quote>minor</quote> releases. These are usually 15.17 + identical to the major releases off which they're based, but with 15.18 + a few bugs fixed.</para> 15.19 + 15.20 + <para>In this chapter, we'll start by talking about how to keep 15.21 + records of project milestones such as releases. We'll then 15.22 + continue on to talk about the flow of work between different 15.23 + phases of a project, and how Mercurial can help you to isolate and 15.24 + manage this work.</para> 15.25 + 15.26 + <sect1> 15.27 + <title>Giving a persistent name to a revision</title> 15.28 + 15.29 + <para>Once you decide that you'd like to call a particular 15.30 + revision a <quote>release</quote>, it's a good idea to record 15.31 + the identity of that revision. This will let you reproduce that 15.32 + release at a later date, for whatever purpose you might need at 15.33 + the time (reproducing a bug, porting to a new platform, etc). 15.34 + <!-- &interaction.tag.init; --></para> 15.35 + 15.36 + <para>Mercurial lets you give a permanent name to any revision 15.37 + using the <command role="hg-cmd">hg tag</command> command. Not 15.38 + surprisingly, these names are called <quote>tags</quote>. <!-- 15.39 + &interaction.tag.tag; --></para> 15.40 + 15.41 + <para>A tag is nothing more than a <quote>symbolic name</quote> 15.42 + for a revision. Tags exist purely for your convenience, so that 15.43 + you have a handy permanent way to refer to a revision; Mercurial 15.44 + doesn't interpret the tag names you use in any way. Neither 15.45 + does Mercurial place any restrictions on the name of a tag, 15.46 + beyond a few that are necessary to ensure that a tag can be 15.47 + parsed unambiguously. A tag name cannot contain any of the 15.48 + following characters:</para> 15.49 + <itemizedlist> 15.50 + <listitem><para>Colon (ASCII 58, 15.51 + <quote><literal>:</literal></quote>)</para> 15.52 + </listitem> 15.53 + <listitem><para>Carriage return (ASCII 13, 15.54 + <quote><literal>\r</literal></quote>)</para> 15.55 + </listitem> 15.56 + <listitem><para>Newline (ASCII 10, 15.57 + <quote><literal>\n</literal></quote>)</para> 15.58 + </listitem></itemizedlist> 15.59 + 15.60 + <para>You can use the <command role="hg-cmd">hg tags</command> 15.61 + command to display the tags present in your repository. In the 15.62 + output, each tagged revision is identified first by its name, 15.63 + then by revision number, and finally by the unique hash of the 15.64 + revision. <!-- &interaction.tag.tags; --> Notice that 15.65 + <literal>tip</literal> is listed in the output of <command 15.66 + role="hg-cmd">hg tags</command>. The <literal>tip</literal> 15.67 + tag is a special <quote>floating</quote> tag, which always 15.68 + identifies the newest revision in the repository.</para> 15.69 + 15.70 + <para>In the output of the <command role="hg-cmd">hg 15.71 + tags</command> command, tags are listed in reverse order, by 15.72 + revision number. This usually means that recent tags are listed 15.73 + before older tags. It also means that <literal>tip</literal> is 15.74 + always going to be the first tag listed in the output of 15.75 + <command role="hg-cmd">hg tags</command>.</para> 15.76 + 15.77 + <para>When you run <command role="hg-cmd">hg log</command>, if it 15.78 + displays a revision that has tags associated with it, it will 15.79 + print those tags. <!-- &interaction.tag.log; --></para> 15.80 + 15.81 + <para>Any time you need to provide a revision ID to a Mercurial 15.82 + command, the command will accept a tag name in its place. 15.83 + Internally, Mercurial will translate your tag name into the 15.84 + corresponding revision ID, then use that. <!-- 15.85 + &interaction.tag.log.v1.0; --></para> 15.86 + 15.87 + <para>There's no limit on the number of tags you can have in a 15.88 + repository, or on the number of tags that a single revision can 15.89 + have. As a practical matter, it's not a great idea to have 15.90 + <quote>too many</quote> (a number which will vary from project 15.91 + to project), simply because tags are supposed to help you to 15.92 + find revisions. If you have lots of tags, the ease of using 15.93 + them to identify revisions diminishes rapidly.</para> 15.94 + 15.95 + <para>For example, if your project has milestones as frequent as 15.96 + every few days, it's perfectly reasonable to tag each one of 15.97 + those. But if you have a continuous build system that makes 15.98 + sure every revision can be built cleanly, you'd be introducing a 15.99 + lot of noise if you were to tag every clean build. Instead, you 15.100 + could tag failed builds (on the assumption that they're rare!), 15.101 + or simply not use tags to track buildability.</para> 15.102 + 15.103 + <para>If you want to remove a tag that you no longer want, use 15.104 + <command role="hg-cmd">hg tag --remove</command>. <!-- 15.105 + &interaction.tag.remove; --> You can also modify a tag at any 15.106 + time, so that it identifies a different revision, by simply 15.107 + issuing a new <command role="hg-cmd">hg tag</command> command. 15.108 + You'll have to use the <option role="hg-opt-tag">-f</option> 15.109 + option to tell Mercurial that you <emphasis>really</emphasis> 15.110 + want to update the tag. <!-- &interaction.tag.replace; --> There 15.111 + will still be a permanent record of the previous identity of the 15.112 + tag, but Mercurial will no longer use it. There's thus no 15.113 + penalty to tagging the wrong revision; all you have to do is 15.114 + turn around and tag the correct revision once you discover your 15.115 + error.</para> 15.116 + 15.117 + <para>Mercurial stores tags in a normal revision-controlled file 15.118 + in your repository. If you've created any tags, you'll find 15.119 + them in a file named <filename 15.120 + role="special">.hgtags</filename>. When you run the <command 15.121 + role="hg-cmd">hg tag</command> command, Mercurial modifies 15.122 + this file, then automatically commits the change to it. This 15.123 + means that every time you run <command role="hg-cmd">hg 15.124 + tag</command>, you'll see a corresponding changeset in the 15.125 + output of <command role="hg-cmd">hg log</command>. <!-- 15.126 + &interaction.tag.tip; --></para> 15.127 + 15.128 + <sect2> 15.129 + <title>Handling tag conflicts during a merge</title> 15.130 + 15.131 + <para>You won't often need to care about the <filename 15.132 + role="special">.hgtags</filename> file, but it sometimes 15.133 + makes its presence known during a merge. The format of the 15.134 + file is simple: it consists of a series of lines. Each line 15.135 + starts with a changeset hash, followed by a space, followed by 15.136 + the name of a tag.</para> 15.137 + 15.138 + <para>If you're resolving a conflict in the <filename 15.139 + role="special">.hgtags</filename> file during a merge, 15.140 + there's one twist to modifying the <filename 15.141 + role="special">.hgtags</filename> file: when Mercurial is 15.142 + parsing the tags in a repository, it 15.143 + <emphasis>never</emphasis> reads the working copy of the 15.144 + <filename role="special">.hgtags</filename> file. Instead, it 15.145 + reads the <emphasis>most recently committed</emphasis> 15.146 + revision of the file.</para> 15.147 + 15.148 + <para>An unfortunate consequence of this design is that you 15.149 + can't actually verify that your merged <filename 15.150 + role="special">.hgtags</filename> file is correct until 15.151 + <emphasis>after</emphasis> you've committed a change. So if 15.152 + you find yourself resolving a conflict on <filename 15.153 + role="special">.hgtags</filename> during a merge, be sure to 15.154 + run <command role="hg-cmd">hg tags</command> after you commit. 15.155 + If it finds an error in the <filename 15.156 + role="special">.hgtags</filename> file, it will report the 15.157 + location of the error, which you can then fix and commit. You 15.158 + should then run <command role="hg-cmd">hg tags</command> 15.159 + again, just to be sure that your fix is correct.</para> 15.160 + 15.161 + </sect2> 15.162 + <sect2> 15.163 + <title>Tags and cloning</title> 15.164 + 15.165 + <para>You may have noticed that the <command role="hg-cmd">hg 15.166 + clone</command> command has a <option 15.167 + role="hg-opt-clone">-r</option> option that lets you clone 15.168 + an exact copy of the repository as of a particular changeset. 15.169 + The new clone will not contain any project history that comes 15.170 + after the revision you specified. This has an interaction 15.171 + with tags that can surprise the unwary.</para> 15.172 + 15.173 + <para>Recall that a tag is stored as a revision to the <filename 15.174 + role="special">.hgtags</filename> file, so that when you 15.175 + create a tag, the changeset in which it's recorded necessarily 15.176 + refers to an older changeset. When you run <command 15.177 + role="hg-cmd">hg clone -r foo</command> to clone a 15.178 + repository as of tag <literal>foo</literal>, the new clone 15.179 + <emphasis>will not contain the history that created the 15.180 + tag</emphasis> that you used to clone the repository. The 15.181 + result is that you'll get exactly the right subset of the 15.182 + project's history in the new repository, but 15.183 + <emphasis>not</emphasis> the tag you might have 15.184 + expected.</para> 15.185 + 15.186 + </sect2> 15.187 + <sect2> 15.188 + <title>When permanent tags are too much</title> 15.189 + 15.190 + <para>Since Mercurial's tags are revision controlled and carried 15.191 + around with a project's history, everyone you work with will 15.192 + see the tags you create. But giving names to revisions has 15.193 + uses beyond simply noting that revision 15.194 + <literal>4237e45506ee</literal> is really 15.195 + <literal>v2.0.2</literal>. If you're trying to track down a 15.196 + subtle bug, you might want a tag to remind you of something 15.197 + like <quote>Anne saw the symptoms with this 15.198 + revision</quote>.</para> 15.199 + 15.200 + <para>For cases like this, what you might want to use are 15.201 + <emphasis>local</emphasis> tags. You can create a local tag 15.202 + with the <option role="hg-opt-tag">-l</option> option to the 15.203 + <command role="hg-cmd">hg tag</command> command. This will 15.204 + store the tag in a file called <filename 15.205 + role="special">.hg/localtags</filename>. Unlike <filename 15.206 + role="special">.hgtags</filename>, <filename 15.207 + role="special">.hg/localtags</filename> is not revision 15.208 + controlled. Any tags you create using <option 15.209 + role="hg-opt-tag">-l</option> remain strictly local to the 15.210 + repository you're currently working in.</para> 15.211 + 15.212 + </sect2> 15.213 + </sect1> 15.214 + <sect1> 15.215 + <title>The flow of changes&emdash;big picture vs. little</title> 15.216 + 15.217 + <para>To return to the outline I sketched at the beginning of a 15.218 + chapter, let's think about a project that has multiple 15.219 + concurrent pieces of work under development at once.</para> 15.220 + 15.221 + <para>There might be a push for a new <quote>main</quote> release; 15.222 + a new minor bugfix release to the last main release; and an 15.223 + unexpected <quote>hot fix</quote> to an old release that is now 15.224 + in maintenance mode.</para> 15.225 + 15.226 + <para>The usual way people refer to these different concurrent 15.227 + directions of development is as <quote>branches</quote>. 15.228 + However, we've already seen numerous times that Mercurial treats 15.229 + <emphasis>all of history</emphasis> as a series of branches and 15.230 + merges. Really, what we have here is two ideas that are 15.231 + peripherally related, but which happen to share a name.</para> 15.232 + <itemizedlist> 15.233 + <listitem><para><quote>Big picture</quote> branches represent 15.234 + the sweep of a project's evolution; people give them names, 15.235 + and talk about them in conversation.</para> 15.236 + </listitem> 15.237 + <listitem><para><quote>Little picture</quote> branches are 15.238 + artefacts of the day-to-day activity of developing and 15.239 + merging changes. They expose the narrative of how the code 15.240 + was developed.</para> 15.241 + </listitem></itemizedlist> 15.242 + 15.243 + </sect1> 15.244 + <sect1> 15.245 + <title>Managing big-picture branches in repositories</title> 15.246 + 15.247 + <para>The easiest way to isolate a <quote>big picture</quote> 15.248 + branch in Mercurial is in a dedicated repository. If you have 15.249 + an existing shared repository&emdash;let's call it 15.250 + <literal>myproject</literal>&emdash;that reaches a 15.251 + <quote>1.0</quote> milestone, you can start to prepare for 15.252 + future maintenance releases on top of version 1.0 by tagging the 15.253 + revision from which you prepared the 1.0 release. <!-- 15.254 + &interaction.branch-repo.tag; --> You can then clone a new 15.255 + shared <literal>myproject-1.0.1</literal> repository as of that 15.256 + tag. <!-- &interaction.branch-repo.clone; --></para> 15.257 + 15.258 + <para>Afterwards, if someone needs to work on a bug fix that ought 15.259 + to go into an upcoming 1.0.1 minor release, they clone the 15.260 + <literal>myproject-1.0.1</literal> repository, make their 15.261 + changes, and push them back. <!-- 15.262 + &interaction.branch-repo.bugfix; --> Meanwhile, development for 15.263 + the next major release can continue, isolated and unabated, in 15.264 + the <literal>myproject</literal> repository. <!-- 15.265 + &interaction.branch-repo.new; --></para> 15.266 + 15.267 + </sect1> 15.268 + <sect1> 15.269 + <title>Don't repeat yourself: merging across branches</title> 15.270 + 15.271 + <para>In many cases, if you have a bug to fix on a maintenance 15.272 + branch, the chances are good that the bug exists on your 15.273 + project's main branch (and possibly other maintenance branches, 15.274 + too). It's a rare developer who wants to fix the same bug 15.275 + multiple times, so let's look at a few ways that Mercurial can 15.276 + help you to manage these bugfixes without duplicating your 15.277 + work.</para> 15.278 + 15.279 + <para>In the simplest instance, all you need to do is pull changes 15.280 + from your maintenance branch into your local clone of the target 15.281 + branch. <!-- &interaction.branch-repo.pull; --> You'll then need 15.282 + to merge the heads of the two branches, and push back to the 15.283 + main branch. <!-- &interaction.branch-repo.merge; --></para> 15.284 + 15.285 + </sect1> 15.286 + <sect1> 15.287 + <title>Naming branches within one repository</title> 15.288 + 15.289 + <para>In most instances, isolating branches in repositories is the 15.290 + right approach. Its simplicity makes it easy to understand; and 15.291 + so it's hard to make mistakes. There's a one-to-one 15.292 + relationship between branches you're working in and directories 15.293 + on your system. This lets you use normal (non-Mercurial-aware) 15.294 + tools to work on files within a branch/repository.</para> 15.295 + 15.296 + <para>If you're more in the <quote>power user</quote> category 15.297 + (<emphasis>and</emphasis> your collaborators are too), there is 15.298 + an alternative way of handling branches that you can consider. 15.299 + I've already mentioned the human-level distinction between 15.300 + <quote>small picture</quote> and <quote>big picture</quote> 15.301 + branches. While Mercurial works with multiple <quote>small 15.302 + picture</quote> branches in a repository all the time (for 15.303 + example after you pull changes in, but before you merge them), 15.304 + it can <emphasis>also</emphasis> work with multiple <quote>big 15.305 + picture</quote> branches.</para> 15.306 + 15.307 + <para>The key to working this way is that Mercurial lets you 15.308 + assign a persistent <emphasis>name</emphasis> to a branch. 15.309 + There always exists a branch named <literal>default</literal>. 15.310 + Even before you start naming branches yourself, you can find 15.311 + traces of the <literal>default</literal> branch if you look for 15.312 + them.</para> 15.313 + 15.314 + <para>As an example, when you run the <command role="hg-cmd">hg 15.315 + commit</command> command, and it pops up your editor so that 15.316 + you can enter a commit message, look for a line that contains 15.317 + the text <quote><literal>HG: branch default</literal></quote> at 15.318 + the bottom. This is telling you that your commit will occur on 15.319 + the branch named <literal>default</literal>.</para> 15.320 + 15.321 + <para>To start working with named branches, use the <command 15.322 + role="hg-cmd">hg branches</command> command. This command 15.323 + lists the named branches already present in your repository, 15.324 + telling you which changeset is the tip of each. <!-- 15.325 + &interaction.branch-named.branches; --> Since you haven't 15.326 + created any named branches yet, the only one that exists is 15.327 + <literal>default</literal>.</para> 15.328 + 15.329 + <para>To find out what the <quote>current</quote> branch is, run 15.330 + the <command role="hg-cmd">hg branch</command> command, giving 15.331 + it no arguments. This tells you what branch the parent of the 15.332 + current changeset is on. <!-- &interaction.branch-named.branch; 15.333 + --></para> 15.334 + 15.335 + <para>To create a new branch, run the <command role="hg-cmd">hg 15.336 + branch</command> command again. This time, give it one 15.337 + argument: the name of the branch you want to create. <!-- 15.338 + &interaction.branch-named.create; --></para> 15.339 + 15.340 + <para>After you've created a branch, you might wonder what effect 15.341 + the <command role="hg-cmd">hg branch</command> command has had. 15.342 + What do the <command role="hg-cmd">hg status</command> and 15.343 + <command role="hg-cmd">hg tip</command> commands report? <!-- 15.344 + &interaction.branch-named.status; --> Nothing has changed in the 15.345 + working directory, and there's been no new history created. As 15.346 + this suggests, running the <command role="hg-cmd">hg 15.347 + branch</command> command has no permanent effect; it only 15.348 + tells Mercurial what branch name to use the 15.349 + <emphasis>next</emphasis> time you commit a changeset.</para> 15.350 + 15.351 + <para>When you commit a change, Mercurial records the name of the 15.352 + branch on which you committed. Once you've switched from the 15.353 + <literal>default</literal> branch to another and committed, 15.354 + you'll see the name of the new branch show up in the output of 15.355 + <command role="hg-cmd">hg log</command>, <command 15.356 + role="hg-cmd">hg tip</command>, and other commands that 15.357 + display the same kind of output. <!-- 15.358 + &interaction.branch-named.commit; --> The <command 15.359 + role="hg-cmd">hg log</command>-like commands will print the 15.360 + branch name of every changeset that's not on the 15.361 + <literal>default</literal> branch. As a result, if you never 15.362 + use named branches, you'll never see this information.</para> 15.363 + 15.364 + <para>Once you've named a branch and committed a change with that 15.365 + name, every subsequent commit that descends from that change 15.366 + will inherit the same branch name. You can change the name of a 15.367 + branch at any time, using the <command role="hg-cmd">hg 15.368 + branch</command> command. <!-- 15.369 + &interaction.branch-named.rebranch; --> In practice, this is 15.370 + something you won't do very often, as branch names tend to have 15.371 + fairly long lifetimes. (This isn't a rule, just an 15.372 + observation.)</para> 15.373 + 15.374 + </sect1> 15.375 + <sect1> 15.376 + <title>Dealing with multiple named branches in a 15.377 + repository</title> 15.378 + 15.379 + <para>If you have more than one named branch in a repository, 15.380 + Mercurial will remember the branch that your working directory 15.381 + on when you start a command like <command role="hg-cmd">hg 15.382 + update</command> or <command role="hg-cmd">hg pull 15.383 + -u</command>. It will update the working directory to the tip 15.384 + of this branch, no matter what the <quote>repo-wide</quote> tip 15.385 + is. To update to a revision that's on a different named branch, 15.386 + you may need to use the <option role="hg-opt-update">-C</option> 15.387 + option to <command role="hg-cmd">hg update</command>.</para> 15.388 + 15.389 + <para>This behaviour is a little subtle, so let's see it in 15.390 + action. First, let's remind ourselves what branch we're 15.391 + currently on, and what branches are in our repository. <!-- 15.392 + &interaction.branch-named.parents; --> We're on the 15.393 + <literal>bar</literal> branch, but there also exists an older 15.394 + <command role="hg-cmd">hg foo</command> branch.</para> 15.395 + 15.396 + <para>We can <command role="hg-cmd">hg update</command> back and 15.397 + forth between the tips of the <literal>foo</literal> and 15.398 + <literal>bar</literal> branches without needing to use the 15.399 + <option role="hg-opt-update">-C</option> option, because this 15.400 + only involves going backwards and forwards linearly through our 15.401 + change history. <!-- &interaction.branch-named.update-switchy; 15.402 + --></para> 15.403 + 15.404 + <para>If we go back to the <literal>foo</literal> branch and then 15.405 + run <command role="hg-cmd">hg update</command>, it will keep us 15.406 + on <literal>foo</literal>, not move us to the tip of 15.407 + <literal>bar</literal>. <!-- 15.408 + &interaction.branch-named.update-nothing; --></para> 15.409 + 15.410 + <para>Committing a new change on the <literal>foo</literal> branch 15.411 + introduces a new head. <!-- 15.412 + &interaction.branch-named.foo-commit; --></para> 15.413 + 15.414 + </sect1> 15.415 + <sect1> 15.416 + <title>Branch names and merging</title> 15.417 + 15.418 + <para>As you've probably noticed, merges in Mercurial are not 15.419 + symmetrical. Let's say our repository has two heads, 17 and 23. 15.420 + If I <command role="hg-cmd">hg update</command> to 17 and then 15.421 + <command role="hg-cmd">hg merge</command> with 23, Mercurial 15.422 + records 17 as the first parent of the merge, and 23 as the 15.423 + second. Whereas if I <command role="hg-cmd">hg update</command> 15.424 + to 23 and then <command role="hg-cmd">hg merge</command> with 15.425 + 17, it records 23 as the first parent, and 17 as the 15.426 + second.</para> 15.427 + 15.428 + <para>This affects Mercurial's choice of branch name when you 15.429 + merge. After a merge, Mercurial will retain the branch name of 15.430 + the first parent when you commit the result of the merge. If 15.431 + your first parent's branch name is <literal>foo</literal>, and 15.432 + you merge with <literal>bar</literal>, the branch name will 15.433 + still be <literal>foo</literal> after you merge.</para> 15.434 + 15.435 + <para>It's not unusual for a repository to contain multiple heads, 15.436 + each with the same branch name. Let's say I'm working on the 15.437 + <literal>foo</literal> branch, and so are you. We commit 15.438 + different changes; I pull your changes; I now have two heads, 15.439 + each claiming to be on the <literal>foo</literal> branch. The 15.440 + result of a merge will be a single head on the 15.441 + <literal>foo</literal> branch, as you might hope.</para> 15.442 + 15.443 + <para>But if I'm working on the <literal>bar</literal> branch, and 15.444 + I merge work from the <literal>foo</literal> branch, the result 15.445 + will remain on the <literal>bar</literal> branch. <!-- 15.446 + &interaction.branch-named.merge; --></para> 15.447 + 15.448 + <para>To give a more concrete example, if I'm working on the 15.449 + <literal>bleeding-edge</literal> branch, and I want to bring in 15.450 + the latest fixes from the <literal>stable</literal> branch, 15.451 + Mercurial will choose the <quote>right</quote> 15.452 + (<literal>bleeding-edge</literal>) branch name when I pull and 15.453 + merge from <literal>stable</literal>.</para> 15.454 + 15.455 + </sect1> 15.456 + <sect1> 15.457 + <title>Branch naming is generally useful</title> 15.458 + 15.459 + <para>You shouldn't think of named branches as applicable only to 15.460 + situations where you have multiple long-lived branches 15.461 + cohabiting in a single repository. They're very useful even in 15.462 + the one-branch-per-repository case.</para> 15.463 + 15.464 + <para>In the simplest case, giving a name to each branch gives you 15.465 + a permanent record of which branch a changeset originated on. 15.466 + This gives you more context when you're trying to follow the 15.467 + history of a long-lived branchy project.</para> 15.468 + 15.469 + <para>If you're working with shared repositories, you can set up a 15.470 + <literal role="hook">pretxnchangegroup</literal> hook on each 15.471 + that will block incoming changes that have the 15.472 + <quote>wrong</quote> branch name. This provides a simple, but 15.473 + effective, defence against people accidentally pushing changes 15.474 + from a <quote>bleeding edge</quote> branch to a 15.475 + <quote>stable</quote> branch. Such a hook might look like this 15.476 + inside the shared repo's <filename role="special"> 15.477 + /.hgrc</filename>.</para> 15.478 + <programlisting>[hooks] pretxnchangegroup.branch = hg heads 15.479 + --template '{branches} ' | grep mybranch</programlisting> 15.480 + 15.481 + </sect1> 15.482 +</chapter> 15.483 + 15.484 +<!-- 15.485 +local variables: 15.486 +sgml-parent-document: ("00book.xml" "book" "chapter") 15.487 +end: 15.488 +-->
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/en/ch09-undo.xml Wed Feb 18 00:22:09 2009 -0800 16.3 @@ -0,0 +1,997 @@ 16.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 16.5 + 16.6 +<chapter id="chap:undo"> 16.7 + <title>Finding and fixing your mistakes</title> 16.8 + 16.9 + <para>To err might be human, but to really handle the consequences 16.10 + well takes a top-notch revision control system. In this chapter, 16.11 + we'll discuss some of the techniques you can use when you find 16.12 + that a problem has crept into your project. Mercurial has some 16.13 + highly capable features that will help you to isolate the sources 16.14 + of problems, and to handle them appropriately.</para> 16.15 + 16.16 + <sect1> 16.17 + <title>Erasing local history</title> 16.18 + 16.19 + <sect2> 16.20 + <title>The accidental commit</title> 16.21 + 16.22 + <para>I have the occasional but persistent problem of typing 16.23 + rather more quickly than I can think, which sometimes results 16.24 + in me committing a changeset that is either incomplete or 16.25 + plain wrong. In my case, the usual kind of incomplete 16.26 + changeset is one in which I've created a new source file, but 16.27 + forgotten to <command role="hg-cmd">hg add</command> it. A 16.28 + <quote>plain wrong</quote> changeset is not as common, but no 16.29 + less annoying.</para> 16.30 + 16.31 + </sect2> 16.32 + <sect2 id="sec:undo:rollback"> 16.33 + <title>Rolling back a transaction</title> 16.34 + 16.35 + <para>In section <xref linkend="sec:concepts:txn"/>, I mentioned 16.36 + that Mercurial treats each modification of a repository as a 16.37 + <emphasis>transaction</emphasis>. Every time you commit a 16.38 + changeset or pull changes from another repository, Mercurial 16.39 + remembers what you did. You can undo, or <emphasis>roll 16.40 + back</emphasis>, exactly one of these actions using the 16.41 + <command role="hg-cmd">hg rollback</command> command. (See 16.42 + section <xref linkend="sec:undo:rollback-after-push"/> for an 16.43 + important caveat about the use of this command.)</para> 16.44 + 16.45 + <para>Here's a mistake that I often find myself making: 16.46 + committing a change in which I've created a new file, but 16.47 + forgotten to <command role="hg-cmd">hg add</command> it. <!-- 16.48 + &interaction.rollback.commit; --> Looking at the output of 16.49 + <command role="hg-cmd">hg status</command> after the commit 16.50 + immediately confirms the error. <!-- 16.51 + &interaction.rollback.status; --> The commit captured the 16.52 + changes to the file <filename>a</filename>, but not the new 16.53 + file <filename>b</filename>. If I were to push this changeset 16.54 + to a repository that I shared with a colleague, the chances 16.55 + are high that something in <filename>a</filename> would refer 16.56 + to <filename>b</filename>, which would not be present in their 16.57 + repository when they pulled my changes. I would thus become 16.58 + the object of some indignation.</para> 16.59 + 16.60 + <para>However, luck is with me&emdash;I've caught my error 16.61 + before I pushed the changeset. I use the <command 16.62 + role="hg-cmd">hg rollback</command> command, and Mercurial 16.63 + makes that last changeset vanish. <!-- 16.64 + &interaction.rollback.rollback; --> Notice that the changeset 16.65 + is no longer present in the repository's history, and the 16.66 + working directory once again thinks that the file 16.67 + <filename>a</filename> is modified. The commit and rollback 16.68 + have left the working directory exactly as it was prior to the 16.69 + commit; the changeset has been completely erased. I can now 16.70 + safely <command role="hg-cmd">hg add</command> the file 16.71 + <filename>b</filename>, and rerun my commit. <!-- 16.72 + &interaction.rollback.add; --></para> 16.73 + 16.74 + </sect2> 16.75 + <sect2> 16.76 + <title>The erroneous pull</title> 16.77 + 16.78 + <para>It's common practice with Mercurial to maintain separate 16.79 + development branches of a project in different repositories. 16.80 + Your development team might have one shared repository for 16.81 + your project's <quote>0.9</quote> release, and another, 16.82 + containing different changes, for the <quote>1.0</quote> 16.83 + release.</para> 16.84 + 16.85 + <para>Given this, you can imagine that the consequences could be 16.86 + messy if you had a local <quote>0.9</quote> repository, and 16.87 + accidentally pulled changes from the shared <quote>1.0</quote> 16.88 + repository into it. At worst, you could be paying 16.89 + insufficient attention, and push those changes into the shared 16.90 + <quote>0.9</quote> tree, confusing your entire team (but don't 16.91 + worry, we'll return to this horror scenario later). However, 16.92 + it's more likely that you'll notice immediately, because 16.93 + Mercurial will display the URL it's pulling from, or you will 16.94 + see it pull a suspiciously large number of changes into the 16.95 + repository.</para> 16.96 + 16.97 + <para>The <command role="hg-cmd">hg rollback</command> command 16.98 + will work nicely to expunge all of the changesets that you 16.99 + just pulled. Mercurial groups all changes from one <command 16.100 + role="hg-cmd">hg pull</command> into a single transaction, 16.101 + so one <command role="hg-cmd">hg rollback</command> is all you 16.102 + need to undo this mistake.</para> 16.103 + 16.104 + </sect2> 16.105 + <sect2 id="sec:undo:rollback-after-push"> 16.106 + <title>Rolling back is useless once you've pushed</title> 16.107 + 16.108 + <para>The value of the <command role="hg-cmd">hg 16.109 + rollback</command> command drops to zero once you've pushed 16.110 + your changes to another repository. Rolling back a change 16.111 + makes it disappear entirely, but <emphasis>only</emphasis> in 16.112 + the repository in which you perform the <command 16.113 + role="hg-cmd">hg rollback</command>. Because a rollback 16.114 + eliminates history, there's no way for the disappearance of a 16.115 + change to propagate between repositories.</para> 16.116 + 16.117 + <para>If you've pushed a change to another 16.118 + repository&emdash;particularly if it's a shared 16.119 + repository&emdash;it has essentially <quote>escaped into the 16.120 + wild,</quote> and you'll have to recover from your mistake 16.121 + in a different way. What will happen if you push a changeset 16.122 + somewhere, then roll it back, then pull from the repository 16.123 + you pushed to, is that the changeset will reappear in your 16.124 + repository.</para> 16.125 + 16.126 + <para>(If you absolutely know for sure that the change you want 16.127 + to roll back is the most recent change in the repository that 16.128 + you pushed to, <emphasis>and</emphasis> you know that nobody 16.129 + else could have pulled it from that repository, you can roll 16.130 + back the changeset there, too, but you really should really 16.131 + not rely on this working reliably. If you do this, sooner or 16.132 + later a change really will make it into a repository that you 16.133 + don't directly control (or have forgotten about), and come 16.134 + back to bite you.)</para> 16.135 + 16.136 + </sect2> 16.137 + <sect2> 16.138 + <title>You can only roll back once</title> 16.139 + 16.140 + <para>Mercurial stores exactly one transaction in its 16.141 + transaction log; that transaction is the most recent one that 16.142 + occurred in the repository. This means that you can only roll 16.143 + back one transaction. If you expect to be able to roll back 16.144 + one transaction, then its predecessor, this is not the 16.145 + behaviour you will get. <!-- &interaction.rollback.twice; --> 16.146 + Once you've rolled back one transaction in a repository, you 16.147 + can't roll back again in that repository until you perform 16.148 + another commit or pull.</para> 16.149 + 16.150 + </sect2> 16.151 + </sect1> 16.152 + <sect1> 16.153 + <title>Reverting the mistaken change</title> 16.154 + 16.155 + <para>If you make a modification to a file, and decide that you 16.156 + really didn't want to change the file at all, and you haven't 16.157 + yet committed your changes, the <command role="hg-cmd">hg 16.158 + revert</command> command is the one you'll need. It looks at 16.159 + the changeset that's the parent of the working directory, and 16.160 + restores the contents of the file to their state as of that 16.161 + changeset. (That's a long-winded way of saying that, in the 16.162 + normal case, it undoes your modifications.)</para> 16.163 + 16.164 + <para>Let's illustrate how the <command role="hg-cmd">hg 16.165 + revert</command> command works with yet another small example. 16.166 + We'll begin by modifying a file that Mercurial is already 16.167 + tracking. <!-- &interaction.daily.revert.modify; --> If we don't 16.168 + want that change, we can simply <command role="hg-cmd">hg 16.169 + revert</command> the file. <!-- 16.170 + &interaction.daily.revert.unmodify; --> The <command 16.171 + role="hg-cmd">hg revert</command> command provides us with an 16.172 + extra degree of safety by saving our modified file with a 16.173 + <filename>.orig</filename> extension. <!-- 16.174 + &interaction.daily.revert.status; --></para> 16.175 + 16.176 + <para>Here is a summary of the cases that the <command 16.177 + role="hg-cmd">hg revert</command> command can deal with. We 16.178 + will describe each of these in more detail in the section that 16.179 + follows.</para> 16.180 + <itemizedlist> 16.181 + <listitem><para>If you modify a file, it will restore the file 16.182 + to its unmodified state.</para> 16.183 + </listitem> 16.184 + <listitem><para>If you <command role="hg-cmd">hg add</command> a 16.185 + file, it will undo the <quote>added</quote> state of the 16.186 + file, but leave the file itself untouched.</para> 16.187 + </listitem> 16.188 + <listitem><para>If you delete a file without telling Mercurial, 16.189 + it will restore the file to its unmodified contents.</para> 16.190 + </listitem> 16.191 + <listitem><para>If you use the <command role="hg-cmd">hg 16.192 + remove</command> command to remove a file, it will undo 16.193 + the <quote>removed</quote> state of the file, and restore 16.194 + the file to its unmodified contents.</para> 16.195 + </listitem></itemizedlist> 16.196 + 16.197 + <sect2 id="sec:undo:mgmt"> 16.198 + <title>File management errors</title> 16.199 + 16.200 + <para>The <command role="hg-cmd">hg revert</command> command is 16.201 + useful for more than just modified files. It lets you reverse 16.202 + the results of all of Mercurial's file management 16.203 + commands&emdash;<command role="hg-cmd">hg add</command>, 16.204 + <command role="hg-cmd">hg remove</command>, and so on.</para> 16.205 + 16.206 + <para>If you <command role="hg-cmd">hg add</command> a file, 16.207 + then decide that in fact you don't want Mercurial to track it, 16.208 + use <command role="hg-cmd">hg revert</command> to undo the 16.209 + add. Don't worry; Mercurial will not modify the file in any 16.210 + way. It will just <quote>unmark</quote> the file. <!-- 16.211 + &interaction.daily.revert.add; --></para> 16.212 + 16.213 + <para>Similarly, if you ask Mercurial to <command 16.214 + role="hg-cmd">hg remove</command> a file, you can use 16.215 + <command role="hg-cmd">hg revert</command> to restore it to 16.216 + the contents it had as of the parent of the working directory. 16.217 + <!-- &interaction.daily.revert.remove; --> This works just as 16.218 + well for a file that you deleted by hand, without telling 16.219 + Mercurial (recall that in Mercurial terminology, this kind of 16.220 + file is called <quote>missing</quote>). <!-- 16.221 + &interaction.daily.revert.missing; --></para> 16.222 + 16.223 + <para>If you revert a <command role="hg-cmd">hg copy</command>, 16.224 + the copied-to file remains in your working directory 16.225 + afterwards, untracked. Since a copy doesn't affect the 16.226 + copied-from file in any way, Mercurial doesn't do anything 16.227 + with the copied-from file. <!-- 16.228 + &interaction.daily.revert.copy; --></para> 16.229 + 16.230 + <sect3> 16.231 + <title>A slightly special case: reverting a rename</title> 16.232 + 16.233 + <para>If you <command role="hg-cmd">hg rename</command> a 16.234 + file, there is one small detail that you should remember. 16.235 + When you <command role="hg-cmd">hg revert</command> a 16.236 + rename, it's not enough to provide the name of the 16.237 + renamed-to file, as you can see here. <!-- 16.238 + &interaction.daily.revert.rename; --> As you can see from 16.239 + the output of <command role="hg-cmd">hg status</command>, 16.240 + the renamed-to file is no longer identified as added, but 16.241 + the renamed-<emphasis>from</emphasis> file is still removed! 16.242 + This is counter-intuitive (at least to me), but at least 16.243 + it's easy to deal with. <!-- 16.244 + &interaction.daily.revert.rename-orig; --> So remember, to 16.245 + revert a <command role="hg-cmd">hg rename</command>, you 16.246 + must provide <emphasis>both</emphasis> the source and 16.247 + destination names.</para> 16.248 + 16.249 + <para>% TODO: the output doesn't look like it will be 16.250 + removed!</para> 16.251 + 16.252 + <para>(By the way, if you rename a file, then modify the 16.253 + renamed-to file, then revert both components of the rename, 16.254 + when Mercurial restores the file that was removed as part of 16.255 + the rename, it will be unmodified. If you need the 16.256 + modifications in the renamed-to file to show up in the 16.257 + renamed-from file, don't forget to copy them over.)</para> 16.258 + 16.259 + <para>These fiddly aspects of reverting a rename arguably 16.260 + constitute a small bug in Mercurial.</para> 16.261 + 16.262 + </sect3> 16.263 + </sect2> 16.264 + </sect1> 16.265 + <sect1> 16.266 + <title>Dealing with committed changes</title> 16.267 + 16.268 + <para>Consider a case where you have committed a change $a$, and 16.269 + another change $b$ on top of it; you then realise that change 16.270 + $a$ was incorrect. Mercurial lets you <quote>back out</quote> 16.271 + an entire changeset automatically, and building blocks that let 16.272 + you reverse part of a changeset by hand.</para> 16.273 + 16.274 + <para>Before you read this section, here's something to keep in 16.275 + mind: the <command role="hg-cmd">hg backout</command> command 16.276 + undoes changes by <emphasis>adding</emphasis> history, not by 16.277 + modifying or erasing it. It's the right tool to use if you're 16.278 + fixing bugs, but not if you're trying to undo some change that 16.279 + has catastrophic consequences. To deal with those, see section 16.280 + <xref linkend="sec:undo:aaaiiieee"/>.</para> 16.281 + 16.282 + <sect2> 16.283 + <title>Backing out a changeset</title> 16.284 + 16.285 + <para>The <command role="hg-cmd">hg backout</command> command 16.286 + lets you <quote>undo</quote> the effects of an entire 16.287 + changeset in an automated fashion. Because Mercurial's 16.288 + history is immutable, this command <emphasis>does 16.289 + not</emphasis> get rid of the changeset you want to undo. 16.290 + Instead, it creates a new changeset that 16.291 + <emphasis>reverses</emphasis> the effect of the to-be-undone 16.292 + changeset.</para> 16.293 + 16.294 + <para>The operation of the <command role="hg-cmd">hg 16.295 + backout</command> command is a little intricate, so let's 16.296 + illustrate it with some examples. First, we'll create a 16.297 + repository with some simple changes. <!-- 16.298 + &interaction.backout.init; --></para> 16.299 + 16.300 + <para>The <command role="hg-cmd">hg backout</command> command 16.301 + takes a single changeset ID as its argument; this is the 16.302 + changeset to back out. Normally, <command role="hg-cmd">hg 16.303 + backout</command> will drop you into a text editor to write 16.304 + a commit message, so you can record why you're backing the 16.305 + change out. In this example, we provide a commit message on 16.306 + the command line using the <option 16.307 + role="hg-opt-backout">-m</option> option.</para> 16.308 + 16.309 + </sect2> 16.310 + <sect2> 16.311 + <title>Backing out the tip changeset</title> 16.312 + 16.313 + <para>We're going to start by backing out the last changeset we 16.314 + committed. <!-- &interaction.backout.simple; --> You can see 16.315 + that the second line from <filename>myfile</filename> is no 16.316 + longer present. Taking a look at the output of <command 16.317 + role="hg-cmd">hg log</command> gives us an idea of what the 16.318 + <command role="hg-cmd">hg backout</command> command has done. 16.319 + <!-- &interaction.backout.simple.log; --> Notice that the new 16.320 + changeset that <command role="hg-cmd">hg backout</command> has 16.321 + created is a child of the changeset we backed out. It's 16.322 + easier to see this in figure <xref 16.323 + linkend="fig:undo:backout"/>, which presents a graphical 16.324 + view of the change history. As you can see, the history is 16.325 + nice and linear.</para> 16.326 + 16.327 + <informalfigure id="fig:undo:backout"> 16.328 + <mediaobject><imageobject><imagedata 16.329 + fileref="undo-simple"/></imageobject><textobject><phrase>XXX 16.330 + add text</phrase></textobject><caption><para>Backing out 16.331 + a change using the <command role="hg-cmd">hg 16.332 + backout</command> 16.333 + command</para></caption></mediaobject> 16.334 + 16.335 + </informalfigure> 16.336 + 16.337 + </sect2> 16.338 + <sect2> 16.339 + <title>Backing out a non-tip change</title> 16.340 + 16.341 + <para>If you want to back out a change other than the last one 16.342 + you committed, pass the <option 16.343 + role="hg-opt-backout">--merge</option> option to the 16.344 + <command role="hg-cmd">hg backout</command> command. <!-- 16.345 + &interaction.backout.non-tip.clone; --> This makes backing out 16.346 + any changeset a <quote>one-shot</quote> operation that's 16.347 + usually simple and fast. <!-- 16.348 + &interaction.backout.non-tip.backout; --></para> 16.349 + 16.350 + <para>If you take a look at the contents of 16.351 + <filename>myfile</filename> after the backout finishes, you'll 16.352 + see that the first and third changes are present, but not the 16.353 + second. <!-- &interaction.backout.non-tip.cat; --></para> 16.354 + 16.355 + <para>As the graphical history in figure <xref 16.356 + linkend="fig:undo:backout-non-tip"/> illustrates, Mercurial 16.357 + actually commits <emphasis>two</emphasis> changes in this kind 16.358 + of situation (the box-shaped nodes are the ones that Mercurial 16.359 + commits automatically). Before Mercurial begins the backout 16.360 + process, it first remembers what the current parent of the 16.361 + working directory is. It then backs out the target changeset, 16.362 + and commits that as a changeset. Finally, it merges back to 16.363 + the previous parent of the working directory, and commits the 16.364 + result of the merge.</para> 16.365 + 16.366 + <para>% TODO: to me it looks like mercurial doesn't commit the 16.367 + second merge automatically!</para> 16.368 + 16.369 + <informalfigure id="fig:undo:backout-non-tip"> 16.370 + <mediaobject><imageobject><imagedata 16.371 + fileref="undo-non-tip"/></imageobject><textobject><phrase>XXX 16.372 + add text</phrase></textobject><caption><para>Automated 16.373 + backout of a non-tip change using the <command 16.374 + role="hg-cmd">hg backout</command> 16.375 + command</para></caption></mediaobject> 16.376 + </informalfigure> 16.377 + 16.378 + <para>The result is that you end up <quote>back where you 16.379 + were</quote>, only with some extra history that undoes the 16.380 + effect of the changeset you wanted to back out.</para> 16.381 + 16.382 + <sect3> 16.383 + <title>Always use the <option 16.384 + role="hg-opt-backout">--merge</option> option</title> 16.385 + 16.386 + <para>In fact, since the <option 16.387 + role="hg-opt-backout">--merge</option> option will do the 16.388 + <quote>right thing</quote> whether or not the changeset 16.389 + you're backing out is the tip (i.e. it won't try to merge if 16.390 + it's backing out the tip, since there's no need), you should 16.391 + <emphasis>always</emphasis> use this option when you run the 16.392 + <command role="hg-cmd">hg backout</command> command.</para> 16.393 + 16.394 + </sect3> 16.395 + </sect2> 16.396 + <sect2> 16.397 + <title>Gaining more control of the backout process</title> 16.398 + 16.399 + <para>While I've recommended that you always use the <option 16.400 + role="hg-opt-backout">--merge</option> option when backing 16.401 + out a change, the <command role="hg-cmd">hg backout</command> 16.402 + command lets you decide how to merge a backout changeset. 16.403 + Taking control of the backout process by hand is something you 16.404 + will rarely need to do, but it can be useful to understand 16.405 + what the <command role="hg-cmd">hg backout</command> command 16.406 + is doing for you automatically. To illustrate this, let's 16.407 + clone our first repository, but omit the backout change that 16.408 + it contains.</para> 16.409 + 16.410 + <para><!-- &interaction.backout.manual.clone; --> As with our 16.411 + earlier example, We'll commit a third changeset, then back out 16.412 + its parent, and see what happens. <!-- 16.413 + &interaction.backout.manual.backout; --> Our new changeset is 16.414 + again a descendant of the changeset we backout out; it's thus 16.415 + a new head, <emphasis>not</emphasis> a descendant of the 16.416 + changeset that was the tip. The <command role="hg-cmd">hg 16.417 + backout</command> command was quite explicit in telling us 16.418 + this. <!-- &interaction.backout.manual.log; --></para> 16.419 + 16.420 + <para>Again, it's easier to see what has happened by looking at 16.421 + a graph of the revision history, in figure <xref 16.422 + linkend="fig:undo:backout-manual"/>. This makes it clear 16.423 + that when we use <command role="hg-cmd">hg backout</command> 16.424 + to back out a change other than the tip, Mercurial adds a new 16.425 + head to the repository (the change it committed is 16.426 + box-shaped).</para> 16.427 + 16.428 + <informalfigure id="fig:undo:backout-manual"> 16.429 + <mediaobject><imageobject><imagedata 16.430 + fileref="undo-manual"/></imageobject><textobject><phrase>XXX 16.431 + add text</phrase></textobject><caption><para>Backing out 16.432 + a change using the <command role="hg-cmd">hg 16.433 + backout</command> 16.434 + command</para></caption></mediaobject> 16.435 + 16.436 + </informalfigure> 16.437 + 16.438 + <para>After the <command role="hg-cmd">hg backout</command> 16.439 + command has completed, it leaves the new 16.440 + <quote>backout</quote> changeset as the parent of the working 16.441 + directory. <!-- &interaction.backout.manual.parents; --> Now 16.442 + we have two isolated sets of changes. <!-- 16.443 + &interaction.backout.manual.heads; --></para> 16.444 + 16.445 + <para>Let's think about what we expect to see as the contents of 16.446 + <filename>myfile</filename> now. The first change should be 16.447 + present, because we've never backed it out. The second change 16.448 + should be missing, as that's the change we backed out. Since 16.449 + the history graph shows the third change as a separate head, 16.450 + we <emphasis>don't</emphasis> expect to see the third change 16.451 + present in <filename>myfile</filename>. <!-- 16.452 + &interaction.backout.manual.cat; --> To get the third change 16.453 + back into the file, we just do a normal merge of our two 16.454 + heads. <!-- &interaction.backout.manual.merge; --> Afterwards, 16.455 + the graphical history of our repository looks like figure 16.456 + <xref linkend="fig:undo:backout-manual-merge"/>.</para> 16.457 + 16.458 + <informalfigure id="fig:undo:backout-manual-merge"> 16.459 + <mediaobject><imageobject><imagedata 16.460 + fileref="undo-manual-merge"/></imageobject><textobject><phrase>XXX 16.461 + add text</phrase></textobject><caption><para>Manually 16.462 + merging a backout change</para></caption></mediaobject> 16.463 + 16.464 + </informalfigure> 16.465 + 16.466 + </sect2> 16.467 + <sect2> 16.468 + <title>Why <command role="hg-cmd">hg backout</command> works as 16.469 + it does</title> 16.470 + 16.471 + <para>Here's a brief description of how the <command 16.472 + role="hg-cmd">hg backout</command> command works.</para> 16.473 + <orderedlist> 16.474 + <listitem><para>It ensures that the working directory is 16.475 + <quote>clean</quote>, i.e. that the output of <command 16.476 + role="hg-cmd">hg status</command> would be empty.</para> 16.477 + </listitem> 16.478 + <listitem><para>It remembers the current parent of the working 16.479 + directory. Let's call this changeset 16.480 + <literal>orig</literal></para> 16.481 + </listitem> 16.482 + <listitem><para>It does the equivalent of a <command 16.483 + role="hg-cmd">hg update</command> to sync the working 16.484 + directory to the changeset you want to back out. Let's 16.485 + call this changeset <literal>backout</literal></para> 16.486 + </listitem> 16.487 + <listitem><para>It finds the parent of that changeset. Let's 16.488 + call that changeset <literal>parent</literal>.</para> 16.489 + </listitem> 16.490 + <listitem><para>For each file that the 16.491 + <literal>backout</literal> changeset affected, it does the 16.492 + equivalent of a <command role="hg-cmd">hg revert -r 16.493 + parent</command> on that file, to restore it to the 16.494 + contents it had before that changeset was 16.495 + committed.</para> 16.496 + </listitem> 16.497 + <listitem><para>It commits the result as a new changeset. 16.498 + This changeset has <literal>backout</literal> as its 16.499 + parent.</para> 16.500 + </listitem> 16.501 + <listitem><para>If you specify <option 16.502 + role="hg-opt-backout">--merge</option> on the command 16.503 + line, it merges with <literal>orig</literal>, and commits 16.504 + the result of the merge.</para> 16.505 + </listitem></orderedlist> 16.506 + 16.507 + <para>An alternative way to implement the <command 16.508 + role="hg-cmd">hg backout</command> command would be to 16.509 + <command role="hg-cmd">hg export</command> the 16.510 + to-be-backed-out changeset as a diff, then use the <option 16.511 + role="cmd-opt-patch">--reverse</option> option to the 16.512 + <command>patch</command> command to reverse the effect of the 16.513 + change without fiddling with the working directory. This 16.514 + sounds much simpler, but it would not work nearly as 16.515 + well.</para> 16.516 + 16.517 + <para>The reason that <command role="hg-cmd">hg 16.518 + backout</command> does an update, a commit, a merge, and 16.519 + another commit is to give the merge machinery the best chance 16.520 + to do a good job when dealing with all the changes 16.521 + <emphasis>between</emphasis> the change you're backing out and 16.522 + the current tip.</para> 16.523 + 16.524 + <para>If you're backing out a changeset that's 100 revisions 16.525 + back in your project's history, the chances that the 16.526 + <command>patch</command> command will be able to apply a 16.527 + reverse diff cleanly are not good, because intervening changes 16.528 + are likely to have <quote>broken the context</quote> that 16.529 + <command>patch</command> uses to determine whether it can 16.530 + apply a patch (if this sounds like gibberish, see <xref 16.531 + linkend="sec:mq:patch"/> for a 16.532 + discussion of the <command>patch</command> command). Also, 16.533 + Mercurial's merge machinery will handle files and directories 16.534 + being renamed, permission changes, and modifications to binary 16.535 + files, none of which <command>patch</command> can deal 16.536 + with.</para> 16.537 + 16.538 + </sect2> 16.539 + </sect1> 16.540 + <sect1 id="sec:undo:aaaiiieee"> 16.541 + <title>Changes that should never have been</title> 16.542 + 16.543 + <para>Most of the time, the <command role="hg-cmd">hg 16.544 + backout</command> command is exactly what you need if you want 16.545 + to undo the effects of a change. It leaves a permanent record 16.546 + of exactly what you did, both when committing the original 16.547 + changeset and when you cleaned up after it.</para> 16.548 + 16.549 + <para>On rare occasions, though, you may find that you've 16.550 + committed a change that really should not be present in the 16.551 + repository at all. For example, it would be very unusual, and 16.552 + usually considered a mistake, to commit a software project's 16.553 + object files as well as its source files. Object files have 16.554 + almost no intrinsic value, and they're <emphasis>big</emphasis>, 16.555 + so they increase the size of the repository and the amount of 16.556 + time it takes to clone or pull changes.</para> 16.557 + 16.558 + <para>Before I discuss the options that you have if you commit a 16.559 + <quote>brown paper bag</quote> change (the kind that's so bad 16.560 + that you want to pull a brown paper bag over your head), let me 16.561 + first discuss some approaches that probably won't work.</para> 16.562 + 16.563 + <para>Since Mercurial treats history as accumulative&emdash;every 16.564 + change builds on top of all changes that preceded it&emdash;you 16.565 + generally can't just make disastrous changes disappear. The one 16.566 + exception is when you've just committed a change, and it hasn't 16.567 + been pushed or pulled into another repository. That's when you 16.568 + can safely use the <command role="hg-cmd">hg rollback</command> 16.569 + command, as I detailed in section <xref 16.570 + linkend="sec:undo:rollback"/>.</para> 16.571 + 16.572 + <para>After you've pushed a bad change to another repository, you 16.573 + <emphasis>could</emphasis> still use <command role="hg-cmd">hg 16.574 + rollback</command> to make your local copy of the change 16.575 + disappear, but it won't have the consequences you want. The 16.576 + change will still be present in the remote repository, so it 16.577 + will reappear in your local repository the next time you 16.578 + pull.</para> 16.579 + 16.580 + <para>If a situation like this arises, and you know which 16.581 + repositories your bad change has propagated into, you can 16.582 + <emphasis>try</emphasis> to get rid of the changeefrom 16.583 + <emphasis>every</emphasis> one of those repositories. This is, 16.584 + of course, not a satisfactory solution: if you miss even a 16.585 + single repository while you're expunging, the change is still 16.586 + <quote>in the wild</quote>, and could propagate further.</para> 16.587 + 16.588 + <para>If you've committed one or more changes 16.589 + <emphasis>after</emphasis> the change that you'd like to see 16.590 + disappear, your options are further reduced. Mercurial doesn't 16.591 + provide a way to <quote>punch a hole</quote> in history, leaving 16.592 + changesets intact.</para> 16.593 + 16.594 + <para>XXX This needs filling out. The 16.595 + <literal>hg-replay</literal> script in the 16.596 + <literal>examples</literal> directory works, but doesn't handle 16.597 + merge changesets. Kind of an important omission.</para> 16.598 + 16.599 + <sect2> 16.600 + <title>Protect yourself from <quote>escaped</quote> 16.601 + changes</title> 16.602 + 16.603 + <para>If you've committed some changes to your local repository 16.604 + and they've been pushed or pulled somewhere else, this isn't 16.605 + necessarily a disaster. You can protect yourself ahead of 16.606 + time against some classes of bad changeset. This is 16.607 + particularly easy if your team usually pulls changes from a 16.608 + central repository.</para> 16.609 + 16.610 + <para>By configuring some hooks on that repository to validate 16.611 + incoming changesets (see chapter <xref linkend="chap:hook"/>), 16.612 + you can 16.613 + automatically prevent some kinds of bad changeset from being 16.614 + pushed to the central repository at all. With such a 16.615 + configuration in place, some kinds of bad changeset will 16.616 + naturally tend to <quote>die out</quote> because they can't 16.617 + propagate into the central repository. Better yet, this 16.618 + happens without any need for explicit intervention.</para> 16.619 + 16.620 + <para>For instance, an incoming change hook that verifies that a 16.621 + changeset will actually compile can prevent people from 16.622 + inadvertantly <quote>breaking the build</quote>.</para> 16.623 + 16.624 + </sect2> 16.625 + </sect1> 16.626 + <sect1 id="sec:undo:bisect"> 16.627 + <title>Finding the source of a bug</title> 16.628 + 16.629 + <para>While it's all very well to be able to back out a changeset 16.630 + that introduced a bug, this requires that you know which 16.631 + changeset to back out. Mercurial provides an invaluable 16.632 + command, called <command role="hg-cmd">hg bisect</command>, that 16.633 + helps you to automate this process and accomplish it very 16.634 + efficiently.</para> 16.635 + 16.636 + <para>The idea behind the <command role="hg-cmd">hg 16.637 + bisect</command> command is that a changeset has introduced 16.638 + some change of behaviour that you can identify with a simple 16.639 + binary test. You don't know which piece of code introduced the 16.640 + change, but you know how to test for the presence of the bug. 16.641 + The <command role="hg-cmd">hg bisect</command> command uses your 16.642 + test to direct its search for the changeset that introduced the 16.643 + code that caused the bug.</para> 16.644 + 16.645 + <para>Here are a few scenarios to help you understand how you 16.646 + might apply this command.</para> 16.647 + <itemizedlist> 16.648 + <listitem><para>The most recent version of your software has a 16.649 + bug that you remember wasn't present a few weeks ago, but 16.650 + you don't know when it was introduced. Here, your binary 16.651 + test checks for the presence of that bug.</para> 16.652 + </listitem> 16.653 + <listitem><para>You fixed a bug in a rush, and now it's time to 16.654 + close the entry in your team's bug database. The bug 16.655 + database requires a changeset ID when you close an entry, 16.656 + but you don't remember which changeset you fixed the bug in. 16.657 + Once again, your binary test checks for the presence of the 16.658 + bug.</para> 16.659 + </listitem> 16.660 + <listitem><para>Your software works correctly, but runs 15% 16.661 + slower than the last time you measured it. You want to know 16.662 + which changeset introduced the performance regression. In 16.663 + this case, your binary test measures the performance of your 16.664 + software, to see whether it's <quote>fast</quote> or 16.665 + <quote>slow</quote>.</para> 16.666 + </listitem> 16.667 + <listitem><para>The sizes of the components of your project that 16.668 + you ship exploded recently, and you suspect that something 16.669 + changed in the way you build your project.</para> 16.670 + </listitem></itemizedlist> 16.671 + 16.672 + <para>From these examples, it should be clear that the <command 16.673 + role="hg-cmd">hg bisect</command> command is not useful only 16.674 + for finding the sources of bugs. You can use it to find any 16.675 + <quote>emergent property</quote> of a repository (anything that 16.676 + you can't find from a simple text search of the files in the 16.677 + tree) for which you can write a binary test.</para> 16.678 + 16.679 + <para>We'll introduce a little bit of terminology here, just to 16.680 + make it clear which parts of the search process are your 16.681 + responsibility, and which are Mercurial's. A 16.682 + <emphasis>test</emphasis> is something that 16.683 + <emphasis>you</emphasis> run when <command role="hg-cmd">hg 16.684 + bisect</command> chooses a changeset. A 16.685 + <emphasis>probe</emphasis> is what <command role="hg-cmd">hg 16.686 + bisect</command> runs to tell whether a revision is good. 16.687 + Finally, we'll use the word <quote>bisect</quote>, as both a 16.688 + noun and a verb, to stand in for the phrase <quote>search using 16.689 + the <command role="hg-cmd">hg bisect</command> 16.690 + command</quote>.</para> 16.691 + 16.692 + <para>One simple way to automate the searching process would be 16.693 + simply to probe every changeset. However, this scales poorly. 16.694 + If it took ten minutes to test a single changeset, and you had 16.695 + 10,000 changesets in your repository, the exhaustive approach 16.696 + would take on average 35 <emphasis>days</emphasis> to find the 16.697 + changeset that introduced a bug. Even if you knew that the bug 16.698 + was introduced by one of the last 500 changesets, and limited 16.699 + your search to those, you'd still be looking at over 40 hours to 16.700 + find the changeset that introduced your bug.</para> 16.701 + 16.702 + <para>What the <command role="hg-cmd">hg bisect</command> command 16.703 + does is use its knowledge of the <quote>shape</quote> of your 16.704 + project's revision history to perform a search in time 16.705 + proportional to the <emphasis>logarithm</emphasis> of the number 16.706 + of changesets to check (the kind of search it performs is called 16.707 + a dichotomic search). With this approach, searching through 16.708 + 10,000 changesets will take less than three hours, even at ten 16.709 + minutes per test (the search will require about 14 tests). 16.710 + Limit your search to the last hundred changesets, and it will 16.711 + take only about an hour (roughly seven tests).</para> 16.712 + 16.713 + <para>The <command role="hg-cmd">hg bisect</command> command is 16.714 + aware of the <quote>branchy</quote> nature of a Mercurial 16.715 + project's revision history, so it has no problems dealing with 16.716 + branches, merges, or multiple heads in a repository. It can 16.717 + prune entire branches of history with a single probe, which is 16.718 + how it operates so efficiently.</para> 16.719 + 16.720 + <sect2> 16.721 + <title>Using the <command role="hg-cmd">hg bisect</command> 16.722 + command</title> 16.723 + 16.724 + <para>Here's an example of <command role="hg-cmd">hg 16.725 + bisect</command> in action.</para> 16.726 + 16.727 + <note> 16.728 + <para> In versions 0.9.5 and earlier of Mercurial, <command 16.729 + role="hg-cmd">hg bisect</command> was not a core command: 16.730 + it was distributed with Mercurial as an extension. This 16.731 + section describes the built-in command, not the old 16.732 + extension.</para> 16.733 + </note> 16.734 + 16.735 + <para>Now let's create a repository, so that we can try out the 16.736 + <command role="hg-cmd">hg bisect</command> command in 16.737 + isolation. <!-- &interaction.bisect.init; --> We'll simulate a 16.738 + project that has a bug in it in a simple-minded way: create 16.739 + trivial changes in a loop, and nominate one specific change 16.740 + that will have the <quote>bug</quote>. This loop creates 35 16.741 + changesets, each adding a single file to the repository. 16.742 + We'll represent our <quote>bug</quote> with a file that 16.743 + contains the text <quote>i have a gub</quote>. <!-- 16.744 + &interaction.bisect.commits; --></para> 16.745 + 16.746 + <para>The next thing that we'd like to do is figure out how to 16.747 + use the <command role="hg-cmd">hg bisect</command> command. 16.748 + We can use Mercurial's normal built-in help mechanism for 16.749 + this. <!-- &interaction.bisect.help; --></para> 16.750 + 16.751 + <para>The <command role="hg-cmd">hg bisect</command> command 16.752 + works in steps. Each step proceeds as follows.</para> 16.753 + <orderedlist> 16.754 + <listitem><para>You run your binary test.</para> 16.755 + <itemizedlist> 16.756 + <listitem><para>If the test succeeded, you tell <command 16.757 + role="hg-cmd">hg bisect</command> by running the 16.758 + <command role="hg-cmd">hg bisect good</command> 16.759 + command.</para> 16.760 + </listitem> 16.761 + <listitem><para>If it failed, run the <command 16.762 + role="hg-cmd">hg bisect bad</command> 16.763 + command.</para></listitem></itemizedlist> 16.764 + </listitem> 16.765 + <listitem><para>The command uses your information to decide 16.766 + which changeset to test next.</para> 16.767 + </listitem> 16.768 + <listitem><para>It updates the working directory to that 16.769 + changeset, and the process begins again.</para> 16.770 + </listitem></orderedlist> 16.771 + <para>The process ends when <command role="hg-cmd">hg 16.772 + bisect</command> identifies a unique changeset that marks 16.773 + the point where your test transitioned from 16.774 + <quote>succeeding</quote> to <quote>failing</quote>.</para> 16.775 + 16.776 + <para>To start the search, we must run the <command 16.777 + role="hg-cmd">hg bisect --reset</command> command. <!-- 16.778 + &interaction.bisect.search.init; --></para> 16.779 + 16.780 + <para>In our case, the binary test we use is simple: we check to 16.781 + see if any file in the repository contains the string <quote>i 16.782 + have a gub</quote>. If it does, this changeset contains the 16.783 + change that <quote>caused the bug</quote>. By convention, a 16.784 + changeset that has the property we're searching for is 16.785 + <quote>bad</quote>, while one that doesn't is 16.786 + <quote>good</quote>.</para> 16.787 + 16.788 + <para>Most of the time, the revision to which the working 16.789 + directory is synced (usually the tip) already exhibits the 16.790 + problem introduced by the buggy change, so we'll mark it as 16.791 + <quote>bad</quote>. <!-- &interaction.bisect.search.bad-init; 16.792 + --></para> 16.793 + 16.794 + <para>Our next task is to nominate a changeset that we know 16.795 + <emphasis>doesn't</emphasis> have the bug; the <command 16.796 + role="hg-cmd">hg bisect</command> command will 16.797 + <quote>bracket</quote> its search between the first pair of 16.798 + good and bad changesets. In our case, we know that revision 16.799 + 10 didn't have the bug. (I'll have more words about choosing 16.800 + the first <quote>good</quote> changeset later.) <!-- 16.801 + &interaction.bisect.search.good-init; --></para> 16.802 + 16.803 + <para>Notice that this command printed some output.</para> 16.804 + <itemizedlist> 16.805 + <listitem><para>It told us how many changesets it must 16.806 + consider before it can identify the one that introduced 16.807 + the bug, and how many tests that will require.</para> 16.808 + </listitem> 16.809 + <listitem><para>It updated the working directory to the next 16.810 + changeset to test, and told us which changeset it's 16.811 + testing.</para> 16.812 + </listitem></itemizedlist> 16.813 + 16.814 + <para>We now run our test in the working directory. We use the 16.815 + <command>grep</command> command to see if our 16.816 + <quote>bad</quote> file is present in the working directory. 16.817 + If it is, this revision is bad; if not, this revision is good. 16.818 + <!-- &interaction.bisect.search.step1; --></para> 16.819 + 16.820 + <para>This test looks like a perfect candidate for automation, 16.821 + so let's turn it into a shell function. <!-- 16.822 + &interaction.bisect.search.mytest; --> We can now run an 16.823 + entire test step with a single command, 16.824 + <literal>mytest</literal>. <!-- 16.825 + &interaction.bisect.search.step2; --> A few more invocations 16.826 + of our canned test step command, and we're done. <!-- 16.827 + &interaction.bisect.search.rest; --></para> 16.828 + 16.829 + <para>Even though we had 40 changesets to search through, the 16.830 + <command role="hg-cmd">hg bisect</command> command let us find 16.831 + the changeset that introduced our <quote>bug</quote> with only 16.832 + five tests. Because the number of tests that the <command 16.833 + role="hg-cmd">hg bisect</command> command performs grows 16.834 + logarithmically with the number of changesets to search, the 16.835 + advantage that it has over the <quote>brute force</quote> 16.836 + search approach increases with every changeset you add.</para> 16.837 + 16.838 + </sect2> 16.839 + <sect2> 16.840 + <title>Cleaning up after your search</title> 16.841 + 16.842 + <para>When you're finished using the <command role="hg-cmd">hg 16.843 + bisect</command> command in a repository, you can use the 16.844 + <command role="hg-cmd">hg bisect reset</command> command to 16.845 + drop the information it was using to drive your search. The 16.846 + command doesn't use much space, so it doesn't matter if you 16.847 + forget to run this command. However, <command 16.848 + role="hg-cmd">hg bisect</command> won't let you start a new 16.849 + search in that repository until you do a <command 16.850 + role="hg-cmd">hg bisect reset</command>. <!-- 16.851 + &interaction.bisect.search.reset; --></para> 16.852 + 16.853 + </sect2> 16.854 + </sect1> 16.855 + <sect1> 16.856 + <title>Tips for finding bugs effectively</title> 16.857 + 16.858 + <sect2> 16.859 + <title>Give consistent input</title> 16.860 + 16.861 + <para>The <command role="hg-cmd">hg bisect</command> command 16.862 + requires that you correctly report the result of every test 16.863 + you perform. If you tell it that a test failed when it really 16.864 + succeeded, it <emphasis>might</emphasis> be able to detect the 16.865 + inconsistency. If it can identify an inconsistency in your 16.866 + reports, it will tell you that a particular changeset is both 16.867 + good and bad. However, it can't do this perfectly; it's about 16.868 + as likely to report the wrong changeset as the source of the 16.869 + bug.</para> 16.870 + 16.871 + </sect2> 16.872 + <sect2> 16.873 + <title>Automate as much as possible</title> 16.874 + 16.875 + <para>When I started using the <command role="hg-cmd">hg 16.876 + bisect</command> command, I tried a few times to run my 16.877 + tests by hand, on the command line. This is an approach that 16.878 + I, at least, am not suited to. After a few tries, I found 16.879 + that I was making enough mistakes that I was having to restart 16.880 + my searches several times before finally getting correct 16.881 + results.</para> 16.882 + 16.883 + <para>My initial problems with driving the <command 16.884 + role="hg-cmd">hg bisect</command> command by hand occurred 16.885 + even with simple searches on small repositories; if the 16.886 + problem you're looking for is more subtle, or the number of 16.887 + tests that <command role="hg-cmd">hg bisect</command> must 16.888 + perform increases, the likelihood of operator error ruining 16.889 + the search is much higher. Once I started automating my 16.890 + tests, I had much better results.</para> 16.891 + 16.892 + <para>The key to automated testing is twofold:</para> 16.893 + <itemizedlist> 16.894 + <listitem><para>always test for the same symptom, and</para> 16.895 + </listitem> 16.896 + <listitem><para>always feed consistent input to the <command 16.897 + role="hg-cmd">hg bisect</command> command.</para> 16.898 + </listitem></itemizedlist> 16.899 + <para>In my tutorial example above, the <command>grep</command> 16.900 + command tests for the symptom, and the <literal>if</literal> 16.901 + statement takes the result of this check and ensures that we 16.902 + always feed the same input to the <command role="hg-cmd">hg 16.903 + bisect</command> command. The <literal>mytest</literal> 16.904 + function marries these together in a reproducible way, so that 16.905 + every test is uniform and consistent.</para> 16.906 + 16.907 + </sect2> 16.908 + <sect2> 16.909 + <title>Check your results</title> 16.910 + 16.911 + <para>Because the output of a <command role="hg-cmd">hg 16.912 + bisect</command> search is only as good as the input you 16.913 + give it, don't take the changeset it reports as the absolute 16.914 + truth. A simple way to cross-check its report is to manually 16.915 + run your test at each of the following changesets:</para> 16.916 + <itemizedlist> 16.917 + <listitem><para>The changeset that it reports as the first bad 16.918 + revision. Your test should still report this as 16.919 + bad.</para> 16.920 + </listitem> 16.921 + <listitem><para>The parent of that changeset (either parent, 16.922 + if it's a merge). Your test should report this changeset 16.923 + as good.</para> 16.924 + </listitem> 16.925 + <listitem><para>A child of that changeset. Your test should 16.926 + report this changeset as bad.</para> 16.927 + </listitem></itemizedlist> 16.928 + 16.929 + </sect2> 16.930 + <sect2> 16.931 + <title>Beware interference between bugs</title> 16.932 + 16.933 + <para>It's possible that your search for one bug could be 16.934 + disrupted by the presence of another. For example, let's say 16.935 + your software crashes at revision 100, and worked correctly at 16.936 + revision 50. Unknown to you, someone else introduced a 16.937 + different crashing bug at revision 60, and fixed it at 16.938 + revision 80. This could distort your results in one of 16.939 + several ways.</para> 16.940 + 16.941 + <para>It is possible that this other bug completely 16.942 + <quote>masks</quote> yours, which is to say that it occurs 16.943 + before your bug has a chance to manifest itself. If you can't 16.944 + avoid that other bug (for example, it prevents your project 16.945 + from building), and so can't tell whether your bug is present 16.946 + in a particular changeset, the <command role="hg-cmd">hg 16.947 + bisect</command> command cannot help you directly. Instead, 16.948 + you can mark a changeset as untested by running <command 16.949 + role="hg-cmd">hg bisect --skip</command>.</para> 16.950 + 16.951 + <para>A different problem could arise if your test for a bug's 16.952 + presence is not specific enough. If you check for <quote>my 16.953 + program crashes</quote>, then both your crashing bug and an 16.954 + unrelated crashing bug that masks it will look like the same 16.955 + thing, and mislead <command role="hg-cmd">hg 16.956 + bisect</command>.</para> 16.957 + 16.958 + <para>Another useful situation in which to use <command 16.959 + role="hg-cmd">hg bisect --skip</command> is if you can't 16.960 + test a revision because your project was in a broken and hence 16.961 + untestable state at that revision, perhaps because someone 16.962 + checked in a change that prevented the project from 16.963 + building.</para> 16.964 + 16.965 + </sect2> 16.966 + <sect2> 16.967 + <title>Bracket your search lazily</title> 16.968 + 16.969 + <para>Choosing the first <quote>good</quote> and 16.970 + <quote>bad</quote> changesets that will mark the end points of 16.971 + your search is often easy, but it bears a little discussion 16.972 + nevertheless. From the perspective of <command 16.973 + role="hg-cmd">hg bisect</command>, the <quote>newest</quote> 16.974 + changeset is conventionally <quote>bad</quote>, and the older 16.975 + changeset is <quote>good</quote>.</para> 16.976 + 16.977 + <para>If you're having trouble remembering when a suitable 16.978 + <quote>good</quote> change was, so that you can tell <command 16.979 + role="hg-cmd">hg bisect</command>, you could do worse than 16.980 + testing changesets at random. Just remember to eliminate 16.981 + contenders that can't possibly exhibit the bug (perhaps 16.982 + because the feature with the bug isn't present yet) and those 16.983 + where another problem masks the bug (as I discussed 16.984 + above).</para> 16.985 + 16.986 + <para>Even if you end up <quote>early</quote> by thousands of 16.987 + changesets or months of history, you will only add a handful 16.988 + of tests to the total number that <command role="hg-cmd">hg 16.989 + bisect</command> must perform, thanks to its logarithmic 16.990 + behaviour.</para> 16.991 + 16.992 + </sect2> 16.993 + </sect1> 16.994 +</chapter> 16.995 + 16.996 +<!-- 16.997 +local variables: 16.998 +sgml-parent-document: ("00book.xml" "book" "chapter") 16.999 +end: 16.1000 +-->
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/en/ch10-hook.xml Wed Feb 18 00:22:09 2009 -0800 17.3 @@ -0,0 +1,2067 @@ 17.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 17.5 + 17.6 +<chapter id="chap:hook"> 17.7 + <title>Handling repository events with hooks</title> 17.8 + 17.9 + <para>Mercurial offers a powerful mechanism to let you perform 17.10 + automated actions in response to events that occur in a 17.11 + repository. In some cases, you can even control Mercurial's 17.12 + response to those events.</para> 17.13 + 17.14 + <para>The name Mercurial uses for one of these actions is a 17.15 + <emphasis>hook</emphasis>. Hooks are called 17.16 + <quote>triggers</quote> in some revision control systems, but the 17.17 + two names refer to the same idea.</para> 17.18 + 17.19 + <sect1> 17.20 + <title>An overview of hooks in Mercurial</title> 17.21 + 17.22 + <para>Here is a brief list of the hooks that Mercurial supports. 17.23 + We will revisit each of these hooks in more detail later, in 17.24 + section <xref linkend="sec:hook:ref"/>.</para> 17.25 + 17.26 + <itemizedlist> 17.27 + <listitem><para><literal role="hook">changegroup</literal>: This 17.28 + is run after a group of changesets has been brought into the 17.29 + repository from elsewhere.</para> 17.30 + </listitem> 17.31 + <listitem><para><literal role="hook">commit</literal>: This is 17.32 + run after a new changeset has been created in the local 17.33 + repository.</para> 17.34 + </listitem> 17.35 + <listitem><para><literal role="hook">incoming</literal>: This is 17.36 + run once for each new changeset that is brought into the 17.37 + repository from elsewhere. Notice the difference from 17.38 + <literal role="hook">changegroup</literal>, which is run 17.39 + once per <emphasis>group</emphasis> of changesets brought 17.40 + in.</para> 17.41 + </listitem> 17.42 + <listitem><para><literal role="hook">outgoing</literal>: This is 17.43 + run after a group of changesets has been transmitted from 17.44 + this repository.</para> 17.45 + </listitem> 17.46 + <listitem><para><literal role="hook">prechangegroup</literal>: 17.47 + This is run before starting to bring a group of changesets 17.48 + into the repository. 17.49 + </para> 17.50 + </listitem> 17.51 + <listitem><para><literal role="hook">precommit</literal>: 17.52 + Controlling. This is run before starting a commit. 17.53 + </para> 17.54 + </listitem> 17.55 + <listitem><para><literal role="hook">preoutgoing</literal>: 17.56 + Controlling. This is run before starting to transmit a group 17.57 + of changesets from this repository. 17.58 + </para> 17.59 + </listitem> 17.60 + <listitem><para><literal role="hook">pretag</literal>: 17.61 + Controlling. This is run before creating a tag. 17.62 + </para> 17.63 + </listitem> 17.64 + <listitem><para><literal 17.65 + role="hook">pretxnchangegroup</literal>: Controlling. This 17.66 + is run after a group of changesets has been brought into the 17.67 + local repository from another, but before the transaction 17.68 + completes that will make the changes permanent in the 17.69 + repository. 17.70 + </para> 17.71 + </listitem> 17.72 + <listitem><para><literal role="hook">pretxncommit</literal>: 17.73 + Controlling. This is run after a new changeset has been 17.74 + created in the local repository, but before the transaction 17.75 + completes that will make it permanent. 17.76 + </para> 17.77 + </listitem> 17.78 + <listitem><para><literal role="hook">preupdate</literal>: 17.79 + Controlling. This is run before starting an update or merge 17.80 + of the working directory. 17.81 + </para> 17.82 + </listitem> 17.83 + <listitem><para><literal role="hook">tag</literal>: This is run 17.84 + after a tag is created. 17.85 + </para> 17.86 + </listitem> 17.87 + <listitem><para><literal role="hook">update</literal>: This is 17.88 + run after an update or merge of the working directory has 17.89 + finished. 17.90 + </para> 17.91 + </listitem></itemizedlist> 17.92 + <para>Each of the hooks whose description begins with the word 17.93 + <quote>Controlling</quote> has the ability to determine whether 17.94 + an activity can proceed. If the hook succeeds, the activity may 17.95 + proceed; if it fails, the activity is either not permitted or 17.96 + undone, depending on the hook. 17.97 + </para> 17.98 + 17.99 + </sect1> 17.100 + <sect1> 17.101 + <title>Hooks and security</title> 17.102 + 17.103 + <sect2> 17.104 + <title>Hooks are run with your privileges</title> 17.105 + 17.106 + <para>When you run a Mercurial command in a repository, and the 17.107 + command causes a hook to run, that hook runs on 17.108 + <emphasis>your</emphasis> system, under 17.109 + <emphasis>your</emphasis> user account, with 17.110 + <emphasis>your</emphasis> privilege level. Since hooks are 17.111 + arbitrary pieces of executable code, you should treat them 17.112 + with an appropriate level of suspicion. Do not install a hook 17.113 + unless you are confident that you know who created it and what 17.114 + it does. 17.115 + </para> 17.116 + 17.117 + <para>In some cases, you may be exposed to hooks that you did 17.118 + not install yourself. If you work with Mercurial on an 17.119 + unfamiliar system, Mercurial will run hooks defined in that 17.120 + system's global <filename role="special"> /.hgrc</filename>\ 17.121 + file. 17.122 + </para> 17.123 + 17.124 + <para>If you are working with a repository owned by another 17.125 + user, Mercurial can run hooks defined in that user's 17.126 + repository, but it will still run them as <quote>you</quote>. 17.127 + For example, if you <command role="hg-cmd">hg pull</command> 17.128 + from that repository, and its <filename 17.129 + role="special">.hg/hgrc</filename> defines a local <literal 17.130 + role="hook">outgoing</literal> hook, that hook will run 17.131 + under your user account, even though you don't own that 17.132 + repository. 17.133 + </para> 17.134 + 17.135 + <note> 17.136 + <para> This only applies if you are pulling from a repository 17.137 + on a local or network filesystem. If you're pulling over 17.138 + http or ssh, any <literal role="hook">outgoing</literal> 17.139 + hook will run under whatever account is executing the server 17.140 + process, on the server. 17.141 + </para> 17.142 + </note> 17.143 + 17.144 + <para>XXX To see what hooks are defined in a repository, use the 17.145 + <command role="hg-cmd">hg config hooks</command> command. If 17.146 + you are working in one repository, but talking to another that 17.147 + you do not own (e.g. using <command role="hg-cmd">hg 17.148 + pull</command> or <command role="hg-cmd">hg 17.149 + incoming</command>), remember that it is the other 17.150 + repository's hooks you should be checking, not your own. 17.151 + </para> 17.152 + 17.153 + </sect2> 17.154 + <sect2> 17.155 + <title>Hooks do not propagate</title> 17.156 + 17.157 + <para>In Mercurial, hooks are not revision controlled, and do 17.158 + not propagate when you clone, or pull from, a repository. The 17.159 + reason for this is simple: a hook is a completely arbitrary 17.160 + piece of executable code. It runs under your user identity, 17.161 + with your privilege level, on your machine. 17.162 + </para> 17.163 + 17.164 + <para>It would be extremely reckless for any distributed 17.165 + revision control system to implement revision-controlled 17.166 + hooks, as this would offer an easily exploitable way to 17.167 + subvert the accounts of users of the revision control system. 17.168 + </para> 17.169 + 17.170 + <para>Since Mercurial does not propagate hooks, if you are 17.171 + collaborating with other people on a common project, you 17.172 + should not assume that they are using the same Mercurial hooks 17.173 + as you are, or that theirs are correctly configured. You 17.174 + should document the hooks you expect people to use. 17.175 + </para> 17.176 + 17.177 + <para>In a corporate intranet, this is somewhat easier to 17.178 + control, as you can for example provide a 17.179 + <quote>standard</quote> installation of Mercurial on an NFS 17.180 + filesystem, and use a site-wide <filename role="special"> 17.181 + /.hgrc</filename>\ file to define hooks that all users will 17.182 + see. However, this too has its limits; see below. 17.183 + </para> 17.184 + 17.185 + </sect2> 17.186 + <sect2> 17.187 + <title>Hooks can be overridden</title> 17.188 + 17.189 + <para>Mercurial allows you to override a hook definition by 17.190 + redefining the hook. You can disable it by setting its value 17.191 + to the empty string, or change its behaviour as you wish. 17.192 + </para> 17.193 + 17.194 + <para>If you deploy a system- or site-wide <filename 17.195 + role="special"> /.hgrc</filename>\ file that defines some 17.196 + hooks, you should thus understand that your users can disable 17.197 + or override those hooks. 17.198 + </para> 17.199 + 17.200 + </sect2> 17.201 + <sect2> 17.202 + <title>Ensuring that critical hooks are run</title> 17.203 + 17.204 + <para>Sometimes you may want to enforce a policy that you do not 17.205 + want others to be able to work around. For example, you may 17.206 + have a requirement that every changeset must pass a rigorous 17.207 + set of tests. Defining this requirement via a hook in a 17.208 + site-wide <filename role="special"> /.hgrc</filename>\ won't 17.209 + work for remote users on laptops, and of course local users 17.210 + can subvert it at will by overriding the hook. 17.211 + </para> 17.212 + 17.213 + <para>Instead, you can set up your policies for use of Mercurial 17.214 + so that people are expected to propagate changes through a 17.215 + well-known <quote>canonical</quote> server that you have 17.216 + locked down and configured appropriately. 17.217 + </para> 17.218 + 17.219 + <para>One way to do this is via a combination of social 17.220 + engineering and technology. Set up a restricted-access 17.221 + account; users can push changes over the network to 17.222 + repositories managed by this account, but they cannot log into 17.223 + the account and run normal shell commands. In this scenario, 17.224 + a user can commit a changeset that contains any old garbage 17.225 + they want. 17.226 + </para> 17.227 + 17.228 + <para>When someone pushes a changeset to the server that 17.229 + everyone pulls from, the server will test the changeset before 17.230 + it accepts it as permanent, and reject it if it fails to pass 17.231 + the test suite. If people only pull changes from this 17.232 + filtering server, it will serve to ensure that all changes 17.233 + that people pull have been automatically vetted. 17.234 + </para> 17.235 + 17.236 + </sect2> 17.237 + </sect1> 17.238 + <sect1> 17.239 + <title>Care with <literal>pretxn</literal> hooks in a 17.240 + shared-access repository</title> 17.241 + 17.242 + <para>If you want to use hooks to do some automated work in a 17.243 + repository that a number of people have shared access to, you 17.244 + need to be careful in how you do this. 17.245 + </para> 17.246 + 17.247 + <para>Mercurial only locks a repository when it is writing to the 17.248 + repository, and only the parts of Mercurial that write to the 17.249 + repository pay attention to locks. Write locks are necessary to 17.250 + prevent multiple simultaneous writers from scribbling on each 17.251 + other's work, corrupting the repository. 17.252 + </para> 17.253 + 17.254 + <para>Because Mercurial is careful with the order in which it 17.255 + reads and writes data, it does not need to acquire a lock when 17.256 + it wants to read data from the repository. The parts of 17.257 + Mercurial that read from the repository never pay attention to 17.258 + locks. This lockless reading scheme greatly increases 17.259 + performance and concurrency. 17.260 + </para> 17.261 + 17.262 + <para>With great performance comes a trade-off, though, one which 17.263 + has the potential to cause you trouble unless you're aware of 17.264 + it. To describe this requires a little detail about how 17.265 + Mercurial adds changesets to a repository and reads those 17.266 + changes. 17.267 + </para> 17.268 + 17.269 + <para>When Mercurial <emphasis>writes</emphasis> metadata, it 17.270 + writes it straight into the destination file. It writes file 17.271 + data first, then manifest data (which contains pointers to the 17.272 + new file data), then changelog data (which contains pointers to 17.273 + the new manifest data). Before the first write to each file, it 17.274 + stores a record of where the end of the file was in its 17.275 + transaction log. If the transaction must be rolled back, 17.276 + Mercurial simply truncates each file back to the size it was 17.277 + before the transaction began. 17.278 + </para> 17.279 + 17.280 + <para>When Mercurial <emphasis>reads</emphasis> metadata, it reads 17.281 + the changelog first, then everything else. Since a reader will 17.282 + only access parts of the manifest or file metadata that it can 17.283 + see in the changelog, it can never see partially written data. 17.284 + </para> 17.285 + 17.286 + <para>Some controlling hooks (<literal 17.287 + role="hook">pretxncommit</literal> and <literal 17.288 + role="hook">pretxnchangegroup</literal>) run when a 17.289 + transaction is almost complete. All of the metadata has been 17.290 + written, but Mercurial can still roll the transaction back and 17.291 + cause the newly-written data to disappear. 17.292 + </para> 17.293 + 17.294 + <para>If one of these hooks runs for long, it opens a window of 17.295 + time during which a reader can see the metadata for changesets 17.296 + that are not yet permanent, and should not be thought of as 17.297 + <quote>really there</quote>. The longer the hook runs, the 17.298 + longer that window is open. 17.299 + </para> 17.300 + 17.301 + <sect2> 17.302 + <title>The problem illustrated</title> 17.303 + 17.304 + <para>In principle, a good use for the <literal 17.305 + role="hook">pretxnchangegroup</literal> hook would be to 17.306 + automatically build and test incoming changes before they are 17.307 + accepted into a central repository. This could let you 17.308 + guarantee that nobody can push changes to this repository that 17.309 + <quote>break the build</quote>. But if a client can pull 17.310 + changes while they're being tested, the usefulness of the test 17.311 + is zero; an unsuspecting someone can pull untested changes, 17.312 + potentially breaking their build. 17.313 + </para> 17.314 + 17.315 + <para>The safest technological answer to this challenge is to 17.316 + set up such a <quote>gatekeeper</quote> repository as 17.317 + <emphasis>unidirectional</emphasis>. Let it take changes 17.318 + pushed in from the outside, but do not allow anyone to pull 17.319 + changes from it (use the <literal 17.320 + role="hook">preoutgoing</literal> hook to lock it down). 17.321 + Configure a <literal role="hook">changegroup</literal> hook so 17.322 + that if a build or test succeeds, the hook will push the new 17.323 + changes out to another repository that people 17.324 + <emphasis>can</emphasis> pull from. 17.325 + </para> 17.326 + 17.327 + <para>In practice, putting a centralised bottleneck like this in 17.328 + place is not often a good idea, and transaction visibility has 17.329 + nothing to do with the problem. As the size of a 17.330 + project&emdash;and the time it takes to build and 17.331 + test&emdash;grows, you rapidly run into a wall with this 17.332 + <quote>try before you buy</quote> approach, where you have 17.333 + more changesets to test than time in which to deal with them. 17.334 + The inevitable result is frustration on the part of all 17.335 + involved. 17.336 + </para> 17.337 + 17.338 + <para>An approach that scales better is to get people to build 17.339 + and test before they push, then run automated builds and tests 17.340 + centrally <emphasis>after</emphasis> a push, to be sure all is 17.341 + well. The advantage of this approach is that it does not 17.342 + impose a limit on the rate at which the repository can accept 17.343 + changes. 17.344 + </para> 17.345 + 17.346 + </sect2> 17.347 + </sect1> 17.348 + <sect1 id="sec:hook:simple"> 17.349 + <title>A short tutorial on using hooks</title> 17.350 + 17.351 + <para>It is easy to write a Mercurial hook. Let's start with a 17.352 + hook that runs when you finish a <command role="hg-cmd">hg 17.353 + commit</command>, and simply prints the hash of the changeset 17.354 + you just created. The hook is called <literal 17.355 + role="hook">commit</literal>. 17.356 + </para> 17.357 + 17.358 + <para>All hooks follow the pattern in this example.</para> 17.359 + 17.360 +<!-- &interaction.hook.simple.init; --> 17.361 + 17.362 + <para>You add an entry to the <literal 17.363 + role="rc-hooks">hooks</literal> section of your <filename 17.364 + role="special"> /.hgrc</filename>. On the left is the name of 17.365 + the event to trigger on; on the right is the action to take. As 17.366 + you can see, you can run an arbitrary shell command in a hook. 17.367 + Mercurial passes extra information to the hook using environment 17.368 + variables (look for <envar>HG_NODE</envar> in the example). 17.369 + </para> 17.370 + 17.371 + <sect2> 17.372 + <title>Performing multiple actions per event</title> 17.373 + 17.374 + <para>Quite often, you will want to define more than one hook 17.375 + for a particular kind of event, as shown below.</para> 17.376 + 17.377 +<!-- &interaction.hook.simple.ext; --> 17.378 + 17.379 + <para>Mercurial lets you do this by adding an 17.380 + <emphasis>extension</emphasis> to the end of a hook's name. 17.381 + You extend a hook's name by giving the name of the hook, 17.382 + followed by a full stop (the 17.383 + <quote><literal>.</literal></quote> character), followed by 17.384 + some more text of your choosing. For example, Mercurial will 17.385 + run both <literal>commit.foo</literal> and 17.386 + <literal>commit.bar</literal> when the 17.387 + <literal>commit</literal> event occurs. 17.388 + </para> 17.389 + 17.390 + <para>To give a well-defined order of execution when there are 17.391 + multiple hooks defined for an event, Mercurial sorts hooks by 17.392 + extension, and executes the hook commands in this sorted 17.393 + order. In the above example, it will execute 17.394 + <literal>commit.bar</literal> before 17.395 + <literal>commit.foo</literal>, and <literal>commit</literal> 17.396 + before both. 17.397 + </para> 17.398 + 17.399 + <para>It is a good idea to use a somewhat descriptive extension 17.400 + when you define a new hook. This will help you to remember 17.401 + what the hook was for. If the hook fails, you'll get an error 17.402 + message that contains the hook name and extension, so using a 17.403 + descriptive extension could give you an immediate hint as to 17.404 + why the hook failed (see section <xref 17.405 + linkend="sec:hook:perm"/> for an example). 17.406 + </para> 17.407 + 17.408 + </sect2> 17.409 + <sect2 id="sec:hook:perm"> 17.410 + <title>Controlling whether an activity can proceed</title> 17.411 + 17.412 + <para>In our earlier examples, we used the <literal 17.413 + role="hook">commit</literal> hook, which is run after a 17.414 + commit has completed. This is one of several Mercurial hooks 17.415 + that run after an activity finishes. Such hooks have no way 17.416 + of influencing the activity itself. 17.417 + </para> 17.418 + 17.419 + <para>Mercurial defines a number of events that occur before an 17.420 + activity starts; or after it starts, but before it finishes. 17.421 + Hooks that trigger on these events have the added ability to 17.422 + choose whether the activity can continue, or will abort. 17.423 + </para> 17.424 + 17.425 + <para>The <literal role="hook">pretxncommit</literal> hook runs 17.426 + after a commit has all but completed. In other words, the 17.427 + metadata representing the changeset has been written out to 17.428 + disk, but the transaction has not yet been allowed to 17.429 + complete. The <literal role="hook">pretxncommit</literal> 17.430 + hook has the ability to decide whether the transaction can 17.431 + complete, or must be rolled back. 17.432 + </para> 17.433 + 17.434 + <para>If the <literal role="hook">pretxncommit</literal> hook 17.435 + exits with a status code of zero, the transaction is allowed 17.436 + to complete; the commit finishes; and the <literal 17.437 + role="hook">commit</literal> hook is run. If the <literal 17.438 + role="hook">pretxncommit</literal> hook exits with a 17.439 + non-zero status code, the transaction is rolled back; the 17.440 + metadata representing the changeset is erased; and the 17.441 + <literal role="hook">commit</literal> hook is not run. 17.442 + </para> 17.443 + 17.444 +<!-- &interaction.hook.simple.pretxncommit; --> 17.445 + 17.446 + <para>The hook in the example above checks that a commit comment 17.447 + contains a bug ID. If it does, the commit can complete. If 17.448 + not, the commit is rolled back. 17.449 + </para> 17.450 + 17.451 + </sect2> 17.452 + </sect1> 17.453 + <sect1> 17.454 + <title>Writing your own hooks</title> 17.455 + 17.456 + <para>When you are writing a hook, you might find it useful to run 17.457 + Mercurial either with the <option 17.458 + role="hg-opt-global">-v</option> option, or the <envar 17.459 + role="rc-item-ui">verbose</envar> config item set to 17.460 + <quote>true</quote>. When you do so, Mercurial will print a 17.461 + message before it calls each hook. 17.462 + </para> 17.463 + 17.464 + <sect2 id="sec:hook:lang"> 17.465 + <title>Choosing how your hook should run</title> 17.466 + 17.467 + <para>You can write a hook either as a normal 17.468 + program&emdash;typically a shell script&emdash;or as a Python 17.469 + function that is executed within the Mercurial process. 17.470 + </para> 17.471 + 17.472 + <para>Writing a hook as an external program has the advantage 17.473 + that it requires no knowledge of Mercurial's internals. You 17.474 + can call normal Mercurial commands to get any added 17.475 + information you need. The trade-off is that external hooks 17.476 + are slower than in-process hooks. 17.477 + </para> 17.478 + 17.479 + <para>An in-process Python hook has complete access to the 17.480 + Mercurial API, and does not <quote>shell out</quote> to 17.481 + another process, so it is inherently faster than an external 17.482 + hook. It is also easier to obtain much of the information 17.483 + that a hook requires by using the Mercurial API than by 17.484 + running Mercurial commands. 17.485 + </para> 17.486 + 17.487 + <para>If you are comfortable with Python, or require high 17.488 + performance, writing your hooks in Python may be a good 17.489 + choice. However, when you have a straightforward hook to 17.490 + write and you don't need to care about performance (probably 17.491 + the majority of hooks), a shell script is perfectly fine. 17.492 + </para> 17.493 + 17.494 + </sect2> 17.495 + <sect2 id="sec:hook:param"> 17.496 + <title>Hook parameters</title> 17.497 + 17.498 + <para>Mercurial calls each hook with a set of well-defined 17.499 + parameters. In Python, a parameter is passed as a keyword 17.500 + argument to your hook function. For an external program, a 17.501 + parameter is passed as an environment variable. 17.502 + </para> 17.503 + 17.504 + <para>Whether your hook is written in Python or as a shell 17.505 + script, the hook-specific parameter names and values will be 17.506 + the same. A boolean parameter will be represented as a 17.507 + boolean value in Python, but as the number 1 (for 17.508 + <quote>true</quote>) or 0 (for <quote>false</quote>) as an 17.509 + environment variable for an external hook. If a hook 17.510 + parameter is named <literal>foo</literal>, the keyword 17.511 + argument for a Python hook will also be named 17.512 + <literal>foo</literal>, while the environment variable for an 17.513 + external hook will be named <literal>HG_FOO</literal>. 17.514 + </para> 17.515 + 17.516 + </sect2> 17.517 + <sect2> 17.518 + <title>Hook return values and activity control</title> 17.519 + 17.520 + <para>A hook that executes successfully must exit with a status 17.521 + of zero if external, or return boolean <quote>false</quote> if 17.522 + in-process. Failure is indicated with a non-zero exit status 17.523 + from an external hook, or an in-process hook returning boolean 17.524 + <quote>true</quote>. If an in-process hook raises an 17.525 + exception, the hook is considered to have failed. 17.526 + </para> 17.527 + 17.528 + <para>For a hook that controls whether an activity can proceed, 17.529 + zero/false means <quote>allow</quote>, while 17.530 + non-zero/true/exception means <quote>deny</quote>. 17.531 + </para> 17.532 + 17.533 + </sect2> 17.534 + <sect2> 17.535 + <title>Writing an external hook</title> 17.536 + 17.537 + <para>When you define an external hook in your <filename 17.538 + role="special"> /.hgrc</filename>\ and the hook is run, its 17.539 + value is passed to your shell, which interprets it. This 17.540 + means that you can use normal shell constructs in the body of 17.541 + the hook. 17.542 + </para> 17.543 + 17.544 + <para>An executable hook is always run with its current 17.545 + directory set to a repository's root directory. 17.546 + </para> 17.547 + 17.548 + <para>Each hook parameter is passed in as an environment 17.549 + variable; the name is upper-cased, and prefixed with the 17.550 + string <quote><literal>HG_</literal></quote>. 17.551 + </para> 17.552 + 17.553 + <para>With the exception of hook parameters, Mercurial does not 17.554 + set or modify any environment variables when running a hook. 17.555 + This is useful to remember if you are writing a site-wide hook 17.556 + that may be run by a number of different users with differing 17.557 + environment variables set. In multi-user situations, you 17.558 + should not rely on environment variables being set to the 17.559 + values you have in your environment when testing the hook. 17.560 + </para> 17.561 + 17.562 + </sect2> 17.563 + <sect2> 17.564 + <title>Telling Mercurial to use an in-process hook</title> 17.565 + 17.566 + <para>The <filename role="special"> /.hgrc</filename>\ syntax 17.567 + for defining an in-process hook is slightly different than for 17.568 + an executable hook. The value of the hook must start with the 17.569 + text <quote><literal>python:</literal></quote>, and continue 17.570 + with the fully-qualified name of a callable object to use as 17.571 + the hook's value. 17.572 + </para> 17.573 + 17.574 + <para>The module in which a hook lives is automatically imported 17.575 + when a hook is run. So long as you have the module name and 17.576 + <envar>PYTHONPATH</envar> right, it should <quote>just 17.577 + work</quote>. 17.578 + </para> 17.579 + 17.580 + <para>The following <filename role="special"> /.hgrc</filename>\ 17.581 + example snippet illustrates the syntax and meaning of the 17.582 + notions we just described. 17.583 + </para> 17.584 + <programlisting>[hooks] commit.example = 17.585 + python:mymodule.submodule.myhook</programlisting> 17.586 + <para>When Mercurial runs the <literal>commit.example</literal> 17.587 + hook, it imports <literal>mymodule.submodule</literal>, looks 17.588 + for the callable object named <literal>myhook</literal>, and 17.589 + calls it. 17.590 + </para> 17.591 + 17.592 + </sect2> 17.593 + <sect2> 17.594 + <title>Writing an in-process hook</title> 17.595 + 17.596 + <para>The simplest in-process hook does nothing, but illustrates 17.597 + the basic shape of the hook API: 17.598 + </para> 17.599 + <programlisting>def myhook(ui, repo, **kwargs): 17.600 + pass</programlisting> 17.601 + <para>The first argument to a Python hook is always a <literal 17.602 + role="py-mod-mercurial.ui">ui</literal> object. The second 17.603 + is a repository object; at the moment, it is always an 17.604 + instance of <literal 17.605 + role="py-mod-mercurial.localrepo">localrepository</literal>. 17.606 + Following these two arguments are other keyword arguments. 17.607 + Which ones are passed in depends on the hook being called, but 17.608 + a hook can ignore arguments it doesn't care about by dropping 17.609 + them into a keyword argument dict, as with 17.610 + <literal>**kwargs</literal> above. 17.611 + </para> 17.612 + 17.613 + </sect2> 17.614 + </sect1> 17.615 + <sect1> 17.616 + <title>Some hook examples</title> 17.617 + 17.618 + <sect2> 17.619 + <title>Writing meaningful commit messages</title> 17.620 + 17.621 + <para>It's hard to imagine a useful commit message being very 17.622 + short. The simple <literal role="hook">pretxncommit</literal> 17.623 + hook of the example below will prevent you from committing a 17.624 + changeset with a message that is less than ten bytes long. 17.625 + </para> 17.626 + 17.627 +<!-- &interaction.hook.msglen.go; --> 17.628 + 17.629 + </sect2> 17.630 + <sect2> 17.631 + <title>Checking for trailing whitespace</title> 17.632 + 17.633 + <para>An interesting use of a commit-related hook is to help you 17.634 + to write cleaner code. A simple example of <quote>cleaner 17.635 + code</quote> is the dictum that a change should not add any 17.636 + new lines of text that contain <quote>trailing 17.637 + whitespace</quote>. Trailing whitespace is a series of 17.638 + space and tab characters at the end of a line of text. In 17.639 + most cases, trailing whitespace is unnecessary, invisible 17.640 + noise, but it is occasionally problematic, and people often 17.641 + prefer to get rid of it. 17.642 + </para> 17.643 + 17.644 + <para>You can use either the <literal 17.645 + role="hook">precommit</literal> or <literal 17.646 + role="hook">pretxncommit</literal> hook to tell whether you 17.647 + have a trailing whitespace problem. If you use the <literal 17.648 + role="hook">precommit</literal> hook, the hook will not know 17.649 + which files you are committing, so it will have to check every 17.650 + modified file in the repository for trailing white space. If 17.651 + you want to commit a change to just the file 17.652 + <filename>foo</filename>, but the file 17.653 + <filename>bar</filename> contains trailing whitespace, doing a 17.654 + check in the <literal role="hook">precommit</literal> hook 17.655 + will prevent you from committing <filename>foo</filename> due 17.656 + to the problem with <filename>bar</filename>. This doesn't 17.657 + seem right. 17.658 + </para> 17.659 + 17.660 + <para>Should you choose the <literal 17.661 + role="hook">pretxncommit</literal> hook, the check won't 17.662 + occur until just before the transaction for the commit 17.663 + completes. This will allow you to check for problems only the 17.664 + exact files that are being committed. However, if you entered 17.665 + the commit message interactively and the hook fails, the 17.666 + transaction will roll back; you'll have to re-enter the commit 17.667 + message after you fix the trailing whitespace and run <command 17.668 + role="hg-cmd">hg commit</command> again. 17.669 + </para> 17.670 + 17.671 +<!-- &interaction.hook.ws.simple; --> 17.672 + 17.673 + <para>In this example, we introduce a simple <literal 17.674 + role="hook">pretxncommit</literal> hook that checks for 17.675 + trailing whitespace. This hook is short, but not very 17.676 + helpful. It exits with an error status if a change adds a 17.677 + line with trailing whitespace to any file, but does not print 17.678 + any information that might help us to identify the offending 17.679 + file or line. It also has the nice property of not paying 17.680 + attention to unmodified lines; only lines that introduce new 17.681 + trailing whitespace cause problems. 17.682 + </para> 17.683 + 17.684 + <para>The above version is much more complex, but also more 17.685 + useful. It parses a unified diff to see if any lines add 17.686 + trailing whitespace, and prints the name of the file and the 17.687 + line number of each such occurrence. Even better, if the 17.688 + change adds trailing whitespace, this hook saves the commit 17.689 + comment and prints the name of the save file before exiting 17.690 + and telling Mercurial to roll the transaction back, so you can 17.691 + use the <option role="hg-opt-commit">-l filename</option> 17.692 + option to <command role="hg-cmd">hg commit</command> to reuse 17.693 + the saved commit message once you've corrected the problem. 17.694 + </para> 17.695 + 17.696 +<!-- &interaction.hook.ws.better; --> 17.697 + 17.698 + <para>As a final aside, note in the example above the use of 17.699 + <command>perl</command>'s in-place editing feature to get rid 17.700 + of trailing whitespace from a file. This is concise and 17.701 + useful enough that I will reproduce it here. 17.702 + </para> 17.703 + <programlisting>perl -pi -e 's,\s+$,,' filename</programlisting> 17.704 + 17.705 + </sect2> 17.706 + </sect1> 17.707 + <sect1> 17.708 + <title>Bundled hooks</title> 17.709 + 17.710 + <para>Mercurial ships with several bundled hooks. You can find 17.711 + them in the <filename class="directory">hgext</filename> 17.712 + directory of a Mercurial source tree. If you are using a 17.713 + Mercurial binary package, the hooks will be located in the 17.714 + <filename class="directory">hgext</filename> directory of 17.715 + wherever your package installer put Mercurial. 17.716 + </para> 17.717 + 17.718 + <sect2> 17.719 + <title><literal role="hg-ext">acl</literal>&emdash;access 17.720 + control for parts of a repository</title> 17.721 + 17.722 + <para>The <literal role="hg-ext">acl</literal> extension lets 17.723 + you control which remote users are allowed to push changesets 17.724 + to a networked server. You can protect any portion of a 17.725 + repository (including the entire repo), so that a specific 17.726 + remote user can push changes that do not affect the protected 17.727 + portion. 17.728 + </para> 17.729 + 17.730 + <para>This extension implements access control based on the 17.731 + identity of the user performing a push, 17.732 + <emphasis>not</emphasis> on who committed the changesets 17.733 + they're pushing. It makes sense to use this hook only if you 17.734 + have a locked-down server environment that authenticates 17.735 + remote users, and you want to be sure that only specific users 17.736 + are allowed to push changes to that server. 17.737 + </para> 17.738 + 17.739 + <sect3> 17.740 + <title>Configuring the <literal role="hook">acl</literal> 17.741 + hook</title> 17.742 + 17.743 + <para>In order to manage incoming changesets, the <literal 17.744 + role="hg-ext">acl</literal> hook must be used as a 17.745 + <literal role="hook">pretxnchangegroup</literal> hook. This 17.746 + lets it see which files are modified by each incoming 17.747 + changeset, and roll back a group of changesets if they 17.748 + modify <quote>forbidden</quote> files. Example: 17.749 + </para> 17.750 + <programlisting>[hooks] pretxnchangegroup.acl = 17.751 + python:hgext.acl.hook</programlisting> 17.752 + 17.753 + <para>The <literal role="hg-ext">acl</literal> extension is 17.754 + configured using three sections. 17.755 + </para> 17.756 + 17.757 + <para>The <literal role="rc-acl">acl</literal> section has 17.758 + only one entry, <envar role="rc-item-acl">sources</envar>, 17.759 + which lists the sources of incoming changesets that the hook 17.760 + should pay attention to. You don't normally need to 17.761 + configure this section. 17.762 + </para> 17.763 + <itemizedlist> 17.764 + <listitem><para><envar role="rc-item-acl">serve</envar>: 17.765 + Control incoming changesets that are arriving from a 17.766 + remote repository over http or ssh. This is the default 17.767 + value of <envar role="rc-item-acl">sources</envar>, and 17.768 + usually the only setting you'll need for this 17.769 + configuration item. 17.770 + </para> 17.771 + </listitem> 17.772 + <listitem><para><envar role="rc-item-acl">pull</envar>: 17.773 + Control incoming changesets that are arriving via a pull 17.774 + from a local repository. 17.775 + </para> 17.776 + </listitem> 17.777 + <listitem><para><envar role="rc-item-acl">push</envar>: 17.778 + Control incoming changesets that are arriving via a push 17.779 + from a local repository. 17.780 + </para> 17.781 + </listitem> 17.782 + <listitem><para><envar role="rc-item-acl">bundle</envar>: 17.783 + Control incoming changesets that are arriving from 17.784 + another repository via a bundle. 17.785 + </para> 17.786 + </listitem></itemizedlist> 17.787 + 17.788 + <para>The <literal role="rc-acl.allow">acl.allow</literal> 17.789 + section controls the users that are allowed to add 17.790 + changesets to the repository. If this section is not 17.791 + present, all users that are not explicitly denied are 17.792 + allowed. If this section is present, all users that are not 17.793 + explicitly allowed are denied (so an empty section means 17.794 + that all users are denied). 17.795 + </para> 17.796 + 17.797 + <para>The <literal role="rc-acl.deny">acl.deny</literal> 17.798 + section determines which users are denied from adding 17.799 + changesets to the repository. If this section is not 17.800 + present or is empty, no users are denied. 17.801 + </para> 17.802 + 17.803 + <para>The syntaxes for the <literal 17.804 + role="rc-acl.allow">acl.allow</literal> and <literal 17.805 + role="rc-acl.deny">acl.deny</literal> sections are 17.806 + identical. On the left of each entry is a glob pattern that 17.807 + matches files or directories, relative to the root of the 17.808 + repository; on the right, a user name. 17.809 + </para> 17.810 + 17.811 + <para>In the following example, the user 17.812 + <literal>docwriter</literal> can only push changes to the 17.813 + <filename class="directory">docs</filename> subtree of the 17.814 + repository, while <literal>intern</literal> can push changes 17.815 + to any file or directory except <filename 17.816 + class="directory">source/sensitive</filename>. 17.817 + </para> 17.818 + <programlisting>[acl.allow] docs/** = docwriter [acl.deny] 17.819 + source/sensitive/** = intern</programlisting> 17.820 + 17.821 + </sect3> 17.822 + <sect3> 17.823 + <title>Testing and troubleshooting</title> 17.824 + 17.825 + <para>If you want to test the <literal 17.826 + role="hg-ext">acl</literal> hook, run it with Mercurial's 17.827 + debugging output enabled. Since you'll probably be running 17.828 + it on a server where it's not convenient (or sometimes 17.829 + possible) to pass in the <option 17.830 + role="hg-opt-global">--debug</option> option, don't forget 17.831 + that you can enable debugging output in your <filename 17.832 + role="special"> /.hgrc</filename>: 17.833 + </para> 17.834 + <programlisting>[ui] debug = true</programlisting> 17.835 + <para>With this enabled, the <literal 17.836 + role="hg-ext">acl</literal> hook will print enough 17.837 + information to let you figure out why it is allowing or 17.838 + forbidding pushes from specific users. 17.839 + </para> 17.840 + 17.841 + </sect3> 17.842 + </sect2> 17.843 + <sect2> 17.844 + <title><literal 17.845 + role="hg-ext">bugzilla</literal>&emdash;integration with 17.846 + Bugzilla</title> 17.847 + 17.848 + <para>The <literal role="hg-ext">bugzilla</literal> extension 17.849 + adds a comment to a Bugzilla bug whenever it finds a reference 17.850 + to that bug ID in a commit comment. You can install this hook 17.851 + on a shared server, so that any time a remote user pushes 17.852 + changes to this server, the hook gets run. 17.853 + </para> 17.854 + 17.855 + <para>It adds a comment to the bug that looks like this (you can 17.856 + configure the contents of the comment&emdash;see below): 17.857 + </para> 17.858 + <programlisting>Changeset aad8b264143a, made by Joe User 17.859 + <joe.user@domain.com> in the frobnitz repository, refers 17.860 + to this bug. For complete details, see 17.861 + http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a 17.862 + Changeset description: Fix bug 10483 by guarding against some 17.863 + NULL pointers</programlisting> 17.864 + <para>The value of this hook is that it automates the process of 17.865 + updating a bug any time a changeset refers to it. If you 17.866 + configure the hook properly, it makes it easy for people to 17.867 + browse straight from a Bugzilla bug to a changeset that refers 17.868 + to that bug. 17.869 + </para> 17.870 + 17.871 + <para>You can use the code in this hook as a starting point for 17.872 + some more exotic Bugzilla integration recipes. Here are a few 17.873 + possibilities: 17.874 + </para> 17.875 + <itemizedlist> 17.876 + <listitem><para>Require that every changeset pushed to the 17.877 + server have a valid bug ID in its commit comment. In this 17.878 + case, you'd want to configure the hook as a <literal 17.879 + role="hook">pretxncommit</literal> hook. This would 17.880 + allow the hook to reject changes that didn't contain bug 17.881 + IDs. 17.882 + </para> 17.883 + </listitem> 17.884 + <listitem><para>Allow incoming changesets to automatically 17.885 + modify the <emphasis>state</emphasis> of a bug, as well as 17.886 + simply adding a comment. For example, the hook could 17.887 + recognise the string <quote>fixed bug 31337</quote> as 17.888 + indicating that it should update the state of bug 31337 to 17.889 + <quote>requires testing</quote>. 17.890 + </para> 17.891 + </listitem></itemizedlist> 17.892 + 17.893 + <sect3 id="sec:hook:bugzilla:config"> 17.894 + <title>Configuring the <literal role="hook">bugzilla</literal> 17.895 + hook</title> 17.896 + 17.897 + <para>You should configure this hook in your server's 17.898 + <filename role="special"> /.hgrc</filename>\ as an <literal 17.899 + role="hook">incoming</literal> hook, for example as 17.900 + follows: 17.901 + </para> 17.902 + <programlisting>[hooks] incoming.bugzilla = 17.903 + python:hgext.bugzilla.hook</programlisting> 17.904 + 17.905 + <para>Because of the specialised nature of this hook, and 17.906 + because Bugzilla was not written with this kind of 17.907 + integration in mind, configuring this hook is a somewhat 17.908 + involved process. 17.909 + </para> 17.910 + 17.911 + <para>Before you begin, you must install the MySQL bindings 17.912 + for Python on the host(s) where you'll be running the hook. 17.913 + If this is not available as a binary package for your 17.914 + system, you can download it from 17.915 + <citation>web:mysql-python</citation>. 17.916 + </para> 17.917 + 17.918 + <para>Configuration information for this hook lives in the 17.919 + <literal role="rc-bugzilla">bugzilla</literal> section of 17.920 + your <filename role="special"> /.hgrc</filename>. 17.921 + </para> 17.922 + <itemizedlist> 17.923 + <listitem><para><envar 17.924 + role="rc-item-bugzilla">version</envar>: The version 17.925 + of Bugzilla installed on the server. The database 17.926 + schema that Bugzilla uses changes occasionally, so this 17.927 + hook has to know exactly which schema to use. At the 17.928 + moment, the only version supported is 17.929 + <literal>2.16</literal>. 17.930 + </para> 17.931 + </listitem> 17.932 + <listitem><para><envar role="rc-item-bugzilla">host</envar>: 17.933 + The hostname of the MySQL server that stores your 17.934 + Bugzilla data. The database must be configured to allow 17.935 + connections from whatever host you are running the 17.936 + <literal role="hook">bugzilla</literal> hook on. 17.937 + </para> 17.938 + </listitem> 17.939 + <listitem><para><envar role="rc-item-bugzilla">user</envar>: 17.940 + The username with which to connect to the MySQL server. 17.941 + The database must be configured to allow this user to 17.942 + connect from whatever host you are running the <literal 17.943 + role="hook">bugzilla</literal> hook on. This user 17.944 + must be able to access and modify Bugzilla tables. The 17.945 + default value of this item is <literal>bugs</literal>, 17.946 + which is the standard name of the Bugzilla user in a 17.947 + MySQL database. 17.948 + </para> 17.949 + </listitem> 17.950 + <listitem><para><envar 17.951 + role="rc-item-bugzilla">password</envar>: The MySQL 17.952 + password for the user you configured above. This is 17.953 + stored as plain text, so you should make sure that 17.954 + unauthorised users cannot read the <filename 17.955 + role="special"> /.hgrc</filename>\ file where you 17.956 + store this information. 17.957 + </para> 17.958 + </listitem> 17.959 + <listitem><para><envar role="rc-item-bugzilla">db</envar>: 17.960 + The name of the Bugzilla database on the MySQL server. 17.961 + The default value of this item is 17.962 + <literal>bugs</literal>, which is the standard name of 17.963 + the MySQL database where Bugzilla stores its data. 17.964 + </para> 17.965 + </listitem> 17.966 + <listitem><para><envar 17.967 + role="rc-item-bugzilla">notify</envar>: If you want 17.968 + Bugzilla to send out a notification email to subscribers 17.969 + after this hook has added a comment to a bug, you will 17.970 + need this hook to run a command whenever it updates the 17.971 + database. The command to run depends on where you have 17.972 + installed Bugzilla, but it will typically look something 17.973 + like this, if you have Bugzilla installed in <filename 17.974 + class="directory">/var/www/html/bugzilla</filename>: 17.975 + </para> 17.976 + <programlisting>cd /var/www/html/bugzilla && 17.977 + ./processmail %s nobody@nowhere.com</programlisting> 17.978 + </listitem> 17.979 + <listitem><para> The Bugzilla 17.980 + <literal>processmail</literal> program expects to be 17.981 + given a bug ID (the hook replaces 17.982 + <quote><literal>%s</literal></quote> with the bug ID) 17.983 + and an email address. It also expects to be able to 17.984 + write to some files in the directory that it runs in. 17.985 + If Bugzilla and this hook are not installed on the same 17.986 + machine, you will need to find a way to run 17.987 + <literal>processmail</literal> on the server where 17.988 + Bugzilla is installed. 17.989 + </para> 17.990 + </listitem></itemizedlist> 17.991 + 17.992 + </sect3> 17.993 + <sect3> 17.994 + <title>Mapping committer names to Bugzilla user names</title> 17.995 + 17.996 + <para>By default, the <literal 17.997 + role="hg-ext">bugzilla</literal> hook tries to use the 17.998 + email address of a changeset's committer as the Bugzilla 17.999 + user name with which to update a bug. If this does not suit 17.1000 + your needs, you can map committer email addresses to 17.1001 + Bugzilla user names using a <literal 17.1002 + role="rc-usermap">usermap</literal> section. 17.1003 + </para> 17.1004 + 17.1005 + <para>Each item in the <literal 17.1006 + role="rc-usermap">usermap</literal> section contains an 17.1007 + email address on the left, and a Bugzilla user name on the 17.1008 + right. 17.1009 + </para> 17.1010 + <programlisting>[usermap] jane.user@example.com = 17.1011 + jane</programlisting> 17.1012 + <para>You can either keep the <literal 17.1013 + role="rc-usermap">usermap</literal> data in a normal 17.1014 + <filename role="special">~/.hgrc</filename>, or tell the 17.1015 + <literal role="hg-ext">bugzilla</literal> hook to read the 17.1016 + information from an external <filename>usermap</filename> 17.1017 + file. In the latter case, you can store 17.1018 + <filename>usermap</filename> data by itself in (for example) 17.1019 + a user-modifiable repository. This makes it possible to let 17.1020 + your users maintain their own <envar 17.1021 + role="rc-item-bugzilla">usermap</envar> entries. The main 17.1022 + <filename role="special"> /.hgrc</filename>\ file might look 17.1023 + like this: 17.1024 + </para> 17.1025 + <programlisting># regular hgrc file refers to external usermap 17.1026 + file [bugzilla] usermap = 17.1027 + /home/hg/repos/userdata/bugzilla-usermap.conf</programlisting> 17.1028 + <para>While the <filename>usermap</filename> file that it 17.1029 + refers to might look like this: 17.1030 + </para> 17.1031 + <programlisting># bugzilla-usermap.conf - inside a hg 17.1032 + repository [usermap] stephanie@example.com = 17.1033 + steph</programlisting> 17.1034 + 17.1035 + </sect3> 17.1036 + <sect3> 17.1037 + <title>Configuring the text that gets added to a bug</title> 17.1038 + 17.1039 + <para>You can configure the text that this hook adds as a 17.1040 + comment; you specify it in the form of a Mercurial template. 17.1041 + Several <filename role="special"> /.hgrc</filename>\ entries 17.1042 + (still in the <literal role="rc-bugzilla">bugzilla</literal> 17.1043 + section) control this behaviour. 17.1044 + </para> 17.1045 + <itemizedlist> 17.1046 + <listitem><para><literal>strip</literal>: The number of 17.1047 + leading path elements to strip from a repository's path 17.1048 + name to construct a partial path for a URL. For example, 17.1049 + if the repositories on your server live under <filename 17.1050 + class="directory">/home/hg/repos</filename>, and you 17.1051 + have a repository whose path is <filename 17.1052 + class="directory">/home/hg/repos/app/tests</filename>, 17.1053 + then setting <literal>strip</literal> to 17.1054 + <literal>4</literal> will give a partial path of 17.1055 + <filename class="directory">app/tests</filename>. The 17.1056 + hook will make this partial path available when 17.1057 + expanding a template, as <literal>webroot</literal>. 17.1058 + </para> 17.1059 + </listitem> 17.1060 + <listitem><para><literal>template</literal>: The text of the 17.1061 + template to use. In addition to the usual 17.1062 + changeset-related variables, this template can use 17.1063 + <literal>hgweb</literal> (the value of the 17.1064 + <literal>hgweb</literal> configuration item above) and 17.1065 + <literal>webroot</literal> (the path constructed using 17.1066 + <literal>strip</literal> above). 17.1067 + </para> 17.1068 + </listitem></itemizedlist> 17.1069 + 17.1070 + <para>In addition, you can add a <envar 17.1071 + role="rc-item-web">baseurl</envar> item to the <literal 17.1072 + role="rc-web">web</literal> section of your <filename 17.1073 + role="special"> /.hgrc</filename>. The <literal 17.1074 + role="hg-ext">bugzilla</literal> hook will make this 17.1075 + available when expanding a template, as the base string to 17.1076 + use when constructing a URL that will let users browse from 17.1077 + a Bugzilla comment to view a changeset. Example: 17.1078 + </para> 17.1079 + <programlisting>[web] baseurl = 17.1080 + http://hg.domain.com/</programlisting> 17.1081 + 17.1082 + <para>Here is an example set of <literal 17.1083 + role="hg-ext">bugzilla</literal> hook config information. 17.1084 + </para> 17.1085 + <programlisting>[bugzilla] host = bugzilla.example.com 17.1086 + password = mypassword version = 2.16 # server-side repos 17.1087 + live in /home/hg/repos, so strip 4 leading # separators 17.1088 + strip = 4 hgweb = http://hg.example.com/ usermap = 17.1089 + /home/hg/repos/notify/bugzilla.conf template = Changeset 17.1090 + {node|short}, made by {author} in the {webroot} repo, refers 17.1091 + to this bug.\\nFor complete details, see 17.1092 + {hgweb}{webroot}?cmd=changeset;node={node|short}\\nChangeset 17.1093 + description:\\n\\t{desc|tabindent}</programlisting> 17.1094 + 17.1095 + </sect3> 17.1096 + <sect3> 17.1097 + <title>Testing and troubleshooting</title> 17.1098 + 17.1099 + <para>The most common problems with configuring the <literal 17.1100 + role="hg-ext">bugzilla</literal> hook relate to running 17.1101 + Bugzilla's <filename>processmail</filename> script and 17.1102 + mapping committer names to user names. 17.1103 + </para> 17.1104 + 17.1105 + <para>Recall from section <xref 17.1106 + linkend="sec:hook:bugzilla:config"/> above that the user 17.1107 + that runs the Mercurial process on the server is also the 17.1108 + one that will run the <filename>processmail</filename> 17.1109 + script. The <filename>processmail</filename> script 17.1110 + sometimes causes Bugzilla to write to files in its 17.1111 + configuration directory, and Bugzilla's configuration files 17.1112 + are usually owned by the user that your web server runs 17.1113 + under. 17.1114 + </para> 17.1115 + 17.1116 + <para>You can cause <filename>processmail</filename> to be run 17.1117 + with the suitable user's identity using the 17.1118 + <command>sudo</command> command. Here is an example entry 17.1119 + for a <filename>sudoers</filename> file. 17.1120 + </para> 17.1121 + <programlisting>hg_user = (httpd_user) NOPASSWD: 17.1122 + /var/www/html/bugzilla/processmail-wrapper 17.1123 + %s</programlisting> 17.1124 + <para>This allows the <literal>hg_user</literal> user to run a 17.1125 + <filename>processmail-wrapper</filename> program under the 17.1126 + identity of <literal>httpd_user</literal>. 17.1127 + </para> 17.1128 + 17.1129 + <para>This indirection through a wrapper script is necessary, 17.1130 + because <filename>processmail</filename> expects to be run 17.1131 + with its current directory set to wherever you installed 17.1132 + Bugzilla; you can't specify that kind of constraint in a 17.1133 + <filename>sudoers</filename> file. The contents of the 17.1134 + wrapper script are simple: 17.1135 + </para> 17.1136 + <programlisting>#!/bin/sh cd `dirname $0` && 17.1137 + ./processmail "$1" nobody@example.com</programlisting> 17.1138 + <para>It doesn't seem to matter what email address you pass to 17.1139 + <filename>processmail</filename>. 17.1140 + </para> 17.1141 + 17.1142 + <para>If your <literal role="rc-usermap">usermap</literal> is 17.1143 + not set up correctly, users will see an error message from 17.1144 + the <literal role="hg-ext">bugzilla</literal> hook when they 17.1145 + push changes to the server. The error message will look 17.1146 + like this: 17.1147 + </para> 17.1148 + <programlisting>cannot find bugzilla user id for 17.1149 + john.q.public@example.com</programlisting> 17.1150 + <para>What this means is that the committer's address, 17.1151 + <literal>john.q.public@example.com</literal>, is not a valid 17.1152 + Bugzilla user name, nor does it have an entry in your 17.1153 + <literal role="rc-usermap">usermap</literal> that maps it to 17.1154 + a valid Bugzilla user name. 17.1155 + </para> 17.1156 + 17.1157 + </sect3> 17.1158 + </sect2> 17.1159 + <sect2> 17.1160 + <title><literal role="hg-ext">notify</literal>&emdash;send email 17.1161 + notifications</title> 17.1162 + 17.1163 + <para>Although Mercurial's built-in web server provides RSS 17.1164 + feeds of changes in every repository, many people prefer to 17.1165 + receive change notifications via email. The <literal 17.1166 + role="hg-ext">notify</literal> hook lets you send out 17.1167 + notifications to a set of email addresses whenever changesets 17.1168 + arrive that those subscribers are interested in. 17.1169 + </para> 17.1170 + 17.1171 + <para>As with the <literal role="hg-ext">bugzilla</literal> 17.1172 + hook, the <literal role="hg-ext">notify</literal> hook is 17.1173 + template-driven, so you can customise the contents of the 17.1174 + notification messages that it sends. 17.1175 + </para> 17.1176 + 17.1177 + <para>By default, the <literal role="hg-ext">notify</literal> 17.1178 + hook includes a diff of every changeset that it sends out; you 17.1179 + can limit the size of the diff, or turn this feature off 17.1180 + entirely. It is useful for letting subscribers review changes 17.1181 + immediately, rather than clicking to follow a URL. 17.1182 + </para> 17.1183 + 17.1184 + <sect3> 17.1185 + <title>Configuring the <literal role="hg-ext">notify</literal> 17.1186 + hook</title> 17.1187 + 17.1188 + <para>You can set up the <literal 17.1189 + role="hg-ext">notify</literal> hook to send one email 17.1190 + message per incoming changeset, or one per incoming group of 17.1191 + changesets (all those that arrived in a single pull or 17.1192 + push). 17.1193 + </para> 17.1194 + <programlisting>[hooks] # send one email per group of changes 17.1195 + changegroup.notify = python:hgext.notify.hook # send one 17.1196 + email per change incoming.notify = 17.1197 + python:hgext.notify.hook</programlisting> 17.1198 + 17.1199 + <para>Configuration information for this hook lives in the 17.1200 + <literal role="rc-notify">notify</literal> section of a 17.1201 + <filename role="special"> /.hgrc</filename>\ file. 17.1202 + </para> 17.1203 + <itemizedlist> 17.1204 + <listitem><para><envar role="rc-item-notify">test</envar>: 17.1205 + By default, this hook does not send out email at all; 17.1206 + instead, it prints the message that it 17.1207 + <emphasis>would</emphasis> send. Set this item to 17.1208 + <literal>false</literal> to allow email to be sent. The 17.1209 + reason that sending of email is turned off by default is 17.1210 + that it takes several tries to configure this extension 17.1211 + exactly as you would like, and it would be bad form to 17.1212 + spam subscribers with a number of <quote>broken</quote> 17.1213 + notifications while you debug your configuration. 17.1214 + </para> 17.1215 + </listitem> 17.1216 + <listitem><para><envar role="rc-item-notify">config</envar>: 17.1217 + The path to a configuration file that contains 17.1218 + subscription information. This is kept separate from 17.1219 + the main <filename role="special"> /.hgrc</filename>\ so 17.1220 + that you can maintain it in a repository of its own. 17.1221 + People can then clone that repository, update their 17.1222 + subscriptions, and push the changes back to your server. 17.1223 + </para> 17.1224 + </listitem> 17.1225 + <listitem><para><envar role="rc-item-notify">strip</envar>: 17.1226 + The number of leading path separator characters to strip 17.1227 + from a repository's path, when deciding whether a 17.1228 + repository has subscribers. For example, if the 17.1229 + repositories on your server live in <filename 17.1230 + class="directory">/home/hg/repos</filename>, and 17.1231 + <literal role="hg-ext">notify</literal> is considering a 17.1232 + repository named <filename 17.1233 + class="directory">/home/hg/repos/shared/test</filename>, 17.1234 + setting <envar role="rc-item-notify">strip</envar> to 17.1235 + <literal>4</literal> will cause <literal 17.1236 + role="hg-ext">notify</literal> to trim the path it 17.1237 + considers down to <filename 17.1238 + class="directory">shared/test</filename>, and it will 17.1239 + match subscribers against that. 17.1240 + </para> 17.1241 + </listitem> 17.1242 + <listitem><para><envar 17.1243 + role="rc-item-notify">template</envar>: The template 17.1244 + text to use when sending messages. This specifies both 17.1245 + the contents of the message header and its body. 17.1246 + </para> 17.1247 + </listitem> 17.1248 + <listitem><para><envar 17.1249 + role="rc-item-notify">maxdiff</envar>: The maximum 17.1250 + number of lines of diff data to append to the end of a 17.1251 + message. If a diff is longer than this, it is 17.1252 + truncated. By default, this is set to 300. Set this to 17.1253 + <literal>0</literal> to omit diffs from notification 17.1254 + emails. 17.1255 + </para> 17.1256 + </listitem> 17.1257 + <listitem><para><envar 17.1258 + role="rc-item-notify">sources</envar>: A list of 17.1259 + sources of changesets to consider. This lets you limit 17.1260 + <literal role="hg-ext">notify</literal> to only sending 17.1261 + out email about changes that remote users pushed into 17.1262 + this repository via a server, for example. See section 17.1263 + <xref 17.1264 + linkend="sec:hook:sources"/> for the sources you can 17.1265 + specify here. 17.1266 + </para> 17.1267 + </listitem></itemizedlist> 17.1268 + 17.1269 + <para>If you set the <envar role="rc-item-web">baseurl</envar> 17.1270 + item in the <literal role="rc-web">web</literal> section, 17.1271 + you can use it in a template; it will be available as 17.1272 + <literal>webroot</literal>. 17.1273 + </para> 17.1274 + 17.1275 + <para>Here is an example set of <literal 17.1276 + role="hg-ext">notify</literal> configuration information. 17.1277 + </para> 17.1278 + <programlisting> 17.1279 + [notify] # really send email test = false # subscriber data 17.1280 + lives in the notify repo config = 17.1281 + /home/hg/repos/notify/notify.conf # repos live in 17.1282 + /home/hg/repos on server, so strip 4 "/" chars strip = 4 17.1283 + template = X-Hg-Repo: {webroot} Subject: {webroot}: 17.1284 + {desc|firstline|strip} From: {author} changeset {node|short} 17.1285 + in {root} details: 17.1286 + {baseurl}{webroot}?cmd=changeset;node={node|short} 17.1287 + description: {desc|tabindent|strip} [web] baseurl = 17.1288 + http://hg.example.com/ 17.1289 + </programlisting> 17.1290 + 17.1291 + <para>This will produce a message that looks like the 17.1292 + following: 17.1293 + </para> 17.1294 + <programlisting> 17.1295 + X-Hg-Repo: tests/slave Subject: tests/slave: Handle error 17.1296 + case when slave has no buffers Date: Wed, 2 Aug 2006 17.1297 + 15:25:46 -0700 (PDT) changeset 3cba9bfe74b5 in 17.1298 + /home/hg/repos/tests/slave details: 17.1299 + http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5 17.1300 + description: Handle error case when slave has no buffers 17.1301 + diffs (54 lines): diff -r 9d95df7cf2ad -r 3cba9bfe74b5 17.1302 + include/tests.h --- a/include/tests.h Wed Aug 02 17.1303 + 15:19:52 2006 -0700 +++ b/include/tests.h Wed Aug 02 17.1304 + 15:25:26 2006 -0700 @@ -212,6 +212,15 @@ static __inline__ 17.1305 + void test_headers(void *h) [...snip...] 17.1306 + </programlisting> 17.1307 + 17.1308 + </sect3> 17.1309 + <sect3> 17.1310 + <title>Testing and troubleshooting</title> 17.1311 + 17.1312 + <para>Do not forget that by default, the <literal 17.1313 + role="hg-ext">notify</literal> extension \emph{will not 17.1314 + send any mail} until you explicitly configure it to do so, 17.1315 + by setting <envar role="rc-item-notify">test</envar> to 17.1316 + <literal>false</literal>. Until you do that, it simply 17.1317 + prints the message it <emphasis>would</emphasis> send. 17.1318 + </para> 17.1319 + 17.1320 + </sect3> 17.1321 + </sect2> 17.1322 + </sect1> 17.1323 + <sect1 id="sec:hook:ref"> 17.1324 + <title>Information for writers of hooks</title> 17.1325 + 17.1326 + <sect2> 17.1327 + <title>In-process hook execution</title> 17.1328 + 17.1329 + <para>An in-process hook is called with arguments of the 17.1330 + following form: 17.1331 + </para> 17.1332 + <programlisting> 17.1333 + def myhook(ui, repo, **kwargs): pass 17.1334 + </programlisting> 17.1335 + <para>The <literal>ui</literal> parameter is a <literal 17.1336 + role="py-mod-mercurial.ui">ui</literal> object. The 17.1337 + <literal>repo</literal> parameter is a <literal 17.1338 + role="py-mod-mercurial.localrepo">localrepository</literal> 17.1339 + object. The names and values of the 17.1340 + <literal>**kwargs</literal> parameters depend on the hook 17.1341 + being invoked, with the following common features: 17.1342 + </para> 17.1343 + <itemizedlist> 17.1344 + <listitem><para>If a parameter is named 17.1345 + <literal>node</literal> or <literal>parentN</literal>, it 17.1346 + will contain a hexadecimal changeset ID. The empty string 17.1347 + is used to represent <quote>null changeset ID</quote> 17.1348 + instead of a string of zeroes. 17.1349 + </para> 17.1350 + </listitem> 17.1351 + <listitem><para>If a parameter is named 17.1352 + <literal>url</literal>, it will contain the URL of a 17.1353 + remote repository, if that can be determined. 17.1354 + </para> 17.1355 + </listitem> 17.1356 + <listitem><para>Boolean-valued parameters are represented as 17.1357 + Python <literal>bool</literal> objects. 17.1358 + </para> 17.1359 + </listitem></itemizedlist> 17.1360 + 17.1361 + <para>An in-process hook is called without a change to the 17.1362 + process's working directory (unlike external hooks, which are 17.1363 + run in the root of the repository). It must not change the 17.1364 + process's working directory, or it will cause any calls it 17.1365 + makes into the Mercurial API to fail. 17.1366 + </para> 17.1367 + 17.1368 + <para>If a hook returns a boolean <quote>false</quote> value, it 17.1369 + is considered to have succeeded. If it returns a boolean 17.1370 + <quote>true</quote> value or raises an exception, it is 17.1371 + considered to have failed. A useful way to think of the 17.1372 + calling convention is <quote>tell me if you fail</quote>. 17.1373 + </para> 17.1374 + 17.1375 + <para>Note that changeset IDs are passed into Python hooks as 17.1376 + hexadecimal strings, not the binary hashes that Mercurial's 17.1377 + APIs normally use. To convert a hash from hex to binary, use 17.1378 + the \pymodfunc{mercurial.node}{bin} function. 17.1379 + </para> 17.1380 + 17.1381 + </sect2> 17.1382 + <sect2> 17.1383 + <title>External hook execution</title> 17.1384 + 17.1385 + <para>An external hook is passed to the shell of the user 17.1386 + running Mercurial. Features of that shell, such as variable 17.1387 + substitution and command redirection, are available. The hook 17.1388 + is run in the root directory of the repository (unlike 17.1389 + in-process hooks, which are run in the same directory that 17.1390 + Mercurial was run in). 17.1391 + </para> 17.1392 + 17.1393 + <para>Hook parameters are passed to the hook as environment 17.1394 + variables. Each environment variable's name is converted in 17.1395 + upper case and prefixed with the string 17.1396 + <quote><literal>HG_</literal></quote>. For example, if the 17.1397 + name of a parameter is <quote><literal>node</literal></quote>, 17.1398 + the name of the environment variable representing that 17.1399 + parameter will be <quote><literal>HG_NODE</literal></quote>. 17.1400 + </para> 17.1401 + 17.1402 + <para>A boolean parameter is represented as the string 17.1403 + <quote><literal>1</literal></quote> for <quote>true</quote>, 17.1404 + <quote><literal>0</literal></quote> for <quote>false</quote>. 17.1405 + If an environment variable is named <envar>HG_NODE</envar>, 17.1406 + <envar>HG_PARENT1</envar> or <envar>HG_PARENT2</envar>, it 17.1407 + contains a changeset ID represented as a hexadecimal string. 17.1408 + The empty string is used to represent <quote>null changeset 17.1409 + ID</quote> instead of a string of zeroes. If an environment 17.1410 + variable is named <envar>HG_URL</envar>, it will contain the 17.1411 + URL of a remote repository, if that can be determined. 17.1412 + </para> 17.1413 + 17.1414 + <para>If a hook exits with a status of zero, it is considered to 17.1415 + have succeeded. If it exits with a non-zero status, it is 17.1416 + considered to have failed. 17.1417 + </para> 17.1418 + 17.1419 + </sect2> 17.1420 + <sect2> 17.1421 + <title>Finding out where changesets come from</title> 17.1422 + 17.1423 + <para>A hook that involves the transfer of changesets between a 17.1424 + local repository and another may be able to find out 17.1425 + information about the <quote>far side</quote>. Mercurial 17.1426 + knows <emphasis>how</emphasis> changes are being transferred, 17.1427 + and in many cases <emphasis>where</emphasis> they are being 17.1428 + transferred to or from. 17.1429 + </para> 17.1430 + 17.1431 + <sect3 id="sec:hook:sources"> 17.1432 + <title>Sources of changesets</title> 17.1433 + 17.1434 + <para>Mercurial will tell a hook what means are, or were, used 17.1435 + to transfer changesets between repositories. This is 17.1436 + provided by Mercurial in a Python parameter named 17.1437 + <literal>source</literal>, or an environment variable named 17.1438 + <envar>HG_SOURCE</envar>. 17.1439 + </para> 17.1440 + 17.1441 + <itemizedlist> 17.1442 + <listitem><para><literal>serve</literal>: Changesets are 17.1443 + transferred to or from a remote repository over http or 17.1444 + ssh. 17.1445 + </para> 17.1446 + </listitem> 17.1447 + <listitem><para><literal>pull</literal>: Changesets are 17.1448 + being transferred via a pull from one repository into 17.1449 + another. 17.1450 + </para> 17.1451 + </listitem> 17.1452 + <listitem><para><literal>push</literal>: Changesets are 17.1453 + being transferred via a push from one repository into 17.1454 + another. 17.1455 + </para> 17.1456 + </listitem> 17.1457 + <listitem><para><literal>bundle</literal>: Changesets are 17.1458 + being transferred to or from a bundle. 17.1459 + </para> 17.1460 + </listitem></itemizedlist> 17.1461 + 17.1462 + </sect3> 17.1463 + <sect3 id="sec:hook:url"> 17.1464 + <title>Where changes are going&emdash;remote repository 17.1465 + URLs</title> 17.1466 + 17.1467 + <para>When possible, Mercurial will tell a hook the location 17.1468 + of the <quote>far side</quote> of an activity that transfers 17.1469 + changeset data between repositories. This is provided by 17.1470 + Mercurial in a Python parameter named 17.1471 + <literal>url</literal>, or an environment variable named 17.1472 + <envar>HG_URL</envar>. 17.1473 + </para> 17.1474 + 17.1475 + <para>This information is not always known. If a hook is 17.1476 + invoked in a repository that is being served via http or 17.1477 + ssh, Mercurial cannot tell where the remote repository is, 17.1478 + but it may know where the client is connecting from. In 17.1479 + such cases, the URL will take one of the following forms: 17.1480 + </para> 17.1481 + <itemizedlist> 17.1482 + <listitem><para><literal>remote:ssh:1.2.3.4</literal>&emdash;remote 17.1483 + ssh client, at the IP address 17.1484 + <literal>1.2.3.4</literal>. 17.1485 + </para> 17.1486 + </listitem> 17.1487 + <listitem><para><literal>remote:http:1.2.3.4</literal>&emdash;remote 17.1488 + http client, at the IP address 17.1489 + <literal>1.2.3.4</literal>. If the client is using SSL, 17.1490 + this will be of the form 17.1491 + <literal>remote:https:1.2.3.4</literal>. 17.1492 + </para> 17.1493 + </listitem> 17.1494 + <listitem><para>Empty&emdash;no information could be 17.1495 + discovered about the remote client. 17.1496 + </para> 17.1497 + </listitem></itemizedlist> 17.1498 + 17.1499 + </sect3> 17.1500 + </sect2> 17.1501 + </sect1> 17.1502 + <sect1> 17.1503 + <title>Hook reference</title> 17.1504 + 17.1505 + <sect2 id="sec:hook:changegroup"> 17.1506 + <title><literal role="hook">changegroup</literal>&emdash;after 17.1507 + remote changesets added</title> 17.1508 + 17.1509 + <para>This hook is run after a group of pre-existing changesets 17.1510 + has been added to the repository, for example via a <command 17.1511 + role="hg-cmd">hg pull</command> or <command role="hg-cmd">hg 17.1512 + unbundle</command>. This hook is run once per operation 17.1513 + that added one or more changesets. This is in contrast to the 17.1514 + <literal role="hook">incoming</literal> hook, which is run 17.1515 + once per changeset, regardless of whether the changesets 17.1516 + arrive in a group. 17.1517 + </para> 17.1518 + 17.1519 + <para>Some possible uses for this hook include kicking off an 17.1520 + automated build or test of the added changesets, updating a 17.1521 + bug database, or notifying subscribers that a repository 17.1522 + contains new changes. 17.1523 + </para> 17.1524 + 17.1525 + <para>Parameters to this hook: 17.1526 + </para> 17.1527 + <itemizedlist> 17.1528 + <listitem><para><literal>node</literal>: A changeset ID. The 17.1529 + changeset ID of the first changeset in the group that was 17.1530 + added. All changesets between this and 17.1531 + \index{tags!<literal>tip</literal>}<literal>tip</literal>, 17.1532 + inclusive, were added by a single <command 17.1533 + role="hg-cmd">hg pull</command>, <command 17.1534 + role="hg-cmd">hg push</command> or <command 17.1535 + role="hg-cmd">hg unbundle</command>. 17.1536 + </para> 17.1537 + </listitem> 17.1538 + <listitem><para><literal>source</literal>: A string. The 17.1539 + source of these changes. See section <xref 17.1540 + linkend="sec:hook:sources"/> for details. 17.1541 + </para> 17.1542 + </listitem> 17.1543 + <listitem><para><literal>url</literal>: A URL. The location 17.1544 + of the remote repository, if known. See section <xref 17.1545 + linkend="sec:hook:url"/> for more 17.1546 + information. 17.1547 + </para> 17.1548 + </listitem></itemizedlist> 17.1549 + 17.1550 + <para>See also: <literal role="hook">incoming</literal> (section 17.1551 + <xref linkend="sec:hook:incoming"/>), <literal 17.1552 + role="hook">prechangegroup</literal> (section <xref 17.1553 + linkend="sec:hook:prechangegroup"/>), <literal 17.1554 + role="hook">pretxnchangegroup</literal> (section <xref 17.1555 + linkend="sec:hook:pretxnchangegroup"/>) 17.1556 + </para> 17.1557 + 17.1558 + </sect2> 17.1559 + <sect2 id="sec:hook:commit"> 17.1560 + <title><literal role="hook">commit</literal>&emdash;after a new 17.1561 + changeset is created</title> 17.1562 + 17.1563 + <para>This hook is run after a new changeset has been created. 17.1564 + </para> 17.1565 + 17.1566 + <para>Parameters to this hook: 17.1567 + </para> 17.1568 + <itemizedlist> 17.1569 + <listitem><para><literal>node</literal>: A changeset ID. The 17.1570 + changeset ID of the newly committed changeset. 17.1571 + </para> 17.1572 + </listitem> 17.1573 + <listitem><para><literal>parent1</literal>: A changeset ID. 17.1574 + The changeset ID of the first parent of the newly 17.1575 + committed changeset. 17.1576 + </para> 17.1577 + </listitem> 17.1578 + <listitem><para><literal>parent2</literal>: A changeset ID. 17.1579 + The changeset ID of the second parent of the newly 17.1580 + committed changeset. 17.1581 + </para> 17.1582 + </listitem></itemizedlist> 17.1583 + 17.1584 + <para>See also: <literal role="hook">precommit</literal> 17.1585 + (section <xref linkend="sec:hook:precommit"/>), <literal 17.1586 + role="hook">pretxncommit</literal> (section <xref 17.1587 + linkend="sec:hook:pretxncommit"/>) 17.1588 + </para> 17.1589 + 17.1590 + </sect2> 17.1591 + <sect2 id="sec:hook:incoming"> 17.1592 + <title><literal role="hook">incoming</literal>&emdash;after one 17.1593 + remote changeset is added</title> 17.1594 + 17.1595 + <para>This hook is run after a pre-existing changeset has been 17.1596 + added to the repository, for example via a <command 17.1597 + role="hg-cmd">hg push</command>. If a group of changesets 17.1598 + was added in a single operation, this hook is called once for 17.1599 + each added changeset. 17.1600 + </para> 17.1601 + 17.1602 + <para>You can use this hook for the same purposes as the 17.1603 + <literal role="hook">changegroup</literal> hook (section <xref 17.1604 + linkend="sec:hook:changegroup"/>); it's simply 17.1605 + more convenient sometimes to run a hook once per group of 17.1606 + changesets, while other times it's handier once per changeset. 17.1607 + </para> 17.1608 + 17.1609 + <para>Parameters to this hook: 17.1610 + </para> 17.1611 + <itemizedlist> 17.1612 + <listitem><para><literal>node</literal>: A changeset ID. The 17.1613 + ID of the newly added changeset. 17.1614 + </para> 17.1615 + </listitem> 17.1616 + <listitem><para><literal>source</literal>: A string. The 17.1617 + source of these changes. See section <xref 17.1618 + linkend="sec:hook:sources"/> for details. 17.1619 + </para> 17.1620 + </listitem> 17.1621 + <listitem><para><literal>url</literal>: A URL. The location 17.1622 + of the remote repository, if known. See section <xref 17.1623 + linkend="sec:hook:url"/> for more 17.1624 + information. 17.1625 + </para> 17.1626 + </listitem></itemizedlist> 17.1627 + 17.1628 + <para>See also: <literal role="hook">changegroup</literal> 17.1629 + (section <xref linkend="sec:hook:changegroup"/>) <literal 17.1630 + role="hook">prechangegroup</literal> (section <xref 17.1631 + linkend="sec:hook:prechangegroup"/>), <literal 17.1632 + role="hook">pretxnchangegroup</literal> (section <xref 17.1633 + linkend="sec:hook:pretxnchangegroup"/>) 17.1634 + </para> 17.1635 + 17.1636 + </sect2> 17.1637 + <sect2 id="sec:hook:outgoing"> 17.1638 + <title><literal role="hook">outgoing</literal>&emdash;after 17.1639 + changesets are propagated</title> 17.1640 + 17.1641 + <para>This hook is run after a group of changesets has been 17.1642 + propagated out of this repository, for example by a <command 17.1643 + role="hg-cmd">hg push</command> or <command role="hg-cmd">hg 17.1644 + bundle</command> command. 17.1645 + </para> 17.1646 + 17.1647 + <para>One possible use for this hook is to notify administrators 17.1648 + that changes have been pulled. 17.1649 + </para> 17.1650 + 17.1651 + <para>Parameters to this hook: 17.1652 + </para> 17.1653 + <itemizedlist> 17.1654 + <listitem><para><literal>node</literal>: A changeset ID. The 17.1655 + changeset ID of the first changeset of the group that was 17.1656 + sent. 17.1657 + </para> 17.1658 + </listitem> 17.1659 + <listitem><para><literal>source</literal>: A string. The 17.1660 + source of the of the operation (see section <xref 17.1661 + linkend="sec:hook:sources"/>). If a remote 17.1662 + client pulled changes from this repository, 17.1663 + <literal>source</literal> will be 17.1664 + <literal>serve</literal>. If the client that obtained 17.1665 + changes from this repository was local, 17.1666 + <literal>source</literal> will be 17.1667 + <literal>bundle</literal>, <literal>pull</literal>, or 17.1668 + <literal>push</literal>, depending on the operation the 17.1669 + client performed. 17.1670 + </para> 17.1671 + </listitem> 17.1672 + <listitem><para><literal>url</literal>: A URL. The location 17.1673 + of the remote repository, if known. See section <xref 17.1674 + linkend="sec:hook:url"/> for more 17.1675 + information. 17.1676 + </para> 17.1677 + </listitem></itemizedlist> 17.1678 + 17.1679 + <para>See also: <literal role="hook">preoutgoing</literal> 17.1680 + (section <xref linkend="sec:hook:preoutgoing"/>) 17.1681 + </para> 17.1682 + 17.1683 + </sect2> 17.1684 + <sect2 id="sec:hook:prechangegroup"> 17.1685 + <title><literal 17.1686 + role="hook">prechangegroup</literal>&emdash;before starting 17.1687 + to add remote changesets</title> 17.1688 + 17.1689 + <para>This controlling hook is run before Mercurial begins to 17.1690 + add a group of changesets from another repository. 17.1691 + </para> 17.1692 + 17.1693 + <para>This hook does not have any information about the 17.1694 + changesets to be added, because it is run before transmission 17.1695 + of those changesets is allowed to begin. If this hook fails, 17.1696 + the changesets will not be transmitted. 17.1697 + </para> 17.1698 + 17.1699 + <para>One use for this hook is to prevent external changes from 17.1700 + being added to a repository. For example, you could use this 17.1701 + to <quote>freeze</quote> a server-hosted branch temporarily or 17.1702 + permanently so that users cannot push to it, while still 17.1703 + allowing a local administrator to modify the repository. 17.1704 + </para> 17.1705 + 17.1706 + <para>Parameters to this hook: 17.1707 + </para> 17.1708 + <itemizedlist> 17.1709 + <listitem><para><literal>source</literal>: A string. The 17.1710 + source of these changes. See section <xref 17.1711 + linkend="sec:hook:sources"/> for details. 17.1712 + </para> 17.1713 + </listitem> 17.1714 + <listitem><para><literal>url</literal>: A URL. The location 17.1715 + of the remote repository, if known. See section <xref 17.1716 + linkend="sec:hook:url"/> for more 17.1717 + information. 17.1718 + </para> 17.1719 + </listitem></itemizedlist> 17.1720 + 17.1721 + <para>See also: <literal role="hook">changegroup</literal> 17.1722 + (section <xref linkend="sec:hook:changegroup"/>), <literal 17.1723 + role="hook">incoming</literal> (section <xref 17.1724 + linkend="sec:hook:incoming"/>), , <literal 17.1725 + role="hook">pretxnchangegroup</literal> (section <xref 17.1726 + linkend="sec:hook:pretxnchangegroup"/>) 17.1727 + </para> 17.1728 + 17.1729 + </sect2> 17.1730 + <sect2 id="sec:hook:precommit"> 17.1731 + <title><literal role="hook">precommit</literal>&emdash;before 17.1732 + starting to commit a changeset</title> 17.1733 + 17.1734 + <para>This hook is run before Mercurial begins to commit a new 17.1735 + changeset. It is run before Mercurial has any of the metadata 17.1736 + for the commit, such as the files to be committed, the commit 17.1737 + message, or the commit date. 17.1738 + </para> 17.1739 + 17.1740 + <para>One use for this hook is to disable the ability to commit 17.1741 + new changesets, while still allowing incoming changesets. 17.1742 + Another is to run a build or test, and only allow the commit 17.1743 + to begin if the build or test succeeds. 17.1744 + </para> 17.1745 + 17.1746 + <para>Parameters to this hook: 17.1747 + </para> 17.1748 + <itemizedlist> 17.1749 + <listitem><para><literal>parent1</literal>: A changeset ID. 17.1750 + The changeset ID of the first parent of the working 17.1751 + directory. 17.1752 + </para> 17.1753 + </listitem> 17.1754 + <listitem><para><literal>parent2</literal>: A changeset ID. 17.1755 + The changeset ID of the second parent of the working 17.1756 + directory. 17.1757 + </para> 17.1758 + </listitem></itemizedlist> 17.1759 + <para>If the commit proceeds, the parents of the working 17.1760 + directory will become the parents of the new changeset. 17.1761 + </para> 17.1762 + 17.1763 + <para>See also: <literal role="hook">commit</literal> (section 17.1764 + <xref linkend="sec:hook:commit"/>), <literal 17.1765 + role="hook">pretxncommit</literal> (section <xref 17.1766 + linkend="sec:hook:pretxncommit"/>) 17.1767 + </para> 17.1768 + 17.1769 + </sect2> 17.1770 + <sect2 id="sec:hook:preoutgoing"> 17.1771 + <title><literal role="hook">preoutgoing</literal>&emdash;before 17.1772 + starting to propagate changesets</title> 17.1773 + 17.1774 + <para>This hook is invoked before Mercurial knows the identities 17.1775 + of the changesets to be transmitted. 17.1776 + </para> 17.1777 + 17.1778 + <para>One use for this hook is to prevent changes from being 17.1779 + transmitted to another repository. 17.1780 + </para> 17.1781 + 17.1782 + <para>Parameters to this hook: 17.1783 + </para> 17.1784 + <itemizedlist> 17.1785 + <listitem><para><literal>source</literal>: A string. The 17.1786 + source of the operation that is attempting to obtain 17.1787 + changes from this repository (see section <xref 17.1788 + linkend="sec:hook:sources"/>). See the documentation 17.1789 + for the <literal>source</literal> parameter to the 17.1790 + <literal role="hook">outgoing</literal> hook, in section 17.1791 + <xref linkend="sec:hook:outgoing"/>, for possible values 17.1792 + of 17.1793 + this parameter. 17.1794 + </para> 17.1795 + </listitem> 17.1796 + <listitem><para><literal>url</literal>: A URL. The location 17.1797 + of the remote repository, if known. See section <xref 17.1798 + linkend="sec:hook:url"/> for more 17.1799 + information. 17.1800 + </para> 17.1801 + </listitem></itemizedlist> 17.1802 + 17.1803 + <para>See also: <literal role="hook">outgoing</literal> (section 17.1804 + <xref linkend="sec:hook:outgoing"/>) 17.1805 + </para> 17.1806 + 17.1807 + </sect2> 17.1808 + <sect2 id="sec:hook:pretag"> 17.1809 + <title><literal role="hook">pretag</literal>&emdash;before 17.1810 + tagging a changeset</title> 17.1811 + 17.1812 + <para>This controlling hook is run before a tag is created. If 17.1813 + the hook succeeds, creation of the tag proceeds. If the hook 17.1814 + fails, the tag is not created. 17.1815 + </para> 17.1816 + 17.1817 + <para>Parameters to this hook: 17.1818 + </para> 17.1819 + <itemizedlist> 17.1820 + <listitem><para><literal>local</literal>: A boolean. Whether 17.1821 + the tag is local to this repository instance (i.e. stored 17.1822 + in <filename role="special">.hg/localtags</filename>) or 17.1823 + managed by Mercurial (stored in <filename 17.1824 + role="special">.hgtags</filename>). 17.1825 + </para> 17.1826 + </listitem> 17.1827 + <listitem><para><literal>node</literal>: A changeset ID. The 17.1828 + ID of the changeset to be tagged. 17.1829 + </para> 17.1830 + </listitem> 17.1831 + <listitem><para><literal>tag</literal>: A string. The name of 17.1832 + the tag to be created. 17.1833 + </para> 17.1834 + </listitem></itemizedlist> 17.1835 + 17.1836 + <para>If the tag to be created is revision-controlled, the 17.1837 + <literal role="hook">precommit</literal> and <literal 17.1838 + role="hook">pretxncommit</literal> hooks (sections <xref 17.1839 + linkend="sec:hook:commit"/> and <xref 17.1840 + linkend="sec:hook:pretxncommit"/>) will also be run. 17.1841 + </para> 17.1842 + 17.1843 + <para>See also: <literal role="hook">tag</literal> (section 17.1844 + <xref linkend="sec:hook:tag"/>) 17.1845 + </para> 17.1846 + </sect2> 17.1847 + <sect2 id="sec:hook:pretxnchangegroup"> 17.1848 + <title><literal 17.1849 + role="hook">pretxnchangegroup</literal>&emdash;before 17.1850 + completing addition of remote changesets</title> 17.1851 + 17.1852 + <para>This controlling hook is run before a 17.1853 + transaction&emdash;that manages the addition of a group of new 17.1854 + changesets from outside the repository&emdash;completes. If 17.1855 + the hook succeeds, the transaction completes, and all of the 17.1856 + changesets become permanent within this repository. If the 17.1857 + hook fails, the transaction is rolled back, and the data for 17.1858 + the changesets is erased. 17.1859 + </para> 17.1860 + 17.1861 + <para>This hook can access the metadata associated with the 17.1862 + almost-added changesets, but it should not do anything 17.1863 + permanent with this data. It must also not modify the working 17.1864 + directory. 17.1865 + </para> 17.1866 + 17.1867 + <para>While this hook is running, if other Mercurial processes 17.1868 + access this repository, they will be able to see the 17.1869 + almost-added changesets as if they are permanent. This may 17.1870 + lead to race conditions if you do not take steps to avoid 17.1871 + them. 17.1872 + </para> 17.1873 + 17.1874 + <para>This hook can be used to automatically vet a group of 17.1875 + changesets. If the hook fails, all of the changesets are 17.1876 + <quote>rejected</quote> when the transaction rolls back. 17.1877 + </para> 17.1878 + 17.1879 + <para>Parameters to this hook: 17.1880 + </para> 17.1881 + <itemizedlist> 17.1882 + <listitem><para><literal>node</literal>: A changeset ID. The 17.1883 + changeset ID of the first changeset in the group that was 17.1884 + added. All changesets between this and 17.1885 + \index{tags!<literal>tip</literal>}<literal>tip</literal>, 17.1886 + inclusive, were added by a single <command 17.1887 + role="hg-cmd">hg pull</command>, <command 17.1888 + role="hg-cmd">hg push</command> or <command 17.1889 + role="hg-cmd">hg unbundle</command>. 17.1890 + </para> 17.1891 + </listitem> 17.1892 + <listitem><para><literal>source</literal>: A string. The 17.1893 + source of these changes. See section <xref 17.1894 + linkend="sec:hook:sources"/> for details. 17.1895 + </para> 17.1896 + </listitem> 17.1897 + <listitem><para><literal>url</literal>: A URL. The location 17.1898 + of the remote repository, if known. See section <xref 17.1899 + linkend="sec:hook:url"/> for more 17.1900 + information. 17.1901 + </para> 17.1902 + </listitem></itemizedlist> 17.1903 + 17.1904 + <para>See also: <literal role="hook">changegroup</literal> 17.1905 + (section <xref linkend="sec:hook:changegroup"/>), <literal 17.1906 + role="hook">incoming</literal> (section <xref 17.1907 + linkend="sec:hook:incoming"/>), <literal 17.1908 + role="hook">prechangegroup</literal> (section <xref 17.1909 + linkend="sec:hook:prechangegroup"/>) 17.1910 + </para> 17.1911 + 17.1912 + </sect2> 17.1913 + <sect2 id="sec:hook:pretxncommit"> 17.1914 + <title><literal role="hook">pretxncommit</literal>&emdash;before 17.1915 + completing commit of new changeset</title> 17.1916 + 17.1917 + <para>This controlling hook is run before a 17.1918 + transaction&emdash;that manages a new commit&emdash;completes. 17.1919 + If the hook succeeds, the transaction completes and the 17.1920 + changeset becomes permanent within this repository. If the 17.1921 + hook fails, the transaction is rolled back, and the commit 17.1922 + data is erased. 17.1923 + </para> 17.1924 + 17.1925 + <para>This hook can access the metadata associated with the 17.1926 + almost-new changeset, but it should not do anything permanent 17.1927 + with this data. It must also not modify the working 17.1928 + directory. 17.1929 + </para> 17.1930 + 17.1931 + <para>While this hook is running, if other Mercurial processes 17.1932 + access this repository, they will be able to see the 17.1933 + almost-new changeset as if it is permanent. This may lead to 17.1934 + race conditions if you do not take steps to avoid them. 17.1935 + </para> 17.1936 + 17.1937 + <para>Parameters to this hook: 17.1938 + </para> 17.1939 + <itemizedlist> 17.1940 + <listitem><para><literal>node</literal>: A changeset ID. The 17.1941 + changeset ID of the newly committed changeset. 17.1942 + </para> 17.1943 + </listitem> 17.1944 + <listitem><para><literal>parent1</literal>: A changeset ID. 17.1945 + The changeset ID of the first parent of the newly 17.1946 + committed changeset. 17.1947 + </para> 17.1948 + </listitem> 17.1949 + <listitem><para><literal>parent2</literal>: A changeset ID. 17.1950 + The changeset ID of the second parent of the newly 17.1951 + committed changeset. 17.1952 + </para> 17.1953 + </listitem></itemizedlist> 17.1954 + 17.1955 + <para>See also: <literal role="hook">precommit</literal> 17.1956 + (section <xref linkend="sec:hook:precommit"/>) 17.1957 + </para> 17.1958 + 17.1959 + </sect2> 17.1960 + <sect2 id="sec:hook:preupdate"> 17.1961 + <title><literal role="hook">preupdate</literal>&emdash;before 17.1962 + updating or merging working directory</title> 17.1963 + 17.1964 + <para>This controlling hook is run before an update or merge of 17.1965 + the working directory begins. It is run only if Mercurial's 17.1966 + normal pre-update checks determine that the update or merge 17.1967 + can proceed. If the hook succeeds, the update or merge may 17.1968 + proceed; if it fails, the update or merge does not start. 17.1969 + </para> 17.1970 + 17.1971 + <para>Parameters to this hook: 17.1972 + </para> 17.1973 + <itemizedlist> 17.1974 + <listitem><para><literal>parent1</literal>: A changeset ID. 17.1975 + The ID of the parent that the working directory is to be 17.1976 + updated to. If the working directory is being merged, it 17.1977 + will not change this parent. 17.1978 + </para> 17.1979 + </listitem> 17.1980 + <listitem><para><literal>parent2</literal>: A changeset ID. 17.1981 + Only set if the working directory is being merged. The ID 17.1982 + of the revision that the working directory is being merged 17.1983 + with. 17.1984 + </para> 17.1985 + </listitem></itemizedlist> 17.1986 + 17.1987 + <para>See also: <literal role="hook">update</literal> (section 17.1988 + <xref linkend="sec:hook:update"/>) 17.1989 + </para> 17.1990 + 17.1991 + </sect2> 17.1992 + <sect2 id="sec:hook:tag"> 17.1993 + <title><literal role="hook">tag</literal>&emdash;after tagging a 17.1994 + changeset</title> 17.1995 + 17.1996 + <para>This hook is run after a tag has been created. 17.1997 + </para> 17.1998 + 17.1999 + <para>Parameters to this hook: 17.2000 + </para> 17.2001 + <itemizedlist> 17.2002 + <listitem><para><literal>local</literal>: A boolean. Whether 17.2003 + the new tag is local to this repository instance (i.e. 17.2004 + stored in <filename 17.2005 + role="special">.hg/localtags</filename>) or managed by 17.2006 + Mercurial (stored in <filename 17.2007 + role="special">.hgtags</filename>). 17.2008 + </para> 17.2009 + </listitem> 17.2010 + <listitem><para><literal>node</literal>: A changeset ID. The 17.2011 + ID of the changeset that was tagged. 17.2012 + </para> 17.2013 + </listitem> 17.2014 + <listitem><para><literal>tag</literal>: A string. The name of 17.2015 + the tag that was created. 17.2016 + </para> 17.2017 + </listitem></itemizedlist> 17.2018 + 17.2019 + <para>If the created tag is revision-controlled, the <literal 17.2020 + role="hook">commit</literal> hook (section <xref 17.2021 + linkend="sec:hook:commit"/>) is run before this hook. 17.2022 + </para> 17.2023 + 17.2024 + <para>See also: <literal role="hook">pretag</literal> (section 17.2025 + <xref linkend="sec:hook:pretag"/>) 17.2026 + </para> 17.2027 + 17.2028 + </sect2> 17.2029 + <sect2 id="sec:hook:update"> 17.2030 + <title><literal role="hook">update</literal>&emdash;after 17.2031 + updating or merging working directory</title> 17.2032 + 17.2033 + <para>This hook is run after an update or merge of the working 17.2034 + directory completes. Since a merge can fail (if the external 17.2035 + <command>hgmerge</command> command fails to resolve conflicts 17.2036 + in a file), this hook communicates whether the update or merge 17.2037 + completed cleanly. 17.2038 + </para> 17.2039 + 17.2040 + <itemizedlist> 17.2041 + <listitem><para><literal>error</literal>: A boolean. 17.2042 + Indicates whether the update or merge completed 17.2043 + successfully. 17.2044 + </para> 17.2045 + </listitem> 17.2046 + <listitem><para><literal>parent1</literal>: A changeset ID. 17.2047 + The ID of the parent that the working directory was 17.2048 + updated to. If the working directory was merged, it will 17.2049 + not have changed this parent. 17.2050 + </para> 17.2051 + </listitem> 17.2052 + <listitem><para><literal>parent2</literal>: A changeset ID. 17.2053 + Only set if the working directory was merged. The ID of 17.2054 + the revision that the working directory was merged with. 17.2055 + </para> 17.2056 + </listitem></itemizedlist> 17.2057 + 17.2058 + <para>See also: <literal role="hook">preupdate</literal> 17.2059 + (section <xref linkend="sec:hook:preupdate"/>) 17.2060 + </para> 17.2061 + 17.2062 + </sect2> 17.2063 + </sect1> 17.2064 +</chapter> 17.2065 + 17.2066 +<!-- 17.2067 +local variables: 17.2068 +sgml-parent-document: ("00book.xml" "book" "chapter") 17.2069 +end: 17.2070 +-->
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/en/ch11-template.xml Wed Feb 18 00:22:09 2009 -0800 18.3 @@ -0,0 +1,673 @@ 18.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 18.5 + 18.6 +<chapter id="chap:template"> 18.7 + <title>Customising the output of Mercurial</title> 18.8 + 18.9 + <para>Mercurial provides a powerful mechanism to let you control how 18.10 + it displays information. The mechanism is based on templates. 18.11 + You can use templates to generate specific output for a single 18.12 + command, or to customise the entire appearance of the built-in web 18.13 + interface.</para> 18.14 + 18.15 + <sect1 id="sec:style"> 18.16 + <title>Using precanned output styles</title> 18.17 + 18.18 + <para>Packaged with Mercurial are some output styles that you can 18.19 + use immediately. A style is simply a precanned template that 18.20 + someone wrote and installed somewhere that Mercurial can 18.21 + find.</para> 18.22 + 18.23 + <para>Before we take a look at Mercurial's bundled styles, let's 18.24 + review its normal output.</para> 18.25 + 18.26 + <para><!-- &interaction.template.simple.normal; --></para> 18.27 + 18.28 + <para>This is somewhat informative, but it takes up a lot of 18.29 + space&emdash;five lines of output per changeset. The 18.30 + <literal>compact</literal> style reduces this to three lines, 18.31 + presented in a sparse manner.</para> 18.32 + 18.33 + <para><!-- &interaction.template.simple.compact; --></para> 18.34 + 18.35 + <para>The <literal>changelog</literal> style hints at the 18.36 + expressive power of Mercurial's templating engine. This style 18.37 + attempts to follow the GNU Project's changelog 18.38 + guidelines<citation>web:changelog</citation>.</para> 18.39 + 18.40 + <para><!-- &interaction.template.simple.changelog; --></para> 18.41 + 18.42 + <para>You will not be shocked to learn that Mercurial's default 18.43 + output style is named <literal>default</literal>.</para> 18.44 + 18.45 + <sect2> 18.46 + <title>Setting a default style</title> 18.47 + 18.48 + <para>You can modify the output style that Mercurial will use 18.49 + for every command by editing your <filename role="special"> 18.50 + /.hgrc</filename>\ file, naming the style you would prefer 18.51 + to use.</para> 18.52 + 18.53 + <programlisting>[ui] style = compact</programlisting> 18.54 + 18.55 + <para>If you write a style of your own, you can use it by either 18.56 + providing the path to your style file, or copying your style 18.57 + file into a location where Mercurial can find it (typically 18.58 + the <literal>templates</literal> subdirectory of your 18.59 + Mercurial install directory).</para> 18.60 + 18.61 + </sect2> 18.62 + </sect1> 18.63 + <sect1> 18.64 + <title>Commands that support styles and templates</title> 18.65 + 18.66 + <para>All of Mercurial's 18.67 + <quote><literal>log</literal>-like</quote> commands let you use 18.68 + styles and templates: <command role="hg-cmd">hg 18.69 + incoming</command>, <command role="hg-cmd">hg log</command>, 18.70 + <command role="hg-cmd">hg outgoing</command>, and <command 18.71 + role="hg-cmd">hg tip</command>.</para> 18.72 + 18.73 + <para>As I write this manual, these are so far the only commands 18.74 + that support styles and templates. Since these are the most 18.75 + important commands that need customisable output, there has been 18.76 + little pressure from the Mercurial user community to add style 18.77 + and template support to other commands.</para> 18.78 + 18.79 + </sect1> 18.80 + <sect1> 18.81 + <title>The basics of templating</title> 18.82 + 18.83 + <para>At its simplest, a Mercurial template is a piece of text. 18.84 + Some of the text never changes, while other parts are 18.85 + <emphasis>expanded</emphasis>, or replaced with new text, when 18.86 + necessary.</para> 18.87 + 18.88 + <para>Before we continue, let's look again at a simple example of 18.89 + Mercurial's normal output.</para> 18.90 + 18.91 + <para><!-- &interaction.template.simple.normal; --></para> 18.92 + 18.93 + <para>Now, let's run the same command, but using a template to 18.94 + change its output.</para> 18.95 + 18.96 + <para><!-- &interaction.template.simple.simplest; --></para> 18.97 + 18.98 + <para>The example above illustrates the simplest possible 18.99 + template; it's just a piece of static text, printed once for 18.100 + each changeset. The <option 18.101 + role="hg-opt-log">--template</option> option to the <command 18.102 + role="hg-cmd">hg log</command> command tells Mercurial to use 18.103 + the given text as the template when printing each 18.104 + changeset.</para> 18.105 + 18.106 + <para>Notice that the template string above ends with the text 18.107 + <quote><literal>\n</literal></quote>. This is an 18.108 + <emphasis>escape sequence</emphasis>, telling Mercurial to print 18.109 + a newline at the end of each template item. If you omit this 18.110 + newline, Mercurial will run each piece of output together. See 18.111 + section <xref linkend="sec:template:escape"/> for more details 18.112 + of escape sequences.</para> 18.113 + 18.114 + <para>A template that prints a fixed string of text all the time 18.115 + isn't very useful; let's try something a bit more 18.116 + complex.</para> 18.117 + 18.118 + <para><!-- &interaction.template.simple.simplesub; --></para> 18.119 + 18.120 + <para>As you can see, the string 18.121 + <quote><literal>{desc}</literal></quote> in the template has 18.122 + been replaced in the output with the description of each 18.123 + changeset. Every time Mercurial finds text enclosed in curly 18.124 + braces (<quote><literal>{</literal></quote> and 18.125 + <quote>\texttt{}}</quote>), it will try to replace the braces 18.126 + and text with the expansion of whatever is inside. To print a 18.127 + literal curly brace, you must escape it, as described in section 18.128 + <xref 18.129 + linkend="sec:template:escape"/>.</para> 18.130 + 18.131 + </sect1> 18.132 + <sect1 id="sec:template:keyword"> 18.133 + <title>Common template keywords</title> 18.134 + 18.135 + <para>You can start writing simple templates immediately using the 18.136 + keywords below.</para> 18.137 + 18.138 + <itemizedlist> 18.139 + <listitem><para><literal 18.140 + role="template-keyword">author</literal>: String. The 18.141 + unmodified author of the changeset.</para> 18.142 + </listitem> 18.143 + <listitem><para><literal 18.144 + role="template-keyword">branches</literal>: String. The 18.145 + name of the branch on which the changeset was committed. 18.146 + Will be empty if the branch name was 18.147 + <literal>default</literal>.</para> 18.148 + </listitem> 18.149 + <listitem><para><literal role="template-keyword">date</literal>: 18.150 + Date information. The date when the changeset was 18.151 + committed. This is <emphasis>not</emphasis> human-readable; 18.152 + you must pass it through a filter that will render it 18.153 + appropriately. See section <xref 18.154 + linkend="sec:template:filter"/> for more information 18.155 + on filters. The date is expressed as a pair of numbers. The 18.156 + first number is a Unix UTC timestamp (seconds since January 18.157 + 1, 1970); the second is the offset of the committer's 18.158 + timezone from UTC, in seconds.</para> 18.159 + </listitem> 18.160 + <listitem><para><literal role="template-keyword">desc</literal>: 18.161 + String. The text of the changeset description.</para> 18.162 + </listitem> 18.163 + <listitem><para><literal 18.164 + role="template-keyword">files</literal>: List of strings. 18.165 + All files modified, added, or removed by this 18.166 + changeset.</para> 18.167 + </listitem> 18.168 + <listitem><para><literal 18.169 + role="template-keyword">file_adds</literal>: List of 18.170 + strings. Files added by this changeset.</para> 18.171 + </listitem> 18.172 + <listitem><para><literal 18.173 + role="template-keyword">file_dels</literal>: List of 18.174 + strings. Files removed by this changeset.</para> 18.175 + </listitem> 18.176 + <listitem><para><literal role="template-keyword">node</literal>: 18.177 + String. The changeset identification hash, as a 18.178 + 40-character hexadecimal string.</para> 18.179 + </listitem> 18.180 + <listitem><para><literal 18.181 + role="template-keyword">parents</literal>: List of 18.182 + strings. The parents of the changeset.</para> 18.183 + </listitem> 18.184 + <listitem><para><literal role="template-keyword">rev</literal>: 18.185 + Integer. The repository-local changeset revision 18.186 + number.</para> 18.187 + </listitem> 18.188 + <listitem><para><literal role="template-keyword">tags</literal>: 18.189 + List of strings. Any tags associated with the 18.190 + changeset.</para> 18.191 + </listitem></itemizedlist> 18.192 + 18.193 + <para>A few simple experiments will show us what to expect when we 18.194 + use these keywords; you can see the results below.</para> 18.195 + 18.196 +<!-- &interaction.template.simple.keywords; --> 18.197 + 18.198 + <para>As we noted above, the date keyword does not produce 18.199 + human-readable output, so we must treat it specially. This 18.200 + involves using a <emphasis>filter</emphasis>, about which more 18.201 + in section <xref 18.202 + linkend="sec:template:filter"/>.</para> 18.203 + 18.204 + <para><!-- &interaction.template.simple.datekeyword; --></para> 18.205 + 18.206 + </sect1> 18.207 + <sect1 id="sec:template:escape"> 18.208 + <title>Escape sequences</title> 18.209 + 18.210 + <para>Mercurial's templating engine recognises the most commonly 18.211 + used escape sequences in strings. When it sees a backslash 18.212 + (<quote><literal>\</literal></quote>) character, it looks at the 18.213 + following character and substitutes the two characters with a 18.214 + single replacement, as described below.</para> 18.215 + 18.216 + <itemizedlist> 18.217 + <listitem><para><literal>\textbackslash\textbackslash</literal>: 18.218 + Backslash, <quote><literal>\</literal></quote>, ASCII 18.219 + 134.</para> 18.220 + </listitem> 18.221 + <listitem><para><literal>\textbackslash n</literal>: Newline, 18.222 + ASCII 12.</para> 18.223 + </listitem> 18.224 + <listitem><para><literal>\textbackslash r</literal>: Carriage 18.225 + return, ASCII 15.</para> 18.226 + </listitem> 18.227 + <listitem><para><literal>\textbackslash t</literal>: Tab, ASCII 18.228 + 11.</para> 18.229 + </listitem> 18.230 + <listitem><para><literal>\textbackslash v</literal>: Vertical 18.231 + tab, ASCII 13.</para> 18.232 + </listitem> 18.233 + <listitem><para><literal>\textbackslash {</literal>: Open curly 18.234 + brace, <quote><literal>{</literal></quote>, ASCII 18.235 + 173.</para> 18.236 + </listitem> 18.237 + <listitem><para><literal>\textbackslash }</literal>: Close curly 18.238 + brace, <quote><literal>}</literal></quote>, ASCII 18.239 + 175.</para> 18.240 + </listitem></itemizedlist> 18.241 + 18.242 + <para>As indicated above, if you want the expansion of a template 18.243 + to contain a literal <quote><literal>\</literal></quote>, 18.244 + <quote><literal>{</literal></quote>, or 18.245 + <quote><literal>{</literal></quote> character, you must escape 18.246 + it.</para> 18.247 + 18.248 + </sect1> 18.249 + <sect1 id="sec:template:filter"> 18.250 + <title>Filtering keywords to change their results</title> 18.251 + 18.252 + <para>Some of the results of template expansion are not 18.253 + immediately easy to use. Mercurial lets you specify an optional 18.254 + chain of <emphasis>filters</emphasis> to modify the result of 18.255 + expanding a keyword. You have already seen a common filter, 18.256 + <literal role="template-kw-filt-date">isodate</literal>, in 18.257 + action above, to make a date readable.</para> 18.258 + 18.259 + <para>Below is a list of the most commonly used filters that 18.260 + Mercurial supports. While some filters can be applied to any 18.261 + text, others can only be used in specific circumstances. The 18.262 + name of each filter is followed first by an indication of where 18.263 + it can be used, then a description of its effect.</para> 18.264 + 18.265 + <itemizedlist> 18.266 + <listitem><para><literal 18.267 + role="template-filter">addbreaks</literal>: Any text. Add 18.268 + an XHTML <quote><literal><br/></literal></quote> tag 18.269 + before the end of every line except the last. For example, 18.270 + <quote><literal>foo\nbar</literal></quote> becomes 18.271 + <quote><literal>foo<br/>\nbar</literal></quote>.</para> 18.272 + </listitem> 18.273 + <listitem><para><literal 18.274 + role="template-kw-filt-date">age</literal>: <literal 18.275 + role="template-keyword">date</literal> keyword. Render 18.276 + the age of the date, relative to the current time. Yields a 18.277 + string like <quote><literal>10 18.278 + minutes</literal></quote>.</para> 18.279 + </listitem> 18.280 + <listitem><para><literal 18.281 + role="template-filter">basename</literal>: Any text, but 18.282 + most useful for the <literal 18.283 + role="template-keyword">files</literal> keyword and its 18.284 + relatives. Treat the text as a path, and return the 18.285 + basename. For example, 18.286 + <quote><literal>foo/bar/baz</literal></quote> becomes 18.287 + <quote><literal>baz</literal></quote>.</para> 18.288 + </listitem> 18.289 + <listitem><para><literal 18.290 + role="template-kw-filt-date">date</literal>: <literal 18.291 + role="template-keyword">date</literal> keyword. Render a 18.292 + date in a similar format to the Unix <literal 18.293 + role="template-keyword">date</literal> command, but with 18.294 + timezone included. Yields a string like <quote><literal>Mon 18.295 + Sep 04 15:13:13 2006 -0700</literal></quote>.</para> 18.296 + </listitem> 18.297 + <listitem><para><literal 18.298 + role="template-kw-filt-author">domain</literal>: Any text, 18.299 + but most useful for the <literal 18.300 + role="template-keyword">author</literal> keyword. Finds 18.301 + the first string that looks like an email address, and 18.302 + extract just the domain component. For example, 18.303 + <quote><literal>Bryan O'Sullivan 18.304 + <bos@serpentine.com></literal></quote> becomes 18.305 + <quote><literal>serpentine.com</literal></quote>.</para> 18.306 + </listitem> 18.307 + <listitem><para><literal 18.308 + role="template-kw-filt-author">email</literal>: Any text, 18.309 + but most useful for the <literal 18.310 + role="template-keyword">author</literal> keyword. Extract 18.311 + the first string that looks like an email address. For 18.312 + example, <quote><literal>Bryan O'Sullivan 18.313 + <bos@serpentine.com></literal></quote> becomes 18.314 + <quote><literal>bos@serpentine.com</literal></quote>.</para> 18.315 + </listitem> 18.316 + <listitem><para><literal 18.317 + role="template-filter">escape</literal>: Any text. 18.318 + Replace the special XML/XHTML characters 18.319 + <quote><literal>&</literal></quote>, 18.320 + <quote><literal><</literal></quote> and 18.321 + <quote><literal>></literal></quote> with XML 18.322 + entities.</para> 18.323 + </listitem> 18.324 + <listitem><para><literal 18.325 + role="template-filter">fill68</literal>: Any text. Wrap 18.326 + the text to fit in 68 columns. This is useful before you 18.327 + pass text through the <literal 18.328 + role="template-filter">tabindent</literal> filter, and 18.329 + still want it to fit in an 80-column fixed-font 18.330 + window.</para> 18.331 + </listitem> 18.332 + <listitem><para><literal 18.333 + role="template-filter">fill76</literal>: Any text. Wrap 18.334 + the text to fit in 76 columns.</para> 18.335 + </listitem> 18.336 + <listitem><para><literal 18.337 + role="template-filter">firstline</literal>: Any text. 18.338 + Yield the first line of text, without any trailing 18.339 + newlines.</para> 18.340 + </listitem> 18.341 + <listitem><para><literal 18.342 + role="template-kw-filt-date">hgdate</literal>: <literal 18.343 + role="template-keyword">date</literal> keyword. Render 18.344 + the date as a pair of readable numbers. Yields a string 18.345 + like <quote><literal>1157407993 18.346 + 25200</literal></quote>.</para> 18.347 + </listitem> 18.348 + <listitem><para><literal 18.349 + role="template-kw-filt-date">isodate</literal>: <literal 18.350 + role="template-keyword">date</literal> keyword. Render 18.351 + the date as a text string in ISO 8601 format. Yields a 18.352 + string like <quote><literal>2006-09-04 15:13:13 18.353 + -0700</literal></quote>.</para> 18.354 + </listitem> 18.355 + <listitem><para><literal 18.356 + role="template-filter">obfuscate</literal>: Any text, but 18.357 + most useful for the <literal 18.358 + role="template-keyword">author</literal> keyword. Yield 18.359 + the input text rendered as a sequence of XML entities. This 18.360 + helps to defeat some particularly stupid screen-scraping 18.361 + email harvesting spambots.</para> 18.362 + </listitem> 18.363 + <listitem><para><literal 18.364 + role="template-kw-filt-author">person</literal>: Any text, 18.365 + but most useful for the <literal 18.366 + role="template-keyword">author</literal> keyword. Yield 18.367 + the text before an email address. For example, 18.368 + <quote><literal>Bryan O'Sullivan 18.369 + <bos@serpentine.com></literal></quote> becomes 18.370 + <quote><literal>Bryan O'Sullivan</literal></quote>.</para> 18.371 + </listitem> 18.372 + <listitem><para><literal 18.373 + role="template-kw-filt-date">rfc822date</literal>: 18.374 + <literal role="template-keyword">date</literal> keyword. 18.375 + Render a date using the same format used in email headers. 18.376 + Yields a string like <quote><literal>Mon, 04 Sep 2006 18.377 + 15:13:13 -0700</literal></quote>.</para> 18.378 + </listitem> 18.379 + <listitem><para><literal 18.380 + role="template-kw-filt-node">short</literal>: Changeset 18.381 + hash. Yield the short form of a changeset hash, i.e. a 18.382 + 12-character hexadecimal string.</para> 18.383 + </listitem> 18.384 + <listitem><para><literal 18.385 + role="template-kw-filt-date">shortdate</literal>: <literal 18.386 + role="template-keyword">date</literal> keyword. Render 18.387 + the year, month, and day of the date. Yields a string like 18.388 + <quote><literal>2006-09-04</literal></quote>.</para> 18.389 + </listitem> 18.390 + <listitem><para><literal role="template-filter">strip</literal>: 18.391 + Any text. Strip all leading and trailing whitespace from 18.392 + the string.</para> 18.393 + </listitem> 18.394 + <listitem><para><literal 18.395 + role="template-filter">tabindent</literal>: Any text. 18.396 + Yield the text, with every line except the first starting 18.397 + with a tab character.</para> 18.398 + </listitem> 18.399 + <listitem><para><literal 18.400 + role="template-filter">urlescape</literal>: Any text. 18.401 + Escape all characters that are considered 18.402 + <quote>special</quote> by URL parsers. For example, 18.403 + <literal>foo bar</literal> becomes 18.404 + <literal>foo%20bar</literal>.</para> 18.405 + </listitem> 18.406 + <listitem><para><literal 18.407 + role="template-kw-filt-author">user</literal>: Any text, 18.408 + but most useful for the <literal 18.409 + role="template-keyword">author</literal> keyword. Return 18.410 + the <quote>user</quote> portion of an email address. For 18.411 + example, <quote><literal>Bryan O'Sullivan 18.412 + <bos@serpentine.com></literal></quote> becomes 18.413 + <quote><literal>bos</literal></quote>.</para> 18.414 + </listitem></itemizedlist> 18.415 + 18.416 +<!-- &interaction.template.simple.manyfilters; --> 18.417 + 18.418 + <note> 18.419 + <para> If you try to apply a filter to a piece of data that it 18.420 + cannot process, Mercurial will fail and print a Python 18.421 + exception. For example, trying to run the output of the 18.422 + <literal role="template-keyword">desc</literal> keyword into 18.423 + the <literal role="template-kw-filt-date">isodate</literal> 18.424 + filter is not a good idea.</para> 18.425 + </note> 18.426 + 18.427 + <sect2> 18.428 + <title>Combining filters</title> 18.429 + 18.430 + <para>It is easy to combine filters to yield output in the form 18.431 + you would like. The following chain of filters tidies up a 18.432 + description, then makes sure that it fits cleanly into 68 18.433 + columns, then indents it by a further 8 characters (at least 18.434 + on Unix-like systems, where a tab is conventionally 8 18.435 + characters wide).</para> 18.436 + 18.437 + <para><!-- &interaction.template.simple.combine; --></para> 18.438 + 18.439 + <para>Note the use of <quote><literal>\t</literal></quote> (a 18.440 + tab character) in the template to force the first line to be 18.441 + indented; this is necessary since <literal 18.442 + role="template-keyword">tabindent</literal> indents all 18.443 + lines <emphasis>except</emphasis> the first.</para> 18.444 + 18.445 + <para>Keep in mind that the order of filters in a chain is 18.446 + significant. The first filter is applied to the result of the 18.447 + keyword; the second to the result of the first filter; and so 18.448 + on. For example, using <literal>fill68|tabindent</literal> 18.449 + gives very different results from 18.450 + <literal>tabindent|fill68</literal>.</para> 18.451 + 18.452 + 18.453 + </sect2> 18.454 + </sect1> 18.455 + <sect1> 18.456 + <title>From templates to styles</title> 18.457 + 18.458 + <para>A command line template provides a quick and simple way to 18.459 + format some output. Templates can become verbose, though, and 18.460 + it's useful to be able to give a template a name. A style file 18.461 + is a template with a name, stored in a file.</para> 18.462 + 18.463 + <para>More than that, using a style file unlocks the power of 18.464 + Mercurial's templating engine in ways that are not possible 18.465 + using the command line <option 18.466 + role="hg-opt-log">--template</option> option.</para> 18.467 + 18.468 + <sect2> 18.469 + <title>The simplest of style files</title> 18.470 + 18.471 + <para>Our simple style file contains just one line:</para> 18.472 + 18.473 + <para><!-- &interaction.template.simple.rev; --></para> 18.474 + 18.475 + <para>This tells Mercurial, <quote>if you're printing a 18.476 + changeset, use the text on the right as the 18.477 + template</quote>.</para> 18.478 + 18.479 + </sect2> 18.480 + <sect2> 18.481 + <title>Style file syntax</title> 18.482 + 18.483 + <para>The syntax rules for a style file are simple.</para> 18.484 + 18.485 + <itemizedlist> 18.486 + <listitem><para>The file is processed one line at a 18.487 + time.</para> 18.488 + </listitem> 18.489 + <listitem><para>Leading and trailing white space are 18.490 + ignored.</para> 18.491 + </listitem> 18.492 + <listitem><para>Empty lines are skipped.</para> 18.493 + </listitem> 18.494 + <listitem><para>If a line starts with either of the characters 18.495 + <quote><literal>#</literal></quote> or 18.496 + <quote><literal>;</literal></quote>, the entire line is 18.497 + treated as a comment, and skipped as if empty.</para> 18.498 + </listitem> 18.499 + <listitem><para>A line starts with a keyword. This must start 18.500 + with an alphabetic character or underscore, and can 18.501 + subsequently contain any alphanumeric character or 18.502 + underscore. (In regexp notation, a keyword must match 18.503 + <literal>[A-Za-z_][A-Za-z0-9_]*</literal>.)</para> 18.504 + </listitem> 18.505 + <listitem><para>The next element must be an 18.506 + <quote><literal>=</literal></quote> character, which can 18.507 + be preceded or followed by an arbitrary amount of white 18.508 + space.</para> 18.509 + </listitem> 18.510 + <listitem><para>If the rest of the line starts and ends with 18.511 + matching quote characters (either single or double quote), 18.512 + it is treated as a template body.</para> 18.513 + </listitem> 18.514 + <listitem><para>If the rest of the line <emphasis>does 18.515 + not</emphasis> start with a quote character, it is 18.516 + treated as the name of a file; the contents of this file 18.517 + will be read and used as a template body.</para> 18.518 + </listitem></itemizedlist> 18.519 + 18.520 + </sect2> 18.521 + </sect1> 18.522 + <sect1> 18.523 + <title>Style files by example</title> 18.524 + 18.525 + <para>To illustrate how to write a style file, we will construct a 18.526 + few by example. Rather than provide a complete style file and 18.527 + walk through it, we'll mirror the usual process of developing a 18.528 + style file by starting with something very simple, and walking 18.529 + through a series of successively more complete examples.</para> 18.530 + 18.531 + <sect2> 18.532 + <title>Identifying mistakes in style files</title> 18.533 + 18.534 + <para>If Mercurial encounters a problem in a style file you are 18.535 + working on, it prints a terse error message that, once you 18.536 + figure out what it means, is actually quite useful.</para> 18.537 + 18.538 +<!-- &interaction.template.svnstyle.syntax.input; --> 18.539 + 18.540 + <para>Notice that <filename>broken.style</filename> attempts to 18.541 + define a <literal>changeset</literal> keyword, but forgets to 18.542 + give any content for it. When instructed to use this style 18.543 + file, Mercurial promptly complains.</para> 18.544 + 18.545 + <para><!-- &interaction.template.svnstyle.syntax.error; 18.546 + --></para> 18.547 + 18.548 + <para>This error message looks intimidating, but it is not too 18.549 + hard to follow.</para> 18.550 + 18.551 + <itemizedlist> 18.552 + <listitem><para>The first component is simply Mercurial's way 18.553 + of saying <quote>I am giving up</quote>.</para> 18.554 + <programlisting>___abort___: broken.style:1: parse 18.555 + error</programlisting> 18.556 + </listitem> 18.557 + <listitem><para>Next comes the name of the style file that 18.558 + contains the error.</para> 18.559 + <programlisting> 18.560 + abort: ___broken.style___:1: parse error 18.561 + </programlisting> 18.562 + </listitem> 18.563 + <listitem><para>Following the file name is the line number 18.564 + where the error was encountered.</para> 18.565 + <programlisting>abort: broken.style:___1___: parse 18.566 + error</programlisting> 18.567 + </listitem> 18.568 + <listitem><para>Finally, a description of what went 18.569 + wrong.</para> 18.570 + <programlisting>abort: broken.style:1: ___parse 18.571 + error___</programlisting> 18.572 + </listitem> 18.573 + <listitem><para>The description of the problem is not always 18.574 + clear (as in this case), but even when it is cryptic, it 18.575 + is almost always trivial to visually inspect the offending 18.576 + line in the style file and see what is wrong.</para> 18.577 + </listitem></itemizedlist> 18.578 + 18.579 + </sect2> 18.580 + <sect2> 18.581 + <title>Uniquely identifying a repository</title> 18.582 + 18.583 + <para>If you would like to be able to identify a Mercurial 18.584 + repository <quote>fairly uniquely</quote> using a short string 18.585 + as an identifier, you can use the first revision in the 18.586 + repository. <!-- &interaction.template.svnstyle.id; --> This 18.587 + is not guaranteed to be unique, but it is nevertheless useful 18.588 + in many cases.</para> 18.589 + <itemizedlist> 18.590 + <listitem><para>It will not work in a completely empty 18.591 + repository, because such a repository does not have a 18.592 + revision zero.</para> 18.593 + </listitem> 18.594 + <listitem><para>Neither will it work in the (extremely rare) 18.595 + case where a repository is a merge of two or more formerly 18.596 + independent repositories, and you still have those 18.597 + repositories around.</para> 18.598 + </listitem></itemizedlist> 18.599 + <para>Here are some uses to which you could put this 18.600 + identifier:</para> 18.601 + <itemizedlist> 18.602 + <listitem><para>As a key into a table for a database that 18.603 + manages repositories on a server.</para> 18.604 + </listitem> 18.605 + <listitem><para>As half of a {<emphasis>repository 18.606 + ID</emphasis>, <emphasis>revision ID</emphasis>} tuple. 18.607 + Save this information away when you run an automated build 18.608 + or other activity, so that you can <quote>replay</quote> 18.609 + the build later if necessary.</para> 18.610 + </listitem></itemizedlist> 18.611 + 18.612 + </sect2> 18.613 + <sect2> 18.614 + <title>Mimicking Subversion's output</title> 18.615 + 18.616 + <para>Let's try to emulate the default output format used by 18.617 + another revision control tool, Subversion. <!-- 18.618 + &interaction.template.svnstyle.short; --></para> 18.619 + 18.620 + <para>Since Subversion's output style is fairly simple, it is 18.621 + easy to copy-and-paste a hunk of its output into a file, and 18.622 + replace the text produced above by Subversion with the 18.623 + template values we'd like to see expanded. <!-- 18.624 + &interaction.template.svnstyle.template; --></para> 18.625 + 18.626 + <para>There are a few small ways in which this template deviates 18.627 + from the output produced by Subversion.</para> 18.628 + <itemizedlist> 18.629 + <listitem><para>Subversion prints a <quote>readable</quote> 18.630 + date (the <quote>\texttt{Wed, 27 Sep 2006}</quote> in the 18.631 + example output above) in parentheses. Mercurial's 18.632 + templating engine does not provide a way to display a date 18.633 + in this format without also printing the time and time 18.634 + zone.</para> 18.635 + </listitem> 18.636 + <listitem><para>We emulate Subversion's printing of 18.637 + <quote>separator</quote> lines full of 18.638 + <quote><literal>-</literal></quote> characters by ending 18.639 + the template with such a line. We use the templating 18.640 + engine's <literal role="template-keyword">header</literal> 18.641 + keyword to print a separator line as the first line of 18.642 + output (see below), thus achieving similar output to 18.643 + Subversion.</para> 18.644 + </listitem> 18.645 + <listitem><para>Subversion's output includes a count in the 18.646 + header of the number of lines in the commit message. We 18.647 + cannot replicate this in Mercurial; the templating engine 18.648 + does not currently provide a filter that counts the number 18.649 + of lines the template generates.</para> 18.650 + </listitem></itemizedlist> 18.651 + <para>It took me no more than a minute or two of work to replace 18.652 + literal text from an example of Subversion's output with some 18.653 + keywords and filters to give the template above. The style 18.654 + file simply refers to the template. <!-- 18.655 + &interaction.template.svnstyle.style; --></para> 18.656 + 18.657 + <para>We could have included the text of the template file 18.658 + directly in the style file by enclosing it in quotes and 18.659 + replacing the newlines with 18.660 + <quote><literal>\n</literal></quote> sequences, but it would 18.661 + have made the style file too difficult to read. Readability 18.662 + is a good guide when you're trying to decide whether some text 18.663 + belongs in a style file, or in a template file that the style 18.664 + file points to. If the style file will look too big or 18.665 + cluttered if you insert a literal piece of text, drop it into 18.666 + a template instead.</para> 18.667 + 18.668 + </sect2> 18.669 + </sect1> 18.670 +</chapter> 18.671 + 18.672 +<!-- 18.673 +local variables: 18.674 +sgml-parent-document: ("00book.xml" "book" "chapter") 18.675 +end: 18.676 +-->
19.1 --- a/en/ch12-mq.xml Mon Feb 09 23:25:40 2009 -0800 19.2 +++ b/en/ch12-mq.xml Wed Feb 18 00:22:09 2009 -0800 19.3 @@ -36,17 +36,17 @@ 19.4 <para>When you have few changes to maintain, it is easy to manage 19.5 a single patch using the standard <command>diff</command> and 19.6 <command>patch</command> programs (see section <xref 19.7 - linkend="sec:mq:patch"/> for a discussion of these tools). 19.8 - Once the number of changes grows, it starts to make sense to 19.9 - maintain patches as discrete <quote>chunks of work,</quote> so 19.10 - that for example a single patch will contain only one bug fix 19.11 - (the patch might modify several files, but it's doing 19.12 - <quote>only one thing</quote>), and you may have a number of 19.13 - such patches for different bugs you need fixed and local changes 19.14 - you require. In this situation, if you submit a bug fix patch 19.15 - to the upstream maintainers of a package and they include your 19.16 - fix in a subsequent release, you can simply drop that single 19.17 - patch when you're updating to the newer release.</para> 19.18 + linkend="sec:mq:patch"/> for a discussion of these 19.19 + tools). Once the number of changes grows, it starts to make 19.20 + sense to maintain patches as discrete <quote>chunks of 19.21 + work,</quote> so that for example a single patch will contain 19.22 + only one bug fix (the patch might modify several files, but it's 19.23 + doing <quote>only one thing</quote>), and you may have a number 19.24 + of such patches for different bugs you need fixed and local 19.25 + changes you require. In this situation, if you submit a bug fix 19.26 + patch to the upstream maintainers of a package and they include 19.27 + your fix in a subsequent release, you can simply drop that 19.28 + single patch when you're updating to the newer release.</para> 19.29 19.30 <para>Maintaining a single patch against an upstream tree is a 19.31 little tedious and error-prone, but not difficult. However, the 19.32 @@ -146,42 +146,42 @@ 19.33 unification of patches and revision control.</para> 19.34 19.35 <para>A major reason that patches have persisted in the free 19.36 - software and open source world&emdash;in spite of the availability of 19.37 - increasingly capable revision control tools over the years&emdash;is 19.38 - the <emphasis>agility</emphasis> they offer.</para> 19.39 + software and open source world&emdash;in spite of the 19.40 + availability of increasingly capable revision control tools over 19.41 + the years&emdash;is the <emphasis>agility</emphasis> they 19.42 + offer.</para> 19.43 19.44 <para>Traditional revision control tools make a permanent, 19.45 irreversible record of everything that you do. While this has 19.46 great value, it's also somewhat stifling. If you want to 19.47 perform a wild-eyed experiment, you have to be careful in how 19.48 you go about it, or you risk leaving unneeded&emdash;or worse, 19.49 - misleading or destabilising&emdash;traces of your missteps and errors 19.50 - in the permanent revision record.</para> 19.51 + misleading or destabilising&emdash;traces of your missteps and 19.52 + errors in the permanent revision record.</para> 19.53 19.54 <para>By contrast, MQ's marriage of distributed revision control 19.55 with patches makes it much easier to isolate your work. Your 19.56 patches live on top of normal revision history, and you can make 19.57 them disappear or reappear at will. If you don't like a patch, 19.58 you can drop it. If a patch isn't quite as you want it to be, 19.59 - simply fix it&emdash;as many times as you need to, until you have 19.60 - refined it into the form you desire.</para> 19.61 + simply fix it&emdash;as many times as you need to, until you 19.62 + have refined it into the form you desire.</para> 19.63 19.64 <para>As an example, the integration of patches with revision 19.65 control makes understanding patches and debugging their 19.66 effects&emdash;and their interplay with the code they're based 19.67 - on&emdash;<emphasis>enormously</emphasis> easier. Since every applied 19.68 - patch has an associated changeset, you can use <command 19.69 - role="hg-cmd">hg log</command> to see which changesets and 19.70 - patches affected a file. You can use the <literal 19.71 - role="hg-ext">bisect</literal> command to binary-search 19.72 - through all changesets and applied patches to see where a bug 19.73 - got introduced or fixed. You can use the <command 19.74 + on&emdash;<emphasis>enormously</emphasis> easier. Since every 19.75 + applied patch has an associated changeset, you can give <command 19.76 + role="hg-cmd">hg log</command> a file name to see which 19.77 + changesets and patches affected the file. You can use the 19.78 + <command role="hg-cmd">hg bisect</command> command to 19.79 + binary-search through all changesets and applied patches to see 19.80 + where a bug got introduced or fixed. You can use the <command 19.81 role="hg-cmd">hg annotate</command> command to see which 19.82 changeset or patch modified a particular line of a source file. 19.83 And so on.</para> 19.84 19.85 </sect1> 19.86 - 19.87 <sect1 id="sec:mq:patch"> 19.88 <title>Understanding patches</title> 19.89 19.90 @@ -241,7 +241,8 @@ 19.91 19.92 <para>We will return to some of the more subtle aspects of patches 19.93 later (in section <xref linkend="sec:mq:adv-patch"/>), but you 19.94 - should have enough information now to use MQ.</para> 19.95 + should have 19.96 + enough information now to use MQ.</para> 19.97 19.98 </sect1> 19.99 <sect1 id="sec:mq:start"> 19.100 @@ -250,15 +251,16 @@ 19.101 <para>Because MQ is implemented as an extension, you must 19.102 explicitly enable before you can use it. (You don't need to 19.103 download anything; MQ ships with the standard Mercurial 19.104 - distribution.) To enable MQ, edit your <filename role="home"> 19.105 - /.hgrc</filename> file, and add the lines below.</para> 19.106 + distribution.) To enable MQ, edit your <filename 19.107 + role="home">~/.hgrc</filename> file, and add the lines 19.108 + below.</para> 19.109 19.110 <programlisting>[extensions] hgext.mq =</programlisting> 19.111 19.112 <para>Once the extension is enabled, it will make a number of new 19.113 commands available. To verify that the extension is working, 19.114 you can use <command role="hg-cmd">hg help</command> to see if 19.115 - the <command role="hg-ext-mq">hg qinit</command> command is now 19.116 + the <command role="hg-ext-mq">qinit</command> command is now 19.117 available.</para> 19.118 19.119 <!-- &interaction.mq.qinit-help.help; --> 19.120 @@ -266,25 +268,29 @@ 19.121 <para>You can use MQ with <emphasis>any</emphasis> Mercurial 19.122 repository, and its commands only operate within that 19.123 repository. To get started, simply prepare the repository using 19.124 - the <command role="hg-ext-mq">hg qinit</command> command. This 19.125 - command creates an empty directory called <filename 19.126 + the <command role="hg-ext-mq">qinit</command> command.</para> 19.127 + 19.128 +<!-- &interaction.mq.tutorial.qinit; --> 19.129 + 19.130 + <para>This command creates an empty directory called <filename 19.131 role="special" class="directory">.hg/patches</filename>, where 19.132 MQ will keep its metadata. As with many Mercurial commands, the 19.133 - <command role="hg-ext-mq">hg qinit</command> command prints nothing 19.134 + <command role="hg-ext-mq">qinit</command> command prints nothing 19.135 if it succeeds.</para> 19.136 -<!-- &interaction.mq.tutorial.qinit; --> 19.137 - 19.138 19.139 <sect2> 19.140 <title>Creating a new patch</title> 19.141 19.142 <para>To begin work on a new patch, use the <command 19.143 - role="hg-ext-mq">hg qnew</command> command. This command takes 19.144 - one argument, the name of the patch to create. MQ will use 19.145 - this as the name of an actual file in the <filename 19.146 - role="special" class="directory">.hg/patches</filename> 19.147 - directory, as you can see in figure <xref 19.148 - linkend="ex:mq:qnew"/>.</para> 19.149 + role="hg-ext-mq">qnew</command> command. This command takes 19.150 + one argument, the name of the patch to create.</para> 19.151 + 19.152 + <para>MQ will use this as the name of an actual file in the 19.153 + <filename role="special" 19.154 + class="directory">.hg/patches</filename> directory, as you 19.155 + can see below.</para> 19.156 + 19.157 +<!-- &interaction.mq.tutorial.qnew; --> 19.158 19.159 <para>Also newly present in the <filename role="special" 19.160 class="directory">.hg/patches</filename> directory are two 19.161 @@ -318,18 +324,19 @@ 19.162 <title>Refreshing a patch</title> 19.163 19.164 <para>When you reach a point where you want to save your work, 19.165 - use the <command role="hg-ext-mq">hg qrefresh</command> 19.166 - command to update the patch you are working on. This command 19.167 - folds the changes you have made in the working directory into 19.168 - your patch, and updates its corresponding changeset to contain 19.169 - those changes.</para> 19.170 + use the <command role="hg-ext-mq">qrefresh</command> command 19.171 + to update the patch you are working on.</para> 19.172 19.173 <!-- &interaction.mq.tutorial.qrefresh; --> 19.174 19.175 - <para>You can run <command role="hg-ext-mq">hg hg 19.176 - qrefresh</command> as often as you like, so it's a good way 19.177 - to <quote>checkpoint</quote> your work. Refresh your patch at 19.178 - an opportune time; try an experiment; and if the experiment 19.179 + <para>This command folds the changes you have made in the 19.180 + working directory into your patch, and updates its 19.181 + corresponding changeset to contain those changes.</para> 19.182 + 19.183 + <para>You can run <command role="hg-ext-mq">qrefresh</command> 19.184 + as often as you like, so it's a good way to 19.185 + <quote>checkpoint</quote> your work. Refresh your patch at an 19.186 + opportune time; try an experiment; and if the experiment 19.187 doesn't work out, <command role="hg-cmd">hg revert</command> 19.188 your modifications back to the last time you refreshed.</para> 19.189 19.190 @@ -340,38 +347,39 @@ 19.191 <title>Stacking and tracking patches</title> 19.192 19.193 <para>Once you have finished working on a patch, or need to work 19.194 - on another, you can use the <command role="hg-ext-mq">hg hg 19.195 - qnew</command> command again to create a new patch. 19.196 - Mercurial will apply this patch on top of your existing patch. 19.197 - See figure <xref linkend="ex:mq:qnew2"/> for an example. 19.198 - Notice that the patch contains the changes in our prior patch 19.199 - as part of its context (you can see this more clearly in the 19.200 - output of <command role="hg-cmd">hg 19.201 + on another, you can use the <command 19.202 + role="hg-ext-mq">qnew</command> command again to create a 19.203 + new patch. Mercurial will apply this patch on top of your 19.204 + existing patch.</para> 19.205 + 19.206 +<!-- &interaction.mq.tutorial.qnew2; --> 19.207 + <para>Notice that the patch contains the changes in our prior 19.208 + patch as part of its context (you can see this more clearly in 19.209 + the output of <command role="hg-cmd">hg 19.210 annotate</command>).</para> 19.211 19.212 -<!-- &interaction.mq.tutorial.qnew2; --> 19.213 - 19.214 <para>So far, with the exception of <command 19.215 - role="hg-ext-mq">hg qnew</command> and <command 19.216 - role="hg-ext-mq">hg qrefresh</command>, we've been careful to 19.217 + role="hg-ext-mq">qnew</command> and <command 19.218 + role="hg-ext-mq">qrefresh</command>, we've been careful to 19.219 only use regular Mercurial commands. However, MQ provides 19.220 many commands that are easier to use when you are thinking 19.221 - about patches, as illustrated in figure <xref 19.222 - linkend="ex:mq:qseries"/>:</para> 19.223 + about patches, as illustrated below.</para> 19.224 + 19.225 +<!-- &interaction.mq.tutorial.qseries; --> 19.226 19.227 <itemizedlist> 19.228 <listitem><para>The <command 19.229 - role="hg-ext-mq">hg qseries</command> command lists every 19.230 + role="hg-ext-mq">qseries</command> command lists every 19.231 patch that MQ knows about in this repository, from oldest 19.232 to newest (most recently 19.233 - <emphasis>created</emphasis>).</para></listitem> 19.234 + <emphasis>created</emphasis>).</para> 19.235 + </listitem> 19.236 <listitem><para>The <command 19.237 - role="hg-ext-mq">hg qapplied</command> command lists every 19.238 + role="hg-ext-mq">qapplied</command> command lists every 19.239 patch that MQ has <emphasis>applied</emphasis> in this 19.240 repository, again from oldest to newest (most recently 19.241 - applied).</para></listitem></itemizedlist> 19.242 - 19.243 -<!-- &interaction.mq.tutorial.qseries; --> 19.244 + applied).</para> 19.245 + </listitem></itemizedlist> 19.246 19.247 </sect2> 19.248 <sect2> 19.249 @@ -386,52 +394,53 @@ 19.250 changeset in the repository, and the effects of the patch and 19.251 changeset are visible in the working directory. You can undo 19.252 the application of a patch using the <command 19.253 - role="hg-ext-mq">hg qpop</command> command. MQ still 19.254 + role="hg-ext-mq">qpop</command> command. MQ still 19.255 <emphasis>knows about</emphasis>, or manages, a popped patch, 19.256 but the patch no longer has a corresponding changeset in the 19.257 repository, and the working directory does not contain the 19.258 changes made by the patch. Figure <xref 19.259 - linkend="fig:mq:stack"/> illustrates the difference between 19.260 - applied and tracked patches.</para> 19.261 + linkend="fig:mq:stack"/> illustrates 19.262 + the difference between applied and tracked patches.</para> 19.263 19.264 <informalfigure id="fig:mq:stack"> 19.265 - <mediaobject> 19.266 - <imageobject><imagedata fileref="mq-stack"/></imageobject> 19.267 - <textobject><phrase>XXX add text</phrase></textobject> 19.268 - <caption><para>Applied and unapplied patches in the MQ patch 19.269 - stack</para></caption> 19.270 - </mediaobject> 19.271 + <mediaobject><imageobject><imagedata 19.272 + fileref="mq-stack"/></imageobject><textobject><phrase>XXX 19.273 + add text</phrase></textobject><caption><para>Applied and 19.274 + unapplied patches in the MQ patch 19.275 + stack</para></caption></mediaobject> 19.276 </informalfigure> 19.277 19.278 <para>You can reapply an unapplied, or popped, patch using the 19.279 - <command role="hg-ext-mq">hg qpush</command> command. This 19.280 + <command role="hg-ext-mq">qpush</command> command. This 19.281 creates a new changeset to correspond to the patch, and the 19.282 patch's changes once again become present in the working 19.283 - directory. See figure <xref linkend="ex:mq:qpop"/> for 19.284 - examples of <command role="hg-ext-mq">hg qpop</command> and 19.285 - <command role="hg-ext-mq">hg qpush</command> in action. Notice 19.286 - that once we have popped a patch or two patches, the output of 19.287 - <command role="hg-ext-mq">hg qseries</command> remains the same, 19.288 - while that of <command role="hg-ext-mq">hg qapplied</command> has 19.289 - changed.</para> 19.290 - 19.291 + directory. See below for examples of <command 19.292 + role="hg-ext-mq">qpop</command> and <command 19.293 + role="hg-ext-mq">qpush</command> in action.</para> 19.294 <!-- &interaction.mq.tutorial.qpop; --> 19.295 19.296 + <para>Notice that once we have popped a patch or two patches, 19.297 + the output of <command role="hg-ext-mq">qseries</command> 19.298 + remains the same, while that of <command 19.299 + role="hg-ext-mq">qapplied</command> has changed.</para> 19.300 + 19.301 + 19.302 </sect2> 19.303 <sect2> 19.304 <title>Pushing and popping many patches</title> 19.305 19.306 - <para>While <command role="hg-ext-mq">hg qpush</command> and 19.307 - <command role="hg-ext-mq">hg qpop</command> each operate on a 19.308 + <para>While <command role="hg-ext-mq">qpush</command> and 19.309 + <command role="hg-ext-mq">qpop</command> each operate on a 19.310 single patch at a time by default, you can push and pop many 19.311 patches in one go. The <option 19.312 - role="hg-ext-mq-cmd-qpush-opt">-a</option> option to 19.313 - <command role="hg-ext-mq">hg qpush</command> causes it to push 19.314 + role="hg-ext-mq-cmd-qpush-opt">hg -a</option> option to 19.315 + <command role="hg-ext-mq">qpush</command> causes it to push 19.316 all unapplied patches, while the <option 19.317 role="hg-ext-mq-cmd-qpop-opt">-a</option> option to <command 19.318 - role="hg-ext-mq">hg qpop</command> causes it to pop all applied 19.319 + role="hg-ext-mq">qpop</command> causes it to pop all applied 19.320 patches. (For some more ways to push and pop many patches, 19.321 - see section <xref linkend="sec:mq:perf"/> below.)</para> 19.322 + see section <xref linkend="sec:mq:perf"/> 19.323 + below.)</para> 19.324 19.325 <!-- &interaction.mq.tutorial.qpush-a; --> 19.326 19.327 @@ -442,9 +451,9 @@ 19.328 <para>Several MQ commands check the working directory before 19.329 they do anything, and fail if they find any modifications. 19.330 They do this to ensure that you won't lose any changes that 19.331 - you have made, but not yet incorporated into a patch. Figure 19.332 - <xref linkend="ex:mq:add"/> illustrates this; the <command 19.333 - role="hg-ext-mq">hg qnew</command> command will not create a 19.334 + you have made, but not yet incorporated into a patch. The 19.335 + example below illustrates this; the <command 19.336 + role="hg-ext-mq">qnew</command> command will not create a 19.337 new patch if there are outstanding changes, caused in this 19.338 case by the <command role="hg-cmd">hg add</command> of 19.339 <filename>file3</filename>.</para> 19.340 @@ -456,19 +465,19 @@ 19.341 named <option>-f</option>. The exact meaning of 19.342 <option>-f</option> depends on the command. For example, 19.343 <command role="hg-cmd">hg qnew <option 19.344 - role="hg-ext-mq-cmd-qnew-opt">-f</option></command> will 19.345 - incorporate any outstanding changes into the new patch it 19.346 + role="hg-ext-mq-cmd-qnew-opt">hg -f</option></command> 19.347 + will incorporate any outstanding changes into the new patch it 19.348 creates, but <command role="hg-cmd">hg qpop <option 19.349 - role="hg-ext-mq-cmd-qpop-opt">-f</option></command> will 19.350 - revert modifications to any files affected by the patch that 19.351 - it is popping. Be sure to read the documentation for a 19.352 + role="hg-ext-mq-cmd-qpop-opt">hg -f</option></command> 19.353 + will revert modifications to any files affected by the patch 19.354 + that it is popping. Be sure to read the documentation for a 19.355 command's <option>-f</option> option before you use it!</para> 19.356 19.357 </sect2> 19.358 <sect2> 19.359 <title>Working on several patches at once</title> 19.360 19.361 - <para>The <command role="hg-ext-mq">hg qrefresh</command> command 19.362 + <para>The <command role="hg-ext-mq">qrefresh</command> command 19.363 always refreshes the <emphasis>topmost</emphasis> applied 19.364 patch. This means that you can suspend work on one patch (by 19.365 refreshing it), pop or push to make a different patch the top, 19.366 @@ -478,20 +487,19 @@ 19.367 <para>Here's an example that illustrates how you can use this 19.368 ability. Let's say you're developing a new feature as two 19.369 patches. The first is a change to the core of your software, 19.370 - and the second&emdash;layered on top of the first&emdash;changes the 19.371 - user interface to use the code you just added to the core. If 19.372 - you notice a bug in the core while you're working on the UI 19.373 - patch, it's easy to fix the core. Simply <command 19.374 - role="hg-ext-mq">hg qrefresh</command> the UI patch to save 19.375 - your in-progress changes, and <command 19.376 - role="hg-ext-mq">hg qpop</command> down to the core patch. Fix 19.377 - the core bug, <command role="hg-ext-mq">hg qrefresh</command> the 19.378 - core patch, and <command role="hg-ext-mq">hg qpush</command> back 19.379 + and the second&emdash;layered on top of the 19.380 + first&emdash;changes the user interface to use the code you 19.381 + just added to the core. If you notice a bug in the core while 19.382 + you're working on the UI patch, it's easy to fix the core. 19.383 + Simply <command role="hg-ext-mq">qrefresh</command> the UI 19.384 + patch to save your in-progress changes, and <command 19.385 + role="hg-ext-mq">qpop</command> down to the core patch. Fix 19.386 + the core bug, <command role="hg-ext-mq">qrefresh</command> the 19.387 + core patch, and <command role="hg-ext-mq">qpush</command> back 19.388 to the UI patch to continue where you left off.</para> 19.389 19.390 </sect2> 19.391 </sect1> 19.392 - 19.393 <sect1 id="sec:mq:adv-patch"> 19.394 <title>More about patches</title> 19.395 19.396 @@ -555,19 +563,20 @@ 19.397 <para>If you receive a patch from someone that you want to add 19.398 to your patch queue, and the patch needs a strip count other 19.399 than one, you cannot just <command 19.400 - role="hg-ext-mq">hg qimport</command> the patch, because 19.401 - <command role="hg-ext-mq">hg qimport</command> does not yet have 19.402 + role="hg-ext-mq">qimport</command> the patch, because 19.403 + <command role="hg-ext-mq">qimport</command> does not yet have 19.404 a <literal>-p</literal> option (see <ulink role="hg-bug" 19.405 url="http://www.selenic.com/mercurial/bts/issue311">issue 19.406 311</ulink>). Your best bet is to <command 19.407 - role="hg-ext-mq">hg qnew</command> a patch of your own, then 19.408 + role="hg-ext-mq">qnew</command> a patch of your own, then 19.409 use <command>patch -pN</command> to apply their patch, 19.410 followed by <command role="hg-cmd">hg addremove</command> to 19.411 pick up any files added or removed by the patch, followed by 19.412 - <command role="hg-ext-mq">hg qrefresh</command>. This complexity 19.413 - may become unnecessary; see <ulink role="hg-bug" 19.414 + <command role="hg-ext-mq">hg qrefresh</command>. This 19.415 + complexity may become unnecessary; see <ulink role="hg-bug" 19.416 url="http://www.selenic.com/mercurial/bts/issue311">issue 19.417 - 311</ulink> for details.</para> 19.418 + 311</ulink> for details. 19.419 + </para> 19.420 </sect2> 19.421 <sect2> 19.422 <title>Strategies for applying a patch</title> 19.423 @@ -619,42 +628,39 @@ 19.424 19.425 <para>There are a few useful things to know about how 19.426 <command>patch</command> works with files.</para> 19.427 - 19.428 <itemizedlist> 19.429 <listitem><para>This should already be obvious, but 19.430 <command>patch</command> cannot handle binary 19.431 - files.</para></listitem> 19.432 - 19.433 + files.</para> 19.434 + </listitem> 19.435 <listitem><para>Neither does it care about the executable bit; 19.436 it creates new files as readable, but not 19.437 - executable.</para></listitem> 19.438 - 19.439 + executable.</para> 19.440 + </listitem> 19.441 <listitem><para><command>patch</command> treats the removal of 19.442 a file as a diff between the file to be removed and the 19.443 empty file. So your idea of <quote>I deleted this 19.444 file</quote> looks like <quote>every line of this file 19.445 - was deleted</quote> in a patch.</para></listitem> 19.446 - 19.447 + was deleted</quote> in a patch.</para> 19.448 + </listitem> 19.449 <listitem><para>It treats the addition of a file as a diff 19.450 between the empty file and the file to be added. So in a 19.451 patch, your idea of <quote>I added this file</quote> looks 19.452 like <quote>every line of this file was 19.453 - added</quote>.</para></listitem> 19.454 - 19.455 + added</quote>.</para> 19.456 + </listitem> 19.457 <listitem><para>It treats a renamed file as the removal of the 19.458 old name, and the addition of the new name. This means 19.459 that renamed files have a big footprint in patches. (Note 19.460 also that Mercurial does not currently try to infer when 19.461 - files have been renamed or copied in a 19.462 - patch.)</para></listitem> 19.463 - 19.464 + files have been renamed or copied in a patch.)</para> 19.465 + </listitem> 19.466 <listitem><para><command>patch</command> cannot represent 19.467 empty files, so you cannot use a patch to represent the 19.468 notion <quote>I added this empty file to the 19.469 - tree</quote>.</para></listitem> 19.470 - </itemizedlist> 19.471 - </sect2> 19.472 - 19.473 + tree</quote>.</para> 19.474 + </listitem></itemizedlist> 19.475 + </sect2> 19.476 <sect2> 19.477 <title>Beware the fuzz</title> 19.478 19.479 @@ -664,7 +670,7 @@ 19.480 file. The most common cases typically involve applying a 19.481 patch twice, or at an incorrect location in the file. If 19.482 <command>patch</command> or <command 19.483 - role="hg-ext-mq">hg qpush</command> ever mentions an offset or 19.484 + role="hg-ext-mq">qpush</command> ever mentions an offset or 19.485 fuzz factor, you should make sure that the modified files are 19.486 correct afterwards.</para> 19.487 19.488 @@ -683,7 +689,7 @@ 19.489 <sect2> 19.490 <title>Handling rejection</title> 19.491 19.492 - <para>If <command role="hg-ext-mq">hg qpush</command> fails to 19.493 + <para>If <command role="hg-ext-mq">qpush</command> fails to 19.494 apply a patch, it will print an error message and exit. If it 19.495 has left <filename role="special">.rej</filename> files 19.496 behind, it is usually best to fix up the rejected hunks before 19.497 @@ -692,7 +698,8 @@ 19.498 <para>If your patch <emphasis>used to</emphasis> apply cleanly, 19.499 and no longer does because you've changed the underlying code 19.500 that your patches are based on, Mercurial Queues can help; see 19.501 - section <xref linkend="sec:mq:merge"/> for details.</para> 19.502 + section <xref 19.503 + linkend="sec:mq:merge"/> for details.</para> 19.504 19.505 <para>Unfortunately, there aren't any great techniques for 19.506 dealing with rejected hunks. Most often, you'll need to view 19.507 @@ -715,19 +722,18 @@ 19.508 19.509 <itemizedlist> 19.510 <listitem><para>The context in the middle of a hunk has 19.511 - changed.</para></listitem> 19.512 - 19.513 + changed.</para> 19.514 + </listitem> 19.515 <listitem><para>A hunk is missing some context at the 19.516 - beginning or end.</para></listitem> 19.517 - 19.518 + beginning or end.</para> 19.519 + </listitem> 19.520 <listitem><para>A large hunk might apply better&emdash;either 19.521 - entirely or in part&emdash;if it was broken up into smaller 19.522 - hunks.</para></listitem> 19.523 - 19.524 + entirely or in part&emdash;if it was broken up into 19.525 + smaller hunks.</para> 19.526 + </listitem> 19.527 <listitem><para>A hunk removes lines with slightly different 19.528 - content than those currently present in the 19.529 - file.</para></listitem> 19.530 - </itemizedlist> 19.531 + content than those currently present in the file.</para> 19.532 + </listitem></itemizedlist> 19.533 19.534 <para>If you use <command>wiggle</command> or 19.535 <command>mpatch</command>, you should be doubly careful to 19.536 @@ -754,12 +760,12 @@ 19.537 19.538 <para>On my old, slow laptop, I was able to <command 19.539 role="hg-cmd">hg qpush <option 19.540 - role="hg-ext-mq-cmd-qpush-opt">-a</option></command> all 19.541 + role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> all 19.542 1,738 patches in 3.5 minutes, and <command role="hg-cmd">hg qpop 19.543 - <option role="hg-ext-mq-cmd-qpop-opt">-a</option></command> 19.544 + <option role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> 19.545 them all in 30 seconds. (On a newer laptop, the time to push 19.546 all patches dropped to two minutes.) I could <command 19.547 - role="hg-ext-mq">hg qrefresh</command> one of the biggest patches 19.548 + role="hg-ext-mq">qrefresh</command> one of the biggest patches 19.549 (which made 22,779 lines of changes to 287 files) in 6.6 19.550 seconds.</para> 19.551 19.552 @@ -769,23 +775,23 @@ 19.553 19.554 <para>First of all, try to <quote>batch</quote> operations 19.555 together. Every time you run <command 19.556 - role="hg-ext-mq">hg qpush</command> or <command 19.557 - role="hg-ext-mq">hg qpop</command>, these commands scan the 19.558 + role="hg-ext-mq">qpush</command> or <command 19.559 + role="hg-ext-mq">qpop</command>, these commands scan the 19.560 working directory once to make sure you haven't made some 19.561 changes and then forgotten to run <command 19.562 - role="hg-ext-mq">hg qrefresh</command>. On a small tree, the 19.563 + role="hg-ext-mq">qrefresh</command>. On a small tree, the 19.564 time that this scan takes is unnoticeable. However, on a 19.565 medium-sized tree (containing tens of thousands of files), it 19.566 can take a second or more.</para> 19.567 19.568 - <para>The <command role="hg-ext-mq">hg qpush</command> and <command 19.569 - role="hg-ext-mq">hg qpop</command> commands allow you to push and 19.570 + <para>The <command role="hg-ext-mq">qpush</command> and <command 19.571 + role="hg-ext-mq">qpop</command> commands allow you to push and 19.572 pop multiple patches at a time. You can identify the 19.573 <quote>destination patch</quote> that you want to end up at. 19.574 - When you <command role="hg-ext-mq">hg qpush</command> with a 19.575 + When you <command role="hg-ext-mq">qpush</command> with a 19.576 destination specified, it will push patches until that patch is 19.577 at the top of the applied stack. When you <command 19.578 - role="hg-ext-mq">hg qpop</command> to a destination, MQ will pop 19.579 + role="hg-ext-mq">qpop</command> to a destination, MQ will pop 19.580 patches until the destination patch is at the top.</para> 19.581 19.582 <para>You can identify a destination patch using either the name 19.583 @@ -794,7 +800,6 @@ 19.584 is zero, the second is one, and so on.</para> 19.585 19.586 </sect1> 19.587 - 19.588 <sect1 id="sec:mq:merge"> 19.589 <title>Updating your patches when the underlying code 19.590 changes</title> 19.591 @@ -809,15 +814,14 @@ 19.592 series.</para> 19.593 19.594 <para>The simplest way to do this is to <command role="hg-cmd">hg 19.595 - qpop <option 19.596 - role="hg-ext-mq-cmd-qpop-opt">-a</option></command> your 19.597 - patches, then <command role="hg-cmd">hg pull</command> changes 19.598 - into the underlying repository, and finally <command 19.599 - role="hg-cmd">hg qpush <option 19.600 - role="hg-ext-mq-cmd-qpop-opt">-a</option></command> your 19.601 + qpop <option role="hg-ext-mq-cmd-qpop-opt">hg 19.602 + -a</option></command> your patches, then <command 19.603 + role="hg-cmd">hg pull</command> changes into the underlying 19.604 + repository, and finally <command role="hg-cmd">hg qpush <option 19.605 + role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> your 19.606 patches again. MQ will stop pushing any time it runs across a 19.607 patch that fails to apply during conflicts, allowing you to fix 19.608 - your conflicts, <command role="hg-ext-mq">hg qrefresh</command> the 19.609 + your conflicts, <command role="hg-ext-mq">qrefresh</command> the 19.610 affected patch, and continue pushing until you have fixed your 19.611 entire stack.</para> 19.612 19.613 @@ -828,8 +832,8 @@ 19.614 fixing up rejected hunks by hand quickly becomes 19.615 tiresome.</para> 19.616 19.617 - <para>It's possible to partially automate the rebasing process. If 19.618 - your patches apply cleanly against some revision of the 19.619 + <para>It's possible to partially automate the rebasing process. 19.620 + If your patches apply cleanly against some revision of the 19.621 underlying repo, MQ can use this information to help you to 19.622 resolve conflicts between your patches and a different 19.623 revision.</para> 19.624 @@ -838,12 +842,12 @@ 19.625 <orderedlist> 19.626 <listitem><para>To begin, <command role="hg-cmd">hg qpush 19.627 -a</command> all of your patches on top of the revision 19.628 - where you know that they apply cleanly.</para></listitem> 19.629 - 19.630 + where you know that they apply cleanly.</para> 19.631 + </listitem> 19.632 <listitem><para>Save a backup copy of your patch directory using 19.633 <command role="hg-cmd">hg qsave <option 19.634 - role="hg-ext-mq-cmd-qsave-opt">-e</option> <option 19.635 - role="hg-ext-mq-cmd-qsave-opt">-c</option></command>. 19.636 + role="hg-ext-mq-cmd-qsave-opt">hg -e</option> <option 19.637 + role="hg-ext-mq-cmd-qsave-opt">hg -c</option></command>. 19.638 This prints the name of the directory that it has saved the 19.639 patches in. It will save the patches to a directory called 19.640 <filename role="special" 19.641 @@ -852,36 +856,34 @@ 19.642 <quote>save changeset</quote> on top of your applied 19.643 patches; this is for internal book-keeping, and records the 19.644 states of the <filename role="special">series</filename> and 19.645 - <filename role="special">status</filename> 19.646 - files.</para></listitem> 19.647 - 19.648 - <listitem> 19.649 - <para>Use <command role="hg-cmd">hg pull</command> to bring 19.650 - new changes into the underlying repository. (Don't run 19.651 - <command role="hg-cmd">hg pull -u</command>; see below for 19.652 - why.)</para></listitem> 19.653 - 19.654 + <filename role="special">status</filename> files.</para> 19.655 + </listitem> 19.656 + <listitem><para>Use <command role="hg-cmd">hg pull</command> to 19.657 + bring new changes into the underlying repository. (Don't 19.658 + run <command role="hg-cmd">hg pull -u</command>; see below 19.659 + for why.)</para> 19.660 + </listitem> 19.661 <listitem><para>Update to the new tip revision, using <command 19.662 role="hg-cmd">hg update <option 19.663 role="hg-opt-update">-C</option></command> to override 19.664 - the patches you have pushed.</para></listitem> 19.665 - 19.666 + the patches you have pushed.</para> 19.667 + </listitem> 19.668 <listitem><para>Merge all patches using 19.669 - \hgcmdargs{qpush}{<option 19.670 - role="hg-ext-mq-cmd-qpush-opt">-m</option> <option 19.671 - role="hg-ext-mq-cmd-qpush-opt">-a</option>}. The <option 19.672 - role="hg-ext-mq-cmd-qpush-opt">-m</option> option to 19.673 - <command role="hg-ext-mq">hg qpush</command> tells MQ to 19.674 + \hgcmdargs{qpush}{<option role="hg-ext-mq-cmd-qpush-opt">hg 19.675 + -m</option> <option role="hg-ext-mq-cmd-qpush-opt">hg 19.676 + -a</option>}. The <option 19.677 + role="hg-ext-mq-cmd-qpush-opt">hg -m</option> option to 19.678 + <command role="hg-ext-mq">qpush</command> tells MQ to 19.679 perform a three-way merge if the patch fails to 19.680 - apply.</para></listitem> 19.681 - </orderedlist> 19.682 + apply.</para> 19.683 + </listitem></orderedlist> 19.684 19.685 <para>During the <command role="hg-cmd">hg qpush <option 19.686 - role="hg-ext-mq-cmd-qpush-opt">-m</option></command>, each 19.687 - patch in the <filename role="special">series</filename> file is 19.688 - applied normally. If a patch applies with fuzz or rejects, MQ 19.689 - looks at the queue you <command 19.690 - role="hg-ext-mq">hg qsave</command>d, and performs a three-way 19.691 + role="hg-ext-mq-cmd-qpush-opt">hg -m</option></command>, 19.692 + each patch in the <filename role="special">series</filename> 19.693 + file is applied normally. If a patch applies with fuzz or 19.694 + rejects, MQ looks at the queue you <command 19.695 + role="hg-ext-mq">qsave</command>d, and performs a three-way 19.696 merge with the corresponding changeset. This merge uses 19.697 Mercurial's normal merge machinery, so it may pop up a GUI merge 19.698 tool to help you to resolve problems.</para> 19.699 @@ -893,9 +895,7 @@ 19.700 extra head from the old patch queue, and a copy of the old patch 19.701 queue will be in <filename role="special" 19.702 class="directory">.hg/patches.N</filename>. You can remove the 19.703 - extra head using <command role="hg-cmd">hg qpop <option 19.704 - role="hg-ext-mq-cmd-qpop-opt">-a</option> <option 19.705 - role="hg-ext-mq-cmd-qpop-opt">-n</option> 19.706 + extra head using <command role="hg-cmd">hg qpop -a -n 19.707 patches.N</command> or <command role="hg-cmd">hg 19.708 strip</command>. You can delete <filename role="special" 19.709 class="directory">.hg/patches.N</filename> once you are sure 19.710 @@ -908,7 +908,7 @@ 19.711 <para>MQ commands that work with patches let you refer to a patch 19.712 either by using its name or by a number. By name is obvious 19.713 enough; pass the name <filename>foo.patch</filename> to <command 19.714 - role="hg-ext-mq">hg qpush</command>, for example, and it will 19.715 + role="hg-ext-mq">qpush</command>, for example, and it will 19.716 push patches until <filename>foo.patch</filename> is 19.717 applied.</para> 19.718 19.719 @@ -920,7 +920,7 @@ 19.720 19.721 <para>Referring to a patch by index isn't much different. The 19.722 first patch printed in the output of <command 19.723 - role="hg-ext-mq">hg qseries</command> is patch zero (yes, it's 19.724 + role="hg-ext-mq">qseries</command> is patch zero (yes, it's 19.725 one of those start-at-zero counting systems); the second is 19.726 patch one; and so on.</para> 19.727 19.728 @@ -941,19 +941,18 @@ 19.729 <itemizedlist> 19.730 <listitem><para>Want to patchbomb a mailing list with your 19.731 latest series of changes?</para> 19.732 - <programlisting> 19.733 - hg email qbase:qtip 19.734 - </programlisting></listitem> 19.735 - <listitem><para> (Don't know what <quote>patchbombing</quote> 19.736 - is? See section <xref 19.737 - linkend="sec:hgext:patchbomb"/>.)</para></listitem> 19.738 - 19.739 + <programlisting>hg email qbase:qtip 19.740 + </programlisting> 19.741 + <para> (Don't know what <quote>patchbombing</quote> is? See 19.742 + section <xref linkend="sec:hgext:patchbomb"/>.)</para> 19.743 + </listitem> 19.744 <listitem><para>Need to see all of the patches since 19.745 <literal>foo.patch</literal> that have touched files in a 19.746 subdirectory of your tree?</para> 19.747 <programlisting> 19.748 hg log -r foo.patch:qtip <emphasis>subdir</emphasis> 19.749 - </programlisting></listitem> 19.750 + </programlisting> 19.751 + </listitem> 19.752 </itemizedlist> 19.753 19.754 <para>Because MQ makes the names of patches available to the rest 19.755 @@ -961,16 +960,16 @@ 19.756 don't need to type in the entire name of a patch when you want 19.757 to identify it by name.</para> 19.758 19.759 -<!-- &interaction.mq.id.output; --> 19.760 - 19.761 <para>Another nice consequence of representing patch names as tags 19.762 is that when you run the <command role="hg-cmd">hg log</command> 19.763 command, it will display a patch's name as a tag, simply as part 19.764 of its normal output. This makes it easy to visually 19.765 distinguish applied patches from underlying 19.766 - <quote>normal</quote> revisions. Figure <xref 19.767 - linkend="ex:mq:id"/> shows a few normal Mercurial commands in 19.768 - use with applied patches.</para> 19.769 + <quote>normal</quote> revisions. The following example shows a 19.770 + few normal Mercurial commands in use with applied 19.771 + patches.</para> 19.772 + 19.773 +<!-- &interaction.mq.id.output; --> 19.774 19.775 </sect1> 19.776 <sect1> 19.777 @@ -982,25 +981,24 @@ 19.778 19.779 <itemizedlist> 19.780 <listitem><para>Normally, when you <command 19.781 - role="hg-ext-mq">hg qpop</command> a patch and <command 19.782 - role="hg-ext-mq">hg qpush</command> it again, the changeset 19.783 + role="hg-ext-mq">qpop</command> a patch and <command 19.784 + role="hg-ext-mq">qpush</command> it again, the changeset 19.785 that represents the patch after the pop/push will have a 19.786 <emphasis>different identity</emphasis> than the changeset 19.787 that represented the hash beforehand. See section <xref 19.788 - linkend="sec:mqref:cmd:qpush"/> for information as to why 19.789 - this is.</para></listitem> 19.790 - 19.791 + linkend="sec:mqref:cmd:qpush"/> for 19.792 + information as to why this is.</para> 19.793 + </listitem> 19.794 <listitem><para>It's not a good idea to <command 19.795 role="hg-cmd">hg merge</command> changes from another 19.796 branch with a patch changeset, at least if you want to 19.797 maintain the <quote>patchiness</quote> of that changeset and 19.798 changesets below it on the patch stack. If you try to do 19.799 this, it will appear to succeed, but MQ will become 19.800 - confused.</para></listitem> 19.801 - </itemizedlist> 19.802 - 19.803 - </sect1> 19.804 - 19.805 + confused.</para> 19.806 + </listitem></itemizedlist> 19.807 + 19.808 + </sect1> 19.809 <sect1 id="sec:mq:repo"> 19.810 <title>Managing patches in a repository</title> 19.811 19.812 @@ -1014,7 +1012,7 @@ 19.813 contents of the patch directory as a Mercurial repository in its 19.814 own right. This can be a useful way to work. For example, you 19.815 can work on a patch for a while, <command 19.816 - role="hg-ext-mq">hg qrefresh</command> it, then <command 19.817 + role="hg-ext-mq">qrefresh</command> it, then <command 19.818 role="hg-cmd">hg commit</command> the current state of the 19.819 patch. This lets you <quote>roll back</quote> to that version 19.820 of the patch later on.</para> 19.821 @@ -1040,25 +1038,24 @@ 19.822 <para>MQ helps you to work with the <filename role="special" 19.823 class="directory">.hg/patches</filename> directory as a 19.824 repository; when you prepare a repository for working with 19.825 - patches using <command role="hg-ext-mq">hg qinit</command>, you 19.826 - can pass the <option 19.827 - role="hg-ext-mq-cmd-qinit-opt">-c</option> option to create 19.828 - the <filename role="special" 19.829 + patches using <command role="hg-ext-mq">qinit</command>, you 19.830 + can pass the <option role="hg-ext-mq-cmd-qinit-opt">hg 19.831 + -c</option> option to create the <filename role="special" 19.832 class="directory">.hg/patches</filename> directory as a 19.833 Mercurial repository.</para> 19.834 19.835 <note> 19.836 <para> If you forget to use the <option 19.837 - role="hg-ext-mq-cmd-qinit-opt">-c</option> option, you can 19.838 - simply go into the <filename role="special" 19.839 + role="hg-ext-mq-cmd-qinit-opt">hg -c</option> option, you 19.840 + can simply go into the <filename role="special" 19.841 class="directory">.hg/patches</filename> directory at any 19.842 - time and run <command role="hg-cmd">hg init</command>. Don't 19.843 - forget to add an entry for the <filename 19.844 + time and run <command role="hg-cmd">hg init</command>. 19.845 + Don't forget to add an entry for the <filename 19.846 role="special">status</filename> file to the <filename 19.847 role="special">.hgignore</filename> file, though</para> 19.848 19.849 <para> (<command role="hg-cmd">hg qinit <option 19.850 - role="hg-ext-mq-cmd-qinit-opt">-c</option></command> 19.851 + role="hg-ext-mq-cmd-qinit-opt">hg -c</option></command> 19.852 does this for you automatically); you 19.853 <emphasis>really</emphasis> don't want to manage the 19.854 <filename role="special">status</filename> file.</para> 19.855 @@ -1070,7 +1067,7 @@ 19.856 add</command> every patch that you create and import.</para> 19.857 19.858 <para>MQ provides a shortcut command, <command 19.859 - role="hg-ext-mq">hg qcommit</command>, that runs <command 19.860 + role="hg-ext-mq">qcommit</command>, that runs <command 19.861 role="hg-cmd">hg commit</command> in the <filename 19.862 role="special" class="directory">.hg/patches</filename> 19.863 directory. This saves some bothersome typing.</para> 19.864 @@ -1079,12 +1076,11 @@ 19.865 you can define the alias <command>mq</command> on Unix 19.866 systems. For example, on Linux systems using the 19.867 <command>bash</command> shell, you can include the following 19.868 - snippet in your <filename role="home"> 19.869 - /.bashrc</filename>.</para> 19.870 - 19.871 - <programlisting> 19.872 - alias mq=`hg -R $(hg root)/.hg/patches' 19.873 - </programlisting> 19.874 + snippet in your <filename 19.875 + role="home">~/.bashrc</filename>.</para> 19.876 + 19.877 + <programlisting>alias mq=`hg -R $(hg 19.878 + root)/.hg/patches'</programlisting> 19.879 19.880 <para>You can then issue commands of the form <command>mq 19.881 pull</command> from the main repository.</para> 19.882 @@ -1102,9 +1098,9 @@ 19.883 update</command> changes to patches or the <filename 19.884 role="special">series</filename> file, you will have to 19.885 <command role="hg-cmd">hg qpop <option 19.886 - role="hg-ext-mq-cmd-qpop-opt">-a</option></command> and 19.887 + role="hg-ext-mq-cmd-qpop-opt">hg -a</option></command> and 19.888 then <command role="hg-cmd">hg qpush <option 19.889 - role="hg-ext-mq-cmd-qpush-opt">-a</option></command> in 19.890 + role="hg-ext-mq-cmd-qpush-opt">hg -a</option></command> in 19.891 the underlying repository to see those changes show up there. 19.892 If you forget to do this, you can confuse MQ's idea of which 19.893 patches are applied.</para> 19.894 @@ -1121,9 +1117,9 @@ 19.895 <para>The <command>diffstat</command> command 19.896 <citation>web:diffstat</citation> generates a histogram of the 19.897 modifications made to each file in a patch. It provides a good 19.898 - way to <quote>get a sense of</quote> a patch&emdash;which files it 19.899 - affects, and how much change it introduces to each file and as a 19.900 - whole. (I find that it's a good idea to use 19.901 + way to <quote>get a sense of</quote> a patch&emdash;which files 19.902 + it affects, and how much change it introduces to each file and 19.903 + as a whole. (I find that it's a good idea to use 19.904 <command>diffstat</command>'s <option 19.905 role="cmd-opt-diffstat">-p</option> option as a matter of 19.906 course, as otherwise it will try to do clever things with 19.907 @@ -1162,30 +1158,30 @@ 19.908 the patch is. Long names shouldn't be a problem; you won't be 19.909 typing the names often, but you <emphasis>will</emphasis> be 19.910 running commands like <command 19.911 - role="hg-ext-mq">hg qapplied</command> and <command 19.912 - role="hg-ext-mq">hg qtop</command> over and over. Good naming 19.913 + role="hg-ext-mq">qapplied</command> and <command 19.914 + role="hg-ext-mq">qtop</command> over and over. Good naming 19.915 becomes especially important when you have a number of patches 19.916 to work with, or if you are juggling a number of different tasks 19.917 and your patches only get a fraction of your attention.</para> 19.918 19.919 <para>Be aware of what patch you're working on. Use the <command 19.920 - role="hg-ext-mq">hg qtop</command> command and skim over the text 19.921 + role="hg-ext-mq">qtop</command> command and skim over the text 19.922 of your patches frequently&emdash;for example, using <command 19.923 role="hg-cmd">hg tip <option 19.924 - role="hg-opt-tip">-p</option></command>)&emdash;to be sure of 19.925 - where you stand. I have several times worked on and <command 19.926 - role="hg-ext-mq">hg qrefresh</command>ed a patch other than the 19.927 + role="hg-opt-tip">-p</option></command>)&emdash;to be sure 19.928 + of where you stand. I have several times worked on and <command 19.929 + role="hg-ext-mq">qrefresh</command>ed a patch other than the 19.930 one I intended, and it's often tricky to migrate changes into 19.931 the right patch after making them in the wrong one.</para> 19.932 19.933 <para>For this reason, it is very much worth investing a little 19.934 time to learn how to use some of the third-party tools I 19.935 described in section <xref linkend="sec:mq:tools"/>, 19.936 - particularly <command>diffstat</command> and 19.937 - <command>filterdiff</command>. The former will give you a quick 19.938 - idea of what changes your patch is making, while the latter 19.939 - makes it easy to splice hunks selectively out of one patch and 19.940 - into another.</para> 19.941 + particularly 19.942 + <command>diffstat</command> and <command>filterdiff</command>. 19.943 + The former will give you a quick idea of what changes your patch 19.944 + is making, while the latter makes it easy to splice hunks 19.945 + selectively out of one patch and into another.</para> 19.946 19.947 </sect1> 19.948 <sect1> 19.949 @@ -1225,7 +1221,7 @@ 19.950 <title>Combining entire patches</title> 19.951 19.952 <para>MQ provides a command, <command 19.953 - role="hg-ext-mq">hg qfold</command> that lets you combine 19.954 + role="hg-ext-mq">qfold</command> that lets you combine 19.955 entire patches. This <quote>folds</quote> the patches you 19.956 name, in the order you name them, into the topmost applied 19.957 patch, and concatenates their descriptions onto the end of its 19.958 @@ -1234,7 +1230,7 @@ 19.959 19.960 <para>The order in which you fold patches matters. If your 19.961 topmost applied patch is <literal>foo</literal>, and you 19.962 - <command role="hg-ext-mq">hg qfold</command> 19.963 + <command role="hg-ext-mq">qfold</command> 19.964 <literal>bar</literal> and <literal>quux</literal> into it, 19.965 you will end up with a patch that has the same effect as if 19.966 you applied first <literal>foo</literal>, then 19.967 @@ -1257,9 +1253,9 @@ 19.968 output onto the end of the patch you want to merge into. You 19.969 usually won't need to modify the patch you've merged the 19.970 changes from. Instead, MQ will report some rejected hunks 19.971 - when you <command role="hg-ext-mq">hg qpush</command> it (from 19.972 + when you <command role="hg-ext-mq">qpush</command> it (from 19.973 the hunks you moved into the other patch), and you can simply 19.974 - <command role="hg-ext-mq">hg qrefresh</command> the patch to drop 19.975 + <command role="hg-ext-mq">qrefresh</command> the patch to drop 19.976 the duplicate hunks.</para> 19.977 19.978 <para>If you have a patch that has multiple hunks modifying a 19.979 @@ -1273,16 +1269,14 @@ 19.980 <itemizedlist> 19.981 <listitem><para>(in the first column) a <emphasis>file 19.982 number</emphasis> to identify each file modified in the 19.983 - patch;</para></listitem> 19.984 - 19.985 + patch;</para> 19.986 + </listitem> 19.987 <listitem><para>(on the next line, indented) the line number 19.988 - within a modified file where a hunk starts; 19.989 - and</para></listitem> 19.990 - 19.991 + within a modified file where a hunk starts; and</para> 19.992 + </listitem> 19.993 <listitem><para>(on the same line) a <emphasis>hunk 19.994 - number</emphasis> to identify that 19.995 - hunk.</para></listitem> 19.996 - </itemizedlist> 19.997 + number</emphasis> to identify that hunk.</para> 19.998 + </listitem></itemizedlist> 19.999 19.1000 <para>You'll have to use some visual inspection, and reading of 19.1001 the patch, to identify the file and hunk numbers you'll want,
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/en/ch13-mq-collab.xml Wed Feb 18 00:22:09 2009 -0800 20.3 @@ -0,0 +1,496 @@ 20.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 20.5 + 20.6 +<chapter id="chap:mq-collab"> 20.7 + <title>Advanced uses of Mercurial Queues</title> 20.8 + 20.9 + <para>While it's easy to pick up straightforward uses of Mercurial 20.10 + Queues, use of a little discipline and some of MQ's less 20.11 + frequently used capabilities makes it possible to work in 20.12 + complicated development environments.</para> 20.13 + 20.14 + <para>In this chapter, I will use as an example a technique I have 20.15 + used to manage the development of an Infiniband device driver for 20.16 + the Linux kernel. The driver in question is large (at least as 20.17 + drivers go), with 25,000 lines of code spread across 35 source 20.18 + files. It is maintained by a small team of developers.</para> 20.19 + 20.20 + <para>While much of the material in this chapter is specific to 20.21 + Linux, the same principles apply to any code base for which you're 20.22 + not the primary owner, and upon which you need to do a lot of 20.23 + development.</para> 20.24 + 20.25 + <sect1> 20.26 + <title>The problem of many targets</title> 20.27 + 20.28 + <para>The Linux kernel changes rapidly, and has never been 20.29 + internally stable; developers frequently make drastic changes 20.30 + between releases. This means that a version of the driver that 20.31 + works well with a particular released version of the kernel will 20.32 + not even <emphasis>compile</emphasis> correctly against, 20.33 + typically, any other version.</para> 20.34 + 20.35 + <para>To maintain a driver, we have to keep a number of distinct 20.36 + versions of Linux in mind.</para> 20.37 + <itemizedlist> 20.38 + <listitem><para>One target is the main Linux kernel development 20.39 + tree. Maintenance of the code is in this case partly shared 20.40 + by other developers in the kernel community, who make 20.41 + <quote>drive-by</quote> modifications to the driver as they 20.42 + develop and refine kernel subsystems.</para> 20.43 + </listitem> 20.44 + <listitem><para>We also maintain a number of 20.45 + <quote>backports</quote> to older versions of the Linux 20.46 + kernel, to support the needs of customers who are running 20.47 + older Linux distributions that do not incorporate our 20.48 + drivers. (To <emphasis>backport</emphasis> a piece of code 20.49 + is to modify it to work in an older version of its target 20.50 + environment than the version it was developed for.)</para> 20.51 + </listitem> 20.52 + <listitem><para>Finally, we make software releases on a schedule 20.53 + that is necessarily not aligned with those used by Linux 20.54 + distributors and kernel developers, so that we can deliver 20.55 + new features to customers without forcing them to upgrade 20.56 + their entire kernels or distributions.</para> 20.57 + </listitem></itemizedlist> 20.58 + 20.59 + <sect2> 20.60 + <title>Tempting approaches that don't work well</title> 20.61 + 20.62 + <para>There are two <quote>standard</quote> ways to maintain a 20.63 + piece of software that has to target many different 20.64 + environments.</para> 20.65 + 20.66 + <para>The first is to maintain a number of branches, each 20.67 + intended for a single target. The trouble with this approach 20.68 + is that you must maintain iron discipline in the flow of 20.69 + changes between repositories. A new feature or bug fix must 20.70 + start life in a <quote>pristine</quote> repository, then 20.71 + percolate out to every backport repository. Backport changes 20.72 + are more limited in the branches they should propagate to; a 20.73 + backport change that is applied to a branch where it doesn't 20.74 + belong will probably stop the driver from compiling.</para> 20.75 + 20.76 + <para>The second is to maintain a single source tree filled with 20.77 + conditional statements that turn chunks of code on or off 20.78 + depending on the intended target. Because these 20.79 + <quote>ifdefs</quote> are not allowed in the Linux kernel 20.80 + tree, a manual or automatic process must be followed to strip 20.81 + them out and yield a clean tree. A code base maintained in 20.82 + this fashion rapidly becomes a rat's nest of conditional 20.83 + blocks that are difficult to understand and maintain.</para> 20.84 + 20.85 + <para>Neither of these approaches is well suited to a situation 20.86 + where you don't <quote>own</quote> the canonical copy of a 20.87 + source tree. In the case of a Linux driver that is 20.88 + distributed with the standard kernel, Linus's tree contains 20.89 + the copy of the code that will be treated by the world as 20.90 + canonical. The upstream version of <quote>my</quote> driver 20.91 + can be modified by people I don't know, without me even 20.92 + finding out about it until after the changes show up in 20.93 + Linus's tree.</para> 20.94 + 20.95 + <para>These approaches have the added weakness of making it 20.96 + difficult to generate well-formed patches to submit 20.97 + upstream.</para> 20.98 + 20.99 + <para>In principle, Mercurial Queues seems like a good candidate 20.100 + to manage a development scenario such as the above. While 20.101 + this is indeed the case, MQ contains a few added features that 20.102 + make the job more pleasant.</para> 20.103 + 20.104 + </sect2> 20.105 + </sect1> 20.106 + <sect1> 20.107 + <title>Conditionally applying patches with guards</title> 20.108 + 20.109 + <para>Perhaps the best way to maintain sanity with so many targets 20.110 + is to be able to choose specific patches to apply for a given 20.111 + situation. MQ provides a feature called <quote>guards</quote> 20.112 + (which originates with quilt's <literal>guards</literal> 20.113 + command) that does just this. To start off, let's create a 20.114 + simple repository for experimenting in. <!-- 20.115 + &interaction.mq.guards.init; --> This gives us a tiny repository 20.116 + that contains two patches that don't have any dependencies on 20.117 + each other, because they touch different files.</para> 20.118 + 20.119 + <para>The idea behind conditional application is that you can 20.120 + <quote>tag</quote> a patch with a <emphasis>guard</emphasis>, 20.121 + which is simply a text string of your choosing, then tell MQ to 20.122 + select specific guards to use when applying patches. MQ will 20.123 + then either apply, or skip over, a guarded patch, depending on 20.124 + the guards that you have selected.</para> 20.125 + 20.126 + <para>A patch can have an arbitrary number of guards; each one is 20.127 + <emphasis>positive</emphasis> (<quote>apply this patch if this 20.128 + guard is selected</quote>) or <emphasis>negative</emphasis> 20.129 + (<quote>skip this patch if this guard is selected</quote>). A 20.130 + patch with no guards is always applied.</para> 20.131 + 20.132 + </sect1> 20.133 + <sect1> 20.134 + <title>Controlling the guards on a patch</title> 20.135 + 20.136 + <para>The <command role="hg-ext-mq">qguard</command> command lets 20.137 + you determine which guards should apply to a patch, or display 20.138 + the guards that are already in effect. Without any arguments, it 20.139 + displays the guards on the current topmost patch. <!-- 20.140 + &interaction.mq.guards.qguard; --> To set a positive guard on a 20.141 + patch, prefix the name of the guard with a 20.142 + <quote><literal>+</literal></quote>. <!-- 20.143 + &interaction.mq.guards.qguard.pos; --> To set a negative guard 20.144 + on a patch, prefix the name of the guard with a 20.145 + <quote><literal>-</literal></quote>. <!-- 20.146 + &interaction.mq.guards.qguard.neg; --></para> 20.147 + 20.148 + <note> 20.149 + <para> The <command role="hg-ext-mq">qguard</command> command 20.150 + <emphasis>sets</emphasis> the guards on a patch; it doesn't 20.151 + <emphasis>modify</emphasis> them. What this means is that if 20.152 + you run <command role="hg-cmd">hg qguard +a +b</command> on a 20.153 + patch, then <command role="hg-cmd">hg qguard +c</command> on 20.154 + the same patch, the <emphasis>only</emphasis> guard that will 20.155 + be set on it afterwards is <literal>+c</literal>.</para> 20.156 + </note> 20.157 + 20.158 + <para>Mercurial stores guards in the <filename 20.159 + role="special">series</filename> file; the form in which they 20.160 + are stored is easy both to understand and to edit by hand. (In 20.161 + other words, you don't have to use the <command 20.162 + role="hg-ext-mq">qguard</command> command if you don't want 20.163 + to; it's okay to simply edit the <filename 20.164 + role="special">series</filename> file.) <!-- 20.165 + &interaction.mq.guards.series; --></para> 20.166 + 20.167 + </sect1> 20.168 + <sect1> 20.169 + <title>Selecting the guards to use</title> 20.170 + 20.171 + <para>The <command role="hg-ext-mq">qselect</command> command 20.172 + determines which guards are active at a given time. The effect 20.173 + of this is to determine which patches MQ will apply the next 20.174 + time you run <command role="hg-ext-mq">qpush</command>. It has 20.175 + no other effect; in particular, it doesn't do anything to 20.176 + patches that are already applied.</para> 20.177 + 20.178 + <para>With no arguments, the <command 20.179 + role="hg-ext-mq">qselect</command> command lists the guards 20.180 + currently in effect, one per line of output. Each argument is 20.181 + treated as the name of a guard to apply. <!-- 20.182 + &interaction.mq.guards.qselect.foo; --> In case you're 20.183 + interested, the currently selected guards are stored in the 20.184 + <filename role="special">guards</filename> file. <!-- 20.185 + &interaction.mq.guards.qselect.cat; --> We can see the effect 20.186 + the selected guards have when we run <command 20.187 + role="hg-ext-mq">qpush</command>. <!-- 20.188 + &interaction.mq.guards.qselect.qpush; --></para> 20.189 + 20.190 + <para>A guard cannot start with a 20.191 + <quote><literal>+</literal></quote> or 20.192 + <quote><literal>-</literal></quote> character. The name of a 20.193 + guard must not contain white space, but most other characters 20.194 + are acceptable. If you try to use a guard with an invalid name, 20.195 + MQ will complain: <!-- &interaction.mq.guards.qselect.error; --> 20.196 + Changing the selected guards changes the patches that are 20.197 + applied. <!-- &interaction.mq.guards.qselect.quux; --> You can 20.198 + see in the example below that negative guards take precedence 20.199 + over positive guards. <!-- 20.200 + &interaction.mq.guards.qselect.foobar; --></para> 20.201 + 20.202 + </sect1> 20.203 + <sect1> 20.204 + <title>MQ's rules for applying patches</title> 20.205 + 20.206 + <para>The rules that MQ uses when deciding whether to apply a 20.207 + patch are as follows.</para> 20.208 + <itemizedlist> 20.209 + <listitem><para>A patch that has no guards is always 20.210 + applied.</para> 20.211 + </listitem> 20.212 + <listitem><para>If the patch has any negative guard that matches 20.213 + any currently selected guard, the patch is skipped.</para> 20.214 + </listitem> 20.215 + <listitem><para>If the patch has any positive guard that matches 20.216 + any currently selected guard, the patch is applied.</para> 20.217 + </listitem> 20.218 + <listitem><para>If the patch has positive or negative guards, 20.219 + but none matches any currently selected guard, the patch is 20.220 + skipped.</para> 20.221 + </listitem></itemizedlist> 20.222 + 20.223 + </sect1> 20.224 + <sect1> 20.225 + <title>Trimming the work environment</title> 20.226 + 20.227 + <para>In working on the device driver I mentioned earlier, I don't 20.228 + apply the patches to a normal Linux kernel tree. Instead, I use 20.229 + a repository that contains only a snapshot of the source files 20.230 + and headers that are relevant to Infiniband development. This 20.231 + repository is 1% the size of a kernel repository, so it's easier 20.232 + to work with.</para> 20.233 + 20.234 + <para>I then choose a <quote>base</quote> version on top of which 20.235 + the patches are applied. This is a snapshot of the Linux kernel 20.236 + tree as of a revision of my choosing. When I take the snapshot, 20.237 + I record the changeset ID from the kernel repository in the 20.238 + commit message. Since the snapshot preserves the 20.239 + <quote>shape</quote> and content of the relevant parts of the 20.240 + kernel tree, I can apply my patches on top of either my tiny 20.241 + repository or a normal kernel tree.</para> 20.242 + 20.243 + <para>Normally, the base tree atop which the patches apply should 20.244 + be a snapshot of a very recent upstream tree. This best 20.245 + facilitates the development of patches that can easily be 20.246 + submitted upstream with few or no modifications.</para> 20.247 + 20.248 + </sect1> 20.249 + <sect1> 20.250 + <title>Dividing up the <filename role="special">series</filename> 20.251 + file</title> 20.252 + 20.253 + <para>I categorise the patches in the <filename 20.254 + role="special">series</filename> file into a number of logical 20.255 + groups. Each section of like patches begins with a block of 20.256 + comments that describes the purpose of the patches that 20.257 + follow.</para> 20.258 + 20.259 + <para>The sequence of patch groups that I maintain follows. The 20.260 + ordering of these groups is important; I'll describe why after I 20.261 + introduce the groups.</para> 20.262 + <itemizedlist> 20.263 + <listitem><para>The <quote>accepted</quote> group. Patches that 20.264 + the development team has submitted to the maintainer of the 20.265 + Infiniband subsystem, and which he has accepted, but which 20.266 + are not present in the snapshot that the tiny repository is 20.267 + based on. These are <quote>read only</quote> patches, 20.268 + present only to transform the tree into a similar state as 20.269 + it is in the upstream maintainer's repository.</para> 20.270 + </listitem> 20.271 + <listitem><para>The <quote>rework</quote> group. Patches that I 20.272 + have submitted, but that the upstream maintainer has 20.273 + requested modifications to before he will accept 20.274 + them.</para> 20.275 + </listitem> 20.276 + <listitem><para>The <quote>pending</quote> group. Patches that 20.277 + I have not yet submitted to the upstream maintainer, but 20.278 + which we have finished working on. These will be <quote>read 20.279 + only</quote> for a while. If the upstream maintainer 20.280 + accepts them upon submission, I'll move them to the end of 20.281 + the <quote>accepted</quote> group. If he requests that I 20.282 + modify any, I'll move them to the beginning of the 20.283 + <quote>rework</quote> group.</para> 20.284 + </listitem> 20.285 + <listitem><para>The <quote>in progress</quote> group. Patches 20.286 + that are actively being developed, and should not be 20.287 + submitted anywhere yet.</para> 20.288 + </listitem> 20.289 + <listitem><para>The <quote>backport</quote> group. Patches that 20.290 + adapt the source tree to older versions of the kernel 20.291 + tree.</para> 20.292 + </listitem> 20.293 + <listitem><para>The <quote>do not ship</quote> group. Patches 20.294 + that for some reason should never be submitted upstream. 20.295 + For example, one such patch might change embedded driver 20.296 + identification strings to make it easier to distinguish, in 20.297 + the field, between an out-of-tree version of the driver and 20.298 + a version shipped by a distribution vendor.</para> 20.299 + </listitem></itemizedlist> 20.300 + 20.301 + <para>Now to return to the reasons for ordering groups of patches 20.302 + in this way. We would like the lowest patches in the stack to 20.303 + be as stable as possible, so that we will not need to rework 20.304 + higher patches due to changes in context. Putting patches that 20.305 + will never be changed first in the <filename 20.306 + role="special">series</filename> file serves this 20.307 + purpose.</para> 20.308 + 20.309 + <para>We would also like the patches that we know we'll need to 20.310 + modify to be applied on top of a source tree that resembles the 20.311 + upstream tree as closely as possible. This is why we keep 20.312 + accepted patches around for a while.</para> 20.313 + 20.314 + <para>The <quote>backport</quote> and <quote>do not ship</quote> 20.315 + patches float at the end of the <filename 20.316 + role="special">series</filename> file. The backport patches 20.317 + must be applied on top of all other patches, and the <quote>do 20.318 + not ship</quote> patches might as well stay out of harm's 20.319 + way.</para> 20.320 + 20.321 + </sect1> 20.322 + <sect1> 20.323 + <title>Maintaining the patch series</title> 20.324 + 20.325 + <para>In my work, I use a number of guards to control which 20.326 + patches are to be applied.</para> 20.327 + 20.328 + <itemizedlist> 20.329 + <listitem><para><quote>Accepted</quote> patches are guarded with 20.330 + <literal>accepted</literal>. I enable this guard most of 20.331 + the time. When I'm applying the patches on top of a tree 20.332 + where the patches are already present, I can turn this patch 20.333 + off, and the patches that follow it will apply 20.334 + cleanly.</para> 20.335 + </listitem> 20.336 + <listitem><para>Patches that are <quote>finished</quote>, but 20.337 + not yet submitted, have no guards. If I'm applying the 20.338 + patch stack to a copy of the upstream tree, I don't need to 20.339 + enable any guards in order to get a reasonably safe source 20.340 + tree.</para> 20.341 + </listitem> 20.342 + <listitem><para>Those patches that need reworking before being 20.343 + resubmitted are guarded with 20.344 + <literal>rework</literal>.</para> 20.345 + </listitem> 20.346 + <listitem><para>For those patches that are still under 20.347 + development, I use <literal>devel</literal>.</para> 20.348 + </listitem> 20.349 + <listitem><para>A backport patch may have several guards, one 20.350 + for each version of the kernel to which it applies. For 20.351 + example, a patch that backports a piece of code to 2.6.9 20.352 + will have a <literal>2.6.9</literal> guard.</para> 20.353 + </listitem></itemizedlist> 20.354 + <para>This variety of guards gives me considerable flexibility in 20.355 + determining what kind of source tree I want to end up with. For 20.356 + most situations, the selection of appropriate guards is 20.357 + automated during the build process, but I can manually tune the 20.358 + guards to use for less common circumstances.</para> 20.359 + 20.360 + <sect2> 20.361 + <title>The art of writing backport patches</title> 20.362 + 20.363 + <para>Using MQ, writing a backport patch is a simple process. 20.364 + All such a patch has to do is modify a piece of code that uses 20.365 + a kernel feature not present in the older version of the 20.366 + kernel, so that the driver continues to work correctly under 20.367 + that older version.</para> 20.368 + 20.369 + <para>A useful goal when writing a good backport patch is to 20.370 + make your code look as if it was written for the older version 20.371 + of the kernel you're targeting. The less obtrusive the patch, 20.372 + the easier it will be to understand and maintain. If you're 20.373 + writing a collection of backport patches to avoid the 20.374 + <quote>rat's nest</quote> effect of lots of 20.375 + <literal>#ifdef</literal>s (hunks of source code that are only 20.376 + used conditionally) in your code, don't introduce 20.377 + version-dependent <literal>#ifdef</literal>s into the patches. 20.378 + Instead, write several patches, each of which makes 20.379 + unconditional changes, and control their application using 20.380 + guards.</para> 20.381 + 20.382 + <para>There are two reasons to divide backport patches into a 20.383 + distinct group, away from the <quote>regular</quote> patches 20.384 + whose effects they modify. The first is that intermingling the 20.385 + two makes it more difficult to use a tool like the <literal 20.386 + role="hg-ext">patchbomb</literal> extension to automate the 20.387 + process of submitting the patches to an upstream maintainer. 20.388 + The second is that a backport patch could perturb the context 20.389 + in which a subsequent regular patch is applied, making it 20.390 + impossible to apply the regular patch cleanly 20.391 + <emphasis>without</emphasis> the earlier backport patch 20.392 + already being applied.</para> 20.393 + 20.394 + </sect2> 20.395 + </sect1> 20.396 + <sect1> 20.397 + <title>Useful tips for developing with MQ</title> 20.398 + 20.399 + <sect2> 20.400 + <title>Organising patches in directories</title> 20.401 + 20.402 + <para>If you're working on a substantial project with MQ, it's 20.403 + not difficult to accumulate a large number of patches. For 20.404 + example, I have one patch repository that contains over 250 20.405 + patches.</para> 20.406 + 20.407 + <para>If you can group these patches into separate logical 20.408 + categories, you can if you like store them in different 20.409 + directories; MQ has no problems with patch names that contain 20.410 + path separators.</para> 20.411 + 20.412 + </sect2> 20.413 + <sect2 id="mq-collab:tips:interdiff"> 20.414 + <title>Viewing the history of a patch</title> 20.415 + 20.416 + <para>If you're developing a set of patches over a long time, 20.417 + it's a good idea to maintain them in a repository, as 20.418 + discussed in section <xref linkend="sec:mq:repo"/>. If you do 20.419 + so, you'll quickly 20.420 + discover that using the <command role="hg-cmd">hg 20.421 + diff</command> command to look at the history of changes to 20.422 + a patch is unworkable. This is in part because you're looking 20.423 + at the second derivative of the real code (a diff of a diff), 20.424 + but also because MQ adds noise to the process by modifying 20.425 + time stamps and directory names when it updates a 20.426 + patch.</para> 20.427 + 20.428 + <para>However, you can use the <literal 20.429 + role="hg-ext">extdiff</literal> extension, which is bundled 20.430 + with Mercurial, to turn a diff of two versions of a patch into 20.431 + something readable. To do this, you will need a third-party 20.432 + package called <literal role="package">patchutils</literal> 20.433 + <citation>web:patchutils</citation>. This provides a command 20.434 + named <command>interdiff</command>, which shows the 20.435 + differences between two diffs as a diff. Used on two versions 20.436 + of the same diff, it generates a diff that represents the diff 20.437 + from the first to the second version.</para> 20.438 + 20.439 + <para>You can enable the <literal 20.440 + role="hg-ext">extdiff</literal> extension in the usual way, 20.441 + by adding a line to the <literal 20.442 + role="rc-extensions">extensions</literal> section of your 20.443 + <filename role="special"> /.hgrc</filename>.</para> 20.444 + <programlisting>[extensions] extdiff =</programlisting> 20.445 + <para>The <command>interdiff</command> command expects to be 20.446 + passed the names of two files, but the <literal 20.447 + role="hg-ext">extdiff</literal> extension passes the program 20.448 + it runs a pair of directories, each of which can contain an 20.449 + arbitrary number of files. We thus need a small program that 20.450 + will run <command>interdiff</command> on each pair of files in 20.451 + these two directories. This program is available as <filename 20.452 + role="special">hg-interdiff</filename> in the <filename 20.453 + class="directory">examples</filename> directory of the 20.454 + source code repository that accompanies this book. <!-- 20.455 + &example.hg-interdiff; --></para> 20.456 + 20.457 + <para>With the <filename role="special">hg-interdiff</filename> 20.458 + program in your shell's search path, you can run it as 20.459 + follows, from inside an MQ patch directory:</para> 20.460 + <programlisting>hg extdiff -p hg-interdiff -r A:B 20.461 + my-change.patch</programlisting> 20.462 + <para>Since you'll probably want to use this long-winded command 20.463 + a lot, you can get <literal role="hg-ext">hgext</literal> to 20.464 + make it available as a normal Mercurial command, again by 20.465 + editing your <filename role="special"> 20.466 + /.hgrc</filename>.</para> 20.467 + <programlisting>[extdiff] cmd.interdiff = 20.468 + hg-interdiff</programlisting> 20.469 + <para>This directs <literal role="hg-ext">hgext</literal> to 20.470 + make an <literal>interdiff</literal> command available, so you 20.471 + can now shorten the previous invocation of <command 20.472 + role="hg-ext-extdiff">extdiff</command> to something a 20.473 + little more wieldy.</para> 20.474 + <programlisting>hg interdiff -r A:B 20.475 + my-change.patch</programlisting> 20.476 + 20.477 + <note> 20.478 + <para> The <command>interdiff</command> command works well 20.479 + only if the underlying files against which versions of a 20.480 + patch are generated remain the same. If you create a patch, 20.481 + modify the underlying files, and then regenerate the patch, 20.482 + <command>interdiff</command> may not produce useful 20.483 + output.</para> 20.484 + </note> 20.485 + 20.486 + <para>The <literal role="hg-ext">extdiff</literal> extension is 20.487 + useful for more than merely improving the presentation of MQ 20.488 + patches. To read more about it, go to section <xref 20.489 + linkend="sec:hgext:extdiff"/>.</para> 20.490 + 20.491 + </sect2> 20.492 + </sect1> 20.493 +</chapter> 20.494 + 20.495 +<!-- 20.496 +local variables: 20.497 +sgml-parent-document: ("00book.xml" "book" "chapter") 20.498 +end: 20.499 +-->
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/en/ch14-hgext.xml Wed Feb 18 00:22:09 2009 -0800 21.3 @@ -0,0 +1,549 @@ 21.4 +<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : --> 21.5 + 21.6 +<chapter id="chap:hgext"> 21.7 + <title>Adding functionality with extensions</title> 21.8 + 21.9 + <para>While the core of Mercurial is quite complete from a 21.10 + functionality standpoint, it's deliberately shorn of fancy 21.11 + features. This approach of preserving simplicity keeps the 21.12 + software easy to deal with for both maintainers and users.</para> 21.13 + 21.14 + <para>However, Mercurial doesn't box you in with an inflexible 21.15 + command set: you can add features to it as 21.16 + <emphasis>extensions</emphasis> (sometimes known as 21.17 + <emphasis>plugins</emphasis>). We've already discussed a few of 21.18 + these extensions in earlier chapters.</para> 21.19 + <itemizedlist> 21.20 + <listitem><para>Section <xref linkend="sec:tour-merge:fetch"/> 21.21 + covers the <literal role="hg-ext">fetch</literal> extension; 21.22 + this combines pulling new changes and merging them with local 21.23 + changes into a single command, <command 21.24 + role="hg-ext-fetch">fetch</command>.</para> 21.25 + </listitem> 21.26 + <listitem><para>In chapter <xref linkend="chap:hook"/>, we covered 21.27 + several extensions that are useful for hook-related 21.28 + functionality: <literal role="hg-ext">acl</literal> adds 21.29 + access control lists; <literal 21.30 + role="hg-ext">bugzilla</literal> adds integration with the 21.31 + Bugzilla bug tracking system; and <literal 21.32 + role="hg-ext">notify</literal> sends notification emails on 21.33 + new changes.</para> 21.34 + </listitem> 21.35 + <listitem><para>The Mercurial Queues patch management extension is 21.36 + so invaluable that it merits two chapters and an appendix all 21.37 + to itself. Chapter <xref linkend="chap:mq"/> covers the 21.38 + basics; chapter <xref 21.39 + linkend="chap:mq-collab"/> discusses advanced topics; 21.40 + and appendix <xref linkend="chap:mqref"/> goes into detail on 21.41 + each 21.42 + command.</para> 21.43 + </listitem></itemizedlist> 21.44 + 21.45 + <para>In this chapter, we'll cover some of the other extensions that 21.46 + are available for Mercurial, and briefly touch on some of the 21.47 + machinery you'll need to know about if you want to write an 21.48 + extension of your own.</para> 21.49 + <itemizedlist> 21.50 + <listitem><para>In section <xref linkend="sec:hgext:inotify"/>, 21.51 + we'll discuss the possibility of <emphasis>huge</emphasis> 21.52 + performance improvements using the <literal 21.53 + role="hg-ext">inotify</literal> extension.</para> 21.54 + </listitem></itemizedlist> 21.55 + 21.56 + <sect1 id="sec:hgext:inotify"> 21.57 + <title>Improve performance with the <literal 21.58 + role="hg-ext">inotify</literal> extension</title> 21.59 + 21.60 + <para>Are you interested in having some of the most common 21.61 + Mercurial operations run as much as a hundred times faster? 21.62 + Read on!</para> 21.63 + 21.64 + <para>Mercurial has great performance under normal circumstances. 21.65 + For example, when you run the <command role="hg-cmd">hg 21.66 + status</command> command, Mercurial has to scan almost every 21.67 + directory and file in your repository so that it can display 21.68 + file status. Many other Mercurial commands need to do the same 21.69 + work behind the scenes; for example, the <command 21.70 + role="hg-cmd">hg diff</command> command uses the status 21.71 + machinery to avoid doing an expensive comparison operation on 21.72 + files that obviously haven't changed.</para> 21.73 + 21.74 + <para>Because obtaining file status is crucial to good 21.75 + performance, the authors of Mercurial have optimised this code 21.76 + to within an inch of its life. However, there's no avoiding the 21.77 + fact that when you run <command role="hg-cmd">hg 21.78 + status</command>, Mercurial is going to have to perform at 21.79 + least one expensive system call for each managed file to 21.80 + determine whether it's changed since the last time Mercurial 21.81 + checked. For a sufficiently large repository, this can take a 21.82 + long time.</para> 21.83 + 21.84 + <para>To put a number on the magnitude of this effect, I created a 21.85 + repository containing 150,000 managed files. I timed <command 21.86 + role="hg-cmd">hg status</command> as taking ten seconds to 21.87 + run, even when <emphasis>none</emphasis> of those files had been 21.88 + modified.</para> 21.89 + 21.90 + <para>Many modern operating systems contain a file notification 21.91 + facility. If a program signs up to an appropriate service, the 21.92 + operating system will notify it every time a file of interest is 21.93 + created, modified, or deleted. On Linux systems, the kernel 21.94 + component that does this is called 21.95 + <literal>inotify</literal>.</para> 21.96 + 21.97 + <para>Mercurial's <literal role="hg-ext">inotify</literal> 21.98 + extension talks to the kernel's <literal>inotify</literal> 21.99 + component to optimise <command role="hg-cmd">hg status</command> 21.100 + commands. The extension has two components. A daemon sits in 21.101 + the background and receives notifications from the 21.102 + <literal>inotify</literal> subsystem. It also listens for 21.103 + connections from a regular Mercurial command. The extension 21.104 + modifies Mercurial's behaviour so that instead of scanning the 21.105 + filesystem, it queries the daemon. Since the daemon has perfect 21.106 + information about the state of the repository, it can respond 21.107 + with a result instantaneously, avoiding the need to scan every 21.108 + directory and file in the repository.</para> 21.109 + 21.110 + <para>Recall the ten seconds that I measured plain Mercurial as 21.111 + taking to run <command role="hg-cmd">hg status</command> on a 21.112 + 150,000 file repository. With the <literal 21.113 + role="hg-ext">inotify</literal> extension enabled, the time 21.114 + dropped to 0.1 seconds, a factor of <emphasis>one 21.115 + hundred</emphasis> faster.</para> 21.116 + 21.117 + <para>Before we continue, please pay attention to some 21.118 + caveats.</para> 21.119 + <itemizedlist> 21.120 + <listitem><para>The <literal role="hg-ext">inotify</literal> 21.121 + extension is Linux-specific. Because it interfaces directly 21.122 + to the Linux kernel's <literal>inotify</literal> subsystem, 21.123 + it does not work on other operating systems.</para> 21.124 + </listitem> 21.125 + <listitem><para>It should work on any Linux distribution that 21.126 + was released after early 2005. Older distributions are 21.127 + likely to have a kernel that lacks 21.128 + <literal>inotify</literal>, or a version of 21.129 + <literal>glibc</literal> that does not have the necessary 21.130 + interfacing support.</para> 21.131 + </listitem> 21.132 + <listitem><para>Not all filesystems are suitable for use with 21.133 + the <literal role="hg-ext">inotify</literal> extension. 21.134 + Network filesystems such as NFS are a non-starter, for 21.135 + example, particularly if you're running Mercurial on several 21.136 + systems, all mounting the same network filesystem. The 21.137 + kernel's <literal>inotify</literal> system has no way of 21.138 + knowing about changes made on another system. Most local 21.139 + filesystems (e.g. ext3, XFS, ReiserFS) should work 21.140 + fine.</para> 21.141 + </listitem></itemizedlist> 21.142 + 21.143 + <para>The <literal role="hg-ext">inotify</literal> extension is 21.144 + not yet shipped with Mercurial as of May 2007, so it's a little 21.145 + more involved to set up than other extensions. But the 21.146 + performance improvement is worth it!</para> 21.147 + 21.148 + <para>The extension currently comes in two parts: a set of patches 21.149 + to the Mercurial source code, and a library of Python bindings 21.150 + to the <literal>inotify</literal> subsystem.</para> 21.151 + <note> 21.152 + <para> There are <emphasis>two</emphasis> Python 21.153 + <literal>inotify</literal> binding libraries. One of them is 21.154 + called <literal>pyinotify</literal>, and is packaged by some 21.155 + Linux distributions as <literal>python-inotify</literal>. 21.156 + This is <emphasis>not</emphasis> the one you'll need, as it is 21.157 + too buggy and inefficient to be practical.</para> 21.158 + </note> 21.159 + <para>To get going, it's best to already have a functioning copy 21.160 + of Mercurial installed.</para> 21.161 + <note> 21.162 + <para> If you follow the instructions below, you'll be 21.163 + <emphasis>replacing</emphasis> and overwriting any existing 21.164 + installation of Mercurial that you might already have, using 21.165 + the latest <quote>bleeding edge</quote> Mercurial code. Don't 21.166 + say you weren't warned!</para> 21.167 + </note> 21.168 + <orderedlist> 21.169 + <listitem><para>Clone the Python <literal>inotify</literal> 21.170 + binding repository. Build and install it.</para> 21.171 + <programlisting> 21.172 + hg clone http://hg.kublai.com/python/inotify cd inotify 21.173 + python setup.py build --force sudo python setup.py install 21.174 + --skip-build 21.175 + </programlisting> 21.176 + </listitem> 21.177 + <listitem><para>Clone the <filename 21.178 + class="directory">crew</filename> Mercurial repository. 21.179 + Clone the <literal role="hg-ext">inotify</literal> patch 21.180 + repository so that Mercurial Queues will be able to apply 21.181 + patches to your cope of the <filename 21.182 + class="directory">crew</filename> repository.</para> 21.183 + <programlisting> 21.184 + hg clone http://hg.intevation.org/mercurial/crew hg clone 21.185 + crew inotify hg clone 21.186 + http://hg.kublai.com/mercurial/patches/inotify 21.187 + inotify/.hg/patches 21.188 + </programlisting> 21.189 + </listitem> 21.190 + <listitem><para>Make sure that you have the Mercurial Queues 21.191 + extension, <literal role="hg-ext">mq</literal>, enabled. If 21.192 + you've never used MQ, read section <xref 21.193 + linkend="sec:mq:start"/> to get started 21.194 + quickly.</para> 21.195 + </listitem> 21.196 + <listitem><para>Go into the <filename 21.197 + class="directory">inotify</filename> repo, and apply all 21.198 + of the <literal role="hg-ext">inotify</literal> patches 21.199 + using the <option role="hg-ext-mq-cmd-qpush-opt">hg 21.200 + -a</option> option to the <command 21.201 + role="hg-ext-mq">qpush</command> command.</para> 21.202 + <programlisting> 21.203 + cd inotify hg qpush -a 21.204 + </programlisting> 21.205 + </listitem> 21.206 + <listitem><para> If you get an error message from <command 21.207 + role="hg-ext-mq">qpush</command>, you should not continue. 21.208 + Instead, ask for help.</para> 21.209 + </listitem> 21.210 + <listitem><para>Build and install the patched version of 21.211 + Mercurial.</para> 21.212 + <programlisting> 21.213 + python setup.py build --force sudo python setup.py install 21.214 + --skip-build 21.215 + </programlisting> 21.216 + </listitem> 21.217 + </orderedlist> 21.218 + <para>Once you've build a suitably patched version of Mercurial, 21.219 + all you need to do to enable the <literal 21.220 + role="hg-ext">inotify</literal> extension is add an entry to 21.221 + your <filename role="special"> /.hgrc</filename>.</para> 21.222 + <programlisting>[extensions] inotify =</programlisting> 21.223 + <para>When the <literal role="hg-ext">inotify</literal> extension 21.224 + is enabled, Mercurial will automatically and transparently start 21.225 + the status daemon the first time you run a command that needs 21.226 + status in a repository. It runs one status daemon per 21.227 + repository.</para> 21.228 + 21.229 + <para>The status daemon is started silently, and runs in the 21.230 + background. If you look at a list of running processes after 21.231 + you've enabled the <literal role="hg-ext">inotify</literal> 21.232 + extension and run a few commands in different repositories, 21.233 + you'll thus see a few <literal>hg</literal> processes sitting 21.234 + around, waiting for updates from the kernel and queries from 21.235 + Mercurial.</para> 21.236 + 21.237 + <para>The first time you run a Mercurial command in a repository 21.238 + when you have the <literal role="hg-ext">inotify</literal> 21.239 + extension enabled, it will run with about the same performance 21.240 + as a normal Mercurial command. This is because the status 21.241 + daemon needs to perform a normal status scan so that it has a 21.242 + baseline against which to apply later updates from the kernel. 21.243 + However, <emphasis>every</emphasis> subsequent command that does 21.244 + any kind of status check should be noticeably faster on 21.245 + repositories of even fairly modest size. Better yet, the bigger 21.246 + your repository is, the greater a performance advantage you'll 21.247 + see. The <literal role="hg-ext">inotify</literal> daemon makes 21.248 + status operations almost instantaneous on repositories of all 21.249 + sizes!</para> 21.250 + 21.251 + <para>If you like, you can manually start a status daemon using 21.252 + the <command role="hg-ext-inotify">inserve</command> command. 21.253 + This gives you slightly finer control over how the daemon ought 21.254 + to run. This command will of course only be available when the 21.255 + <literal role="hg-ext">inotify</literal> extension is 21.256 + enabled.</para> 21.257 + 21.258 + <para>When you're using the <literal 21.259 + role="hg-ext">inotify</literal> extension, you should notice 21.260 + <emphasis>no difference at all</emphasis> in Mercurial's 21.261 + behaviour, with the sole exception of status-related commands 21.262 + running a whole lot faster than they used to. You should 21.263 + specifically expect that commands will not print different 21.264 + output; neither should they give different results. If either of 21.265 + these situations occurs, please report a bug.</para> 21.266 + 21.267 + </sect1> 21.268 + <sect1 id="sec:hgext:extdiff"> 21.269 + <title>Flexible diff support with the <literal 21.270 + role="hg-ext">extdiff</literal> extension</title> 21.271 + 21.272 + <para>Mercurial's built-in <command role="hg-cmd">hg 21.273 + diff</command> command outputs plaintext unified diffs. <!-- 21.274 + &interaction.extdiff.diff; --> If you would like to use an 21.275 + external tool to display modifications, you'll want to use the 21.276 + <literal role="hg-ext">extdiff</literal> extension. This will 21.277 + let you use, for example, a graphical diff tool.</para> 21.278 + 21.279 + <para>The <literal role="hg-ext">extdiff</literal> extension is 21.280 + bundled with Mercurial, so it's easy to set up. In the <literal 21.281 + role="rc-extensions">extensions</literal> section of your 21.282 + <filename role="special"> /.hgrc</filename>, simply add a 21.283 + one-line entry to enable the extension.</para> 21.284 + <programlisting>[extensions] extdiff =</programlisting> 21.285 + <para>This introduces a command named <command 21.286 + role="hg-ext-extdiff">extdiff</command>, which by default uses 21.287 + your system's <command>diff</command> command to generate a 21.288 + unified diff in the same form as the built-in <command 21.289 + role="hg-cmd">hg diff</command> command. <!-- 21.290 + &interaction.extdiff.extdiff; --> The result won't be exactly 21.291 + the same as with the built-in <command role="hg-cmd">hg 21.292 + diff</command> variations, because the output of 21.293 + <command>diff</command> varies from one system to another, even 21.294 + when passed the same options.</para> 21.295 + 21.296 + <para>As the <quote><literal>making snapshot</literal></quote> 21.297 + lines of output above imply, the <command 21.298 + role="hg-ext-extdiff">extdiff</command> command works by 21.299 + creating two snapshots of your source tree. The first snapshot 21.300 + is of the source revision; the second, of the target revision or 21.301 + working directory. The <command 21.302 + role="hg-ext-extdiff">extdiff</command> command generates 21.303 + these snapshots in a temporary directory, passes the name of 21.304 + each directory to an external diff viewer, then deletes the 21.305 + temporary directory. For efficiency, it only snapshots the 21.306 + directories and files that have changed between the two 21.307 + revisions.</para> 21.308 + 21.309 + <para>Snapshot directory names have the same base name as your 21.310 + repository. If your repository path is <filename 21.311 + class="directory">/quux/bar/foo</filename>, then <filename 21.312 + class="directory">foo</filename> will be the name of each 21.313 + snapshot directory. Each snapshot directory name has its 21.314 + changeset ID appended, if appropriate. If a snapshot is of 21.315 + revision <literal>a631aca1083f</literal>, the directory will be 21.316 + named <filename class="directory">foo.a631aca1083f</filename>. 21.317 + A snapshot of the working directory won't have a changeset ID 21.318 + appended, so it would just be <filename 21.319 + class="directory">foo</filename> in this example. To see what 21.320 + this looks like in practice, look again at the <command 21.321 + role="hg-ext-extdiff">extdiff</command> example above. Notice 21.322 + that the diff has the snapshot directory names embedded in its 21.323 + header.</para> 21.324 + 21.325 + <para>The <command role="hg-ext-extdiff">extdiff</command> command 21.326 + accepts two important options. The <option 21.327 + role="hg-ext-extdiff-cmd-extdiff-opt">hg -p</option> option 21.328 + lets you choose a program to view differences with, instead of 21.329 + <command>diff</command>. With the <option 21.330 + role="hg-ext-extdiff-cmd-extdiff-opt">hg -o</option> option, 21.331 + you can change the options that <command 21.332 + role="hg-ext-extdiff">extdiff</command> passes to the program 21.333 + (by default, these options are 21.334 + <quote><literal>-Npru</literal></quote>, which only make sense 21.335 + if you're running <command>diff</command>). In other respects, 21.336 + the <command role="hg-ext-extdiff">extdiff</command> command 21.337 + acts similarly to the built-in <command role="hg-cmd">hg 21.338 + diff</command> command: you use the same option names, syntax, 21.339 + and arguments to specify the revisions you want, the files you 21.340 + want, and so on.</para> 21.341 + 21.342 + <para>As an example, here's how to run the normal system 21.343 + <command>diff</command> command, getting it to generate context 21.344 + diffs (using the <option role="cmd-opt-diff">-c</option> option) 21.345 + instead of unified diffs, and five lines of context instead of 21.346 + the default three (passing <literal>5</literal> as the argument 21.347 + to the <option role="cmd-opt-diff">-C</option> option). <!-- 21.348 + &interaction.extdiff.extdiff-ctx; --></para> 21.349 + 21.350 + <para>Launching a visual diff tool is just as easy. Here's how to 21.351 + launch the <command>kdiff3</command> viewer.</para> 21.352 + <programlisting>hg extdiff -p kdiff3 -o</programlisting> 21.353 + 21.354 + <para>If your diff viewing command can't deal with directories, 21.355 + you can easily work around this with a little scripting. For an 21.356 + example of such scripting in action with the <literal 21.357 + role="hg-ext">mq</literal> extension and the 21.358 + <command>interdiff</command> command, see section <xref 21.359 + linkend="mq-collab:tips:interdiff"/>.</para> 21.360 + 21.361 + <sect2> 21.362 + <title>Defining command aliases</title> 21.363 + 21.364 + <para>It can be cumbersome to remember the options to both the 21.365 + <command role="hg-ext-extdiff">extdiff</command> command and 21.366 + the diff viewer you want to use, so the <literal 21.367 + role="hg-ext">extdiff</literal> extension lets you define 21.368 + <emphasis>new</emphasis> commands that will invoke your diff 21.369 + viewer with exactly the right options.</para> 21.370 + 21.371 + <para>All you need to do is edit your <filename role="special"> 21.372 + /.hgrc</filename>, and add a section named <literal 21.373 + role="rc-extdiff">extdiff</literal>. Inside this section, 21.374 + you can define multiple commands. Here's how to add a 21.375 + <literal>kdiff3</literal> command. Once you've defined this, 21.376 + you can type <quote><literal>hg kdiff3</literal></quote> and 21.377 + the <literal role="hg-ext">extdiff</literal> extension will 21.378 + run <command>kdiff3</command> for you.</para> 21.379 + <programlisting>[extdiff] cmd.kdiff3 =</programlisting> 21.380 + <para>If you leave the right hand side of the definition empty, 21.381 + as above, the <literal role="hg-ext">extdiff</literal> 21.382 + extension uses the name of the command you defined as the name 21.383 + of the external program to run. But these names don't have to 21.384 + be the same. Here, we define a command named 21.385 + <quote><literal>hg wibble</literal></quote>, which runs 21.386 + <command>kdiff3</command>.</para> 21.387 + <programlisting>[extdiff] cmd.wibble = kdiff3</programlisting> 21.388 + 21.389 + <para>You can also specify the default options that you want to 21.390 + invoke your diff viewing program with. The prefix to use is 21.391 + <quote><literal>opts.</literal></quote>, followed by the name 21.392 + of the command to which the options apply. This example 21.393 + defines a <quote><literal>hg vimdiff</literal></quote> command 21.394 + that runs the <command>vim</command> editor's 21.395 + <literal>DirDiff</literal> extension.</para> 21.396 + <programlisting>[extdiff] cmd.vimdiff = vim opts.vimdiff = -f 21.397 + '+next' '+execute "DirDiff" argv(0) argv(1)'</programlisting> 21.398 + 21.399 + </sect2> 21.400 + </sect1> 21.401 + <sect1 id="sec:hgext:transplant"> 21.402 + <title>Cherrypicking changes with the <literal 21.403 + role="hg-ext">transplant</literal> extension</title> 21.404 + 21.405 + <para>Need to have a long chat with Brendan about this.</para> 21.406 + 21.407 + </sect1> 21.408 + <sect1 id="sec:hgext:patchbomb"> 21.409 + <title>Send changes via email with the <literal 21.410 + role="hg-ext">patchbomb</literal> extension</title> 21.411 + 21.412 + <para>Many projects have a culture of <quote>change 21.413 + review</quote>, in which people send their modifications to a 21.414 + mailing list for others to read and comment on before they 21.415 + commit the final version to a shared repository. Some projects 21.416 + have people who act as gatekeepers; they apply changes from 21.417 + other people to a repository to which those others don't have 21.418 + access.</para> 21.419 + 21.420 + <para>Mercurial makes it easy to send changes over email for 21.421 + review or application, via its <literal 21.422 + role="hg-ext">patchbomb</literal> extension. The extension is 21.423 + so namd because changes are formatted as patches, and it's usual 21.424 + to send one changeset per email message. Sending a long series 21.425 + of changes by email is thus much like <quote>bombing</quote> the 21.426 + recipient's inbox, hence <quote>patchbomb</quote>.</para> 21.427 + 21.428 + <para>As usual, the basic configuration of the <literal 21.429 + role="hg-ext">patchbomb</literal> extension takes just one or 21.430 + two lines in your <filename role="special"> 21.431 + /.hgrc</filename>.</para> 21.432 + <programlisting>[extensions] patchbomb =</programlisting> 21.433 + <para>Once you've enabled the extension, you will have a new 21.434 + command available, named <command 21.435 + role="hg-ext-patchbomb">email</command>.</para> 21.436 + 21.437 + <para>The safest and best way to invoke the <command 21.438 + role="hg-ext-patchbomb">email</command> command is to 21.439 + <emphasis>always</emphasis> run it first with the <option 21.440 + role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option. 21.441 + This will show you what the command <emphasis>would</emphasis> 21.442 + send, without actually sending anything. Once you've had a 21.443 + quick glance over the changes and verified that you are sending 21.444 + the right ones, you can rerun the same command, with the <option 21.445 + role="hg-ext-patchbomb-cmd-email-opt">hg -n</option> option 21.446 + removed.</para> 21.447 + 21.448 + <para>The <command role="hg-ext-patchbomb">email</command> command 21.449 + accepts the same kind of revision syntax as every other 21.450 + Mercurial command. For example, this command will send every 21.451 + revision between 7 and <literal>tip</literal>, inclusive.</para> 21.452 + <programlisting>hg email -n 7:tip</programlisting> 21.453 + <para>You can also specify a <emphasis>repository</emphasis> to 21.454 + compare with. If you provide a repository but no revisions, the 21.455 + <command role="hg-ext-patchbomb">email</command> command will 21.456 + send all revisions in the local repository that are not present 21.457 + in the remote repository. If you additionally specify revisions 21.458 + or a branch name (the latter using the <option 21.459 + role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> option), 21.460 + this will constrain the revisions sent.</para> 21.461 + 21.462 + <para>It's perfectly safe to run the <command 21.463 + role="hg-ext-patchbomb">email</command> command without the 21.464 + names of the people you want to send to: if you do this, it will 21.465 + just prompt you for those values interactively. (If you're 21.466 + using a Linux or Unix-like system, you should have enhanced 21.467 + <literal>readline</literal>-style editing capabilities when 21.468 + entering those headers, too, which is useful.)</para> 21.469 + 21.470 + <para>When you are sending just one revision, the <command 21.471 + role="hg-ext-patchbomb">email</command> command will by 21.472 + default use the first line of the changeset description as the 21.473 + subject of the single email message it sends.</para> 21.474 + 21.475 + <para>If you send multiple revisions, the <command 21.476 + role="hg-ext-patchbomb">email</command> command will usually 21.477 + send one message per changeset. It will preface the series with 21.478 + an introductory message, in which you should describe the 21.479 + purpose of the series of changes you're sending.</para> 21.480 + 21.481 + <sect2> 21.482 + <title>Changing the behaviour of patchbombs</title> 21.483 + 21.484 + <para>Not every project has exactly the same conventions for 21.485 + sending changes in email; the <literal 21.486 + role="hg-ext">patchbomb</literal> extension tries to 21.487 + accommodate a number of variations through command line 21.488 + options.</para> 21.489 + <itemizedlist> 21.490 + <listitem><para>You can write a subject for the introductory 21.491 + message on the command line using the <option 21.492 + role="hg-ext-patchbomb-cmd-email-opt">hg -s</option> 21.493 + option. This takes one argument, the text of the subject 21.494 + to use.</para> 21.495 + </listitem> 21.496 + <listitem><para>To change the email address from which the 21.497 + messages originate, use the <option 21.498 + role="hg-ext-patchbomb-cmd-email-opt">hg -f</option> 21.499 + option. This takes one argument, the email address to 21.500 + use.</para> 21.501 + </listitem> 21.502 + <listitem><para>The default behaviour is to send unified diffs 21.503 + (see section <xref linkend="sec:mq:patch"/> for a 21.504 + description of the 21.505 + format), one per message. You can send a binary bundle 21.506 + instead with the <option 21.507 + role="hg-ext-patchbomb-cmd-email-opt">hg -b</option> 21.508 + option.</para> 21.509 + </listitem> 21.510 + <listitem><para>Unified diffs are normally prefaced with a 21.511 + metadata header. You can omit this, and send unadorned 21.512 + diffs, with the <option 21.513 + role="hg-ext-patchbomb-cmd-email-opt">hg 21.514 + --plain</option> option.</para> 21.515 + </listitem> 21.516 + <listitem><para>Diffs are normally sent <quote>inline</quote>, 21.517 + in the same body part as the description of a patch. This 21.518 + makes it easiest for the largest number of readers to 21.519 + quote and respond to parts of a diff, as some mail clients 21.520 + will only quote the first MIME body part in a message. If 21.521 + you'd prefer to send the description and the diff in 21.522 + separate body parts, use the <option 21.523 + role="hg-ext-patchbomb-cmd-email-opt">hg -a</option> 21.524 + option.</para> 21.525 + </listitem> 21.526 + <listitem><para>Instead of sending mail messages, you can 21.527 + write them to an <literal>mbox</literal>-format mail 21.528 + folder using the <option 21.529 + role="hg-ext-patchbomb-cmd-email-opt">hg -m</option> 21.530 + option. That option takes one argument, the name of the 21.531 + file to write to.</para> 21.532 + </listitem> 21.533 + <listitem><para>If you would like to add a 21.534 + <command>diffstat</command>-format summary to each patch, 21.535 + and one to the introductory message, use the <option 21.536 + role="hg-ext-patchbomb-cmd-email-opt">hg -d</option> 21.537 + option. The <command>diffstat</command> command displays 21.538 + a table containing the name of each file patched, the 21.539 + number of lines affected, and a histogram showing how much 21.540 + each file is modified. This gives readers a qualitative 21.541 + glance at how complex a patch is.</para> 21.542 + </listitem></itemizedlist> 21.543 + 21.544 + </sect2> 21.545 + </sect1> 21.546 +</chapter> 21.547 + 21.548 +<!-- 21.549 +local variables: 21.550 +sgml-parent-document: ("00book.xml" "book" "chapter") 21.551 +end: 21.552 +-->
22.1 --- a/tools/latex-to-docbook Mon Feb 09 23:25:40 2009 -0800 22.2 +++ b/tools/latex-to-docbook Wed Feb 18 00:22:09 2009 -0800 22.3 @@ -33,7 +33,7 @@ 22.4 line = (line.rstrip() 22.5 .replace('~', ' ') 22.6 .replace('&', '&') 22.7 - .replace('&emdash;', '&emdash;') 22.8 + .replace('---', '&emdash;') 22.9 .replace('\_', '_') 22.10 .replace('\{', '{') 22.11 .replace('\}', '}') 22.12 @@ -83,7 +83,7 @@ 22.13 line = re.sub(r'\\filename{(?P<file>[^}]+?)}', 22.14 r'<filename>\g<file></filename>', line) 22.15 line = re.sub(r'\\tildefile{(?P<file>[^}]+)}', 22.16 - r'<filename role="home"> /\g<file></filename>', line) 22.17 + r'<filename role="home">~/\g<file></filename>', line) 22.18 line = re.sub(r'\\sfilename{(?P<file>[^}]+)}', 22.19 r'<filename role="special">\g<file></filename>', line) 22.20 line = re.sub(r'\\sdirname{(?P<dir>[^}]+)}', 22.21 @@ -95,7 +95,7 @@ 22.22 line = re.sub(r'\\pymod{(?P<mod>[^}]+)}', 22.23 r'<literal role="py-mod">\g<mod></literal>', line) 22.24 line = re.sub(r'\\pymodclass{(?P<mod>[^}]+)}{(?P<class>[^}]+)}', 22.25 - r'<literal url="py-mod-\g<mod>">\g<class></ulink>', line) 22.26 + r'<literal role="py-mod-\g<mod>">\g<class></literal>', line) 22.27 line = re.sub(r'\\url{(?P<url>[^}]+)}', 22.28 r'<ulink url="\g<url>">\g<url></ulink>', line) 22.29 line = re.sub(r'\\href{(?P<url>[^}]+)}{(?P<text>[^}]+)}', 22.30 @@ -154,7 +154,7 @@ 22.31 inlist = 1 22.32 else: 22.33 ofp.write('</') 22.34 - if env == ('itemizedlist', 'orderedlist'): 22.35 + if env in ('itemizedlist', 'orderedlist'): 22.36 inlist = 0 22.37 print >> ofp, env + '>' 22.38 else: