hgbook

diff en/ch09-hook.xml @ 686:e9154b3daa94

Repurpose appendix A.
author Bryan O'Sullivan <bos@serpentine.com>
date Sun Apr 26 23:16:56 2009 -0700 (2009-04-26)
parents b338f5490029
children 88828b784971
line diff
     1.1 --- a/en/ch09-hook.xml	Thu Apr 09 22:52:16 2009 -0700
     1.2 +++ b/en/ch09-hook.xml	Sun Apr 26 23:16:56 2009 -0700
     1.3 @@ -147,8 +147,8 @@
     1.4  	  incoming</command>), remember that it is the other
     1.5  	repository's hooks you should be checking, not your own.
     1.6        </para>
     1.7 -
     1.8 -    </sect2>
     1.9 +    </sect2>
    1.10 +
    1.11      <sect2>
    1.12        <title>Hooks do not propagate</title>
    1.13  
    1.14 @@ -178,8 +178,8 @@
    1.15  	filesystem, and use a site-wide <filename role="special">~/.hgrc</filename> file to define hooks that all users will
    1.16  	see.  However, this too has its limits; see below.
    1.17        </para>
    1.18 -
    1.19 -    </sect2>
    1.20 +    </sect2>
    1.21 +
    1.22      <sect2>
    1.23        <title>Hooks can be overridden</title>
    1.24  
    1.25 @@ -193,8 +193,8 @@
    1.26  	hooks, you should thus understand that your users can disable
    1.27  	or override those hooks.
    1.28        </para>
    1.29 -
    1.30 -    </sect2>
    1.31 +    </sect2>
    1.32 +
    1.33      <sect2>
    1.34        <title>Ensuring that critical hooks are run</title>
    1.35  
    1.36 @@ -232,116 +232,7 @@
    1.37  
    1.38      </sect2>
    1.39    </sect1>
    1.40 -  <sect1>
    1.41 -    <title>Care with <literal>pretxn</literal> hooks in a
    1.42 -      shared-access repository</title>
    1.43 -
    1.44 -    <para id="x_206">If you want to use hooks to do some automated work in a
    1.45 -      repository that a number of people have shared access to, you
    1.46 -      need to be careful in how you do this.
    1.47 -    </para>
    1.48 -
    1.49 -    <para id="x_207">Mercurial only locks a repository when it is writing to the
    1.50 -      repository, and only the parts of Mercurial that write to the
    1.51 -      repository pay attention to locks.  Write locks are necessary to
    1.52 -      prevent multiple simultaneous writers from scribbling on each
    1.53 -      other's work, corrupting the repository.
    1.54 -    </para>
    1.55 -
    1.56 -    <para id="x_208">Because Mercurial is careful with the order in which it
    1.57 -      reads and writes data, it does not need to acquire a lock when
    1.58 -      it wants to read data from the repository.  The parts of
    1.59 -      Mercurial that read from the repository never pay attention to
    1.60 -      locks.  This lockless reading scheme greatly increases
    1.61 -      performance and concurrency.
    1.62 -    </para>
    1.63 -
    1.64 -    <para id="x_209">With great performance comes a trade-off, though, one which
    1.65 -      has the potential to cause you trouble unless you're aware of
    1.66 -      it.  To describe this requires a little detail about how
    1.67 -      Mercurial adds changesets to a repository and reads those
    1.68 -      changes.
    1.69 -    </para>
    1.70 -
    1.71 -    <para id="x_20a">When Mercurial <emphasis>writes</emphasis> metadata, it
    1.72 -      writes it straight into the destination file.  It writes file
    1.73 -      data first, then manifest data (which contains pointers to the
    1.74 -      new file data), then changelog data (which contains pointers to
    1.75 -      the new manifest data).  Before the first write to each file, it
    1.76 -      stores a record of where the end of the file was in its
    1.77 -      transaction log.  If the transaction must be rolled back,
    1.78 -      Mercurial simply truncates each file back to the size it was
    1.79 -      before the transaction began.
    1.80 -    </para>
    1.81 -
    1.82 -    <para id="x_20b">When Mercurial <emphasis>reads</emphasis> metadata, it reads
    1.83 -      the changelog first, then everything else.  Since a reader will
    1.84 -      only access parts of the manifest or file metadata that it can
    1.85 -      see in the changelog, it can never see partially written data.
    1.86 -    </para>
    1.87 -
    1.88 -    <para id="x_20c">Some controlling hooks (<literal
    1.89 -	role="hook">pretxncommit</literal> and <literal
    1.90 -	role="hook">pretxnchangegroup</literal>) run when a
    1.91 -      transaction is almost complete. All of the metadata has been
    1.92 -      written, but Mercurial can still roll the transaction back and
    1.93 -      cause the newly-written data to disappear.
    1.94 -    </para>
    1.95 -
    1.96 -    <para id="x_20d">If one of these hooks runs for long, it opens a window of
    1.97 -      time during which a reader can see the metadata for changesets
    1.98 -      that are not yet permanent, and should not be thought of as
    1.99 -      <quote>really there</quote>.  The longer the hook runs, the
   1.100 -      longer that window is open.
   1.101 -    </para>
   1.102 -
   1.103 -    <sect2>
   1.104 -      <title>The problem illustrated</title>
   1.105 -
   1.106 -      <para id="x_20e">In principle, a good use for the <literal
   1.107 -	  role="hook">pretxnchangegroup</literal> hook would be to
   1.108 -	automatically build and test incoming changes before they are
   1.109 -	accepted into a central repository.  This could let you
   1.110 -	guarantee that nobody can push changes to this repository that
   1.111 -	<quote>break the build</quote>. But if a client can pull
   1.112 -	changes while they're being tested, the usefulness of the test
   1.113 -	is zero; an unsuspecting someone can pull untested changes,
   1.114 -	potentially breaking their build.
   1.115 -      </para>
   1.116 -
   1.117 -      <para id="x_20f">The safest technological answer to this challenge is to
   1.118 -	set up such a <quote>gatekeeper</quote> repository as
   1.119 -	<emphasis>unidirectional</emphasis>.  Let it take changes
   1.120 -	pushed in from the outside, but do not allow anyone to pull
   1.121 -	changes from it (use the <literal
   1.122 -	  role="hook">preoutgoing</literal> hook to lock it down).
   1.123 -	Configure a <literal role="hook">changegroup</literal> hook so
   1.124 -	that if a build or test succeeds, the hook will push the new
   1.125 -	changes out to another repository that people
   1.126 -	<emphasis>can</emphasis> pull from.
   1.127 -      </para>
   1.128 -
   1.129 -      <para id="x_210">In practice, putting a centralised bottleneck like this in
   1.130 -	place is not often a good idea, and transaction visibility has
   1.131 -	nothing to do with the problem.  As the size of a
   1.132 -	project&emdash;and the time it takes to build and
   1.133 -	test&emdash;grows, you rapidly run into a wall with this
   1.134 -	<quote>try before you buy</quote> approach, where you have
   1.135 -	more changesets to test than time in which to deal with them.
   1.136 -	The inevitable result is frustration on the part of all
   1.137 -	involved.
   1.138 -      </para>
   1.139 -
   1.140 -      <para id="x_211">An approach that scales better is to get people to build
   1.141 -	and test before they push, then run automated builds and tests
   1.142 -	centrally <emphasis>after</emphasis> a push, to be sure all is
   1.143 -	well.  The advantage of this approach is that it does not
   1.144 -	impose a limit on the rate at which the repository can accept
   1.145 -	changes.
   1.146 -      </para>
   1.147 -
   1.148 -    </sect2>
   1.149 -  </sect1>
   1.150 +
   1.151    <sect1 id="sec:hook:simple">
   1.152      <title>A short tutorial on using hooks</title>
   1.153  
   1.154 @@ -509,8 +400,8 @@
   1.155  	<literal>foo</literal>, while the environment variable for an
   1.156  	external hook will be named <literal>HG_FOO</literal>.
   1.157        </para>
   1.158 -
   1.159 -    </sect2>
   1.160 +    </sect2>
   1.161 +
   1.162      <sect2>
   1.163        <title>Hook return values and activity control</title>
   1.164  
   1.165 @@ -526,8 +417,8 @@
   1.166  	zero/false means <quote>allow</quote>, while
   1.167  	non-zero/true/exception means <quote>deny</quote>.
   1.168        </para>
   1.169 -
   1.170 -    </sect2>
   1.171 +    </sect2>
   1.172 +
   1.173      <sect2>
   1.174        <title>Writing an external hook</title>
   1.175  
   1.176 @@ -555,8 +446,8 @@
   1.177  	should not rely on environment variables being set to the
   1.178  	values you have in your environment when testing the hook.
   1.179        </para>
   1.180 -
   1.181 -    </sect2>
   1.182 +    </sect2>
   1.183 +
   1.184      <sect2>
   1.185        <title>Telling Mercurial to use an in-process hook</title>
   1.186  
   1.187 @@ -585,8 +476,8 @@
   1.188  	for the callable object named <literal>myhook</literal>, and
   1.189  	calls it.
   1.190        </para>
   1.191 -
   1.192 -    </sect2>
   1.193 +    </sect2>
   1.194 +
   1.195      <sect2>
   1.196        <title>Writing an in-process hook</title>
   1.197  
   1.198 @@ -622,8 +513,8 @@
   1.199        </para>
   1.200  
   1.201  &interaction.hook.msglen.go;
   1.202 -
   1.203 -    </sect2>
   1.204 +    </sect2>
   1.205 +
   1.206      <sect2>
   1.207        <title>Checking for trailing whitespace</title>
   1.208  
   1.209 @@ -838,8 +729,8 @@
   1.210  	  forbidding pushes from specific users.
   1.211  	</para>
   1.212  
   1.213 -      </sect3>
   1.214 -    </sect2>
   1.215 +      </sect3>    </sect2>
   1.216 +
   1.217      <sect2>
   1.218        <title><literal
   1.219  	  role="hg-ext">bugzilla</literal>&emdash;integration with
   1.220 @@ -1144,8 +1035,8 @@
   1.221  	  a valid Bugzilla user name.
   1.222  	</para>
   1.223  
   1.224 -      </sect3>
   1.225 -    </sect2>
   1.226 +      </sect3>    </sect2>
   1.227 +
   1.228      <sect2>
   1.229        <title><literal role="hg-ext">notify</literal>&emdash;send email
   1.230  	notifications</title>
   1.231 @@ -1344,8 +1235,8 @@
   1.232  	APIs normally use.  To convert a hash from hex to binary, use
   1.233  	the <literal>bin</literal> function.
   1.234        </para>
   1.235 -
   1.236 -    </sect2>
   1.237 +    </sect2>
   1.238 +
   1.239      <sect2>
   1.240        <title>External hook execution</title>
   1.241  
   1.242 @@ -1382,8 +1273,8 @@
   1.243  	have succeeded.  If it exits with a non-zero status, it is
   1.244  	considered to have failed.
   1.245        </para>
   1.246 -
   1.247 -    </sect2>
   1.248 +    </sect2>
   1.249 +
   1.250      <sect2>
   1.251        <title>Finding out where changesets come from</title>
   1.252  
   1.253 @@ -1425,8 +1316,8 @@
   1.254  	      being transferred to or from a bundle.
   1.255  	    </para>
   1.256  	  </listitem></itemizedlist>
   1.257 -
   1.258        </sect3>
   1.259 +
   1.260        <sect3 id="sec:hook:url">
   1.261  	<title>Where changes are going&emdash;remote repository
   1.262  	  URLs</title>
   1.263 @@ -1462,7 +1353,6 @@
   1.264  	      discovered about the remote client.
   1.265  	    </para>
   1.266  	  </listitem></itemizedlist>
   1.267 -
   1.268        </sect3>
   1.269      </sect2>
   1.270    </sect1>
   1.271 @@ -1520,8 +1410,8 @@
   1.272  	  role="hook">pretxnchangegroup</literal> (<xref
   1.273  	  linkend="sec:hook:pretxnchangegroup"/>)
   1.274        </para>
   1.275 -
   1.276 -    </sect2>
   1.277 +    </sect2>
   1.278 +
   1.279      <sect2 id="sec:hook:commit">
   1.280        <title><literal role="hook">commit</literal>&emdash;after a new
   1.281  	changeset is created</title>
   1.282 @@ -1553,8 +1443,8 @@
   1.283  	  role="hook">pretxncommit</literal> (<xref
   1.284  	  linkend="sec:hook:pretxncommit"/>)
   1.285        </para>
   1.286 -
   1.287 -    </sect2>
   1.288 +    </sect2>
   1.289 +
   1.290      <sect2 id="sec:hook:incoming">
   1.291        <title><literal role="hook">incoming</literal>&emdash;after one
   1.292  	remote changeset is added</title>
   1.293 @@ -1599,8 +1489,8 @@
   1.294  	  role="hook">pretxnchangegroup</literal> (<xref
   1.295  	  linkend="sec:hook:pretxnchangegroup"/>)
   1.296        </para>
   1.297 -
   1.298 -    </sect2>
   1.299 +    </sect2>
   1.300 +
   1.301      <sect2 id="sec:hook:outgoing">
   1.302        <title><literal role="hook">outgoing</literal>&emdash;after
   1.303  	changesets are propagated</title>
   1.304 @@ -1646,8 +1536,8 @@
   1.305  	  role="hook">preoutgoing</literal> (<xref
   1.306  	  linkend="sec:hook:preoutgoing"/>)
   1.307        </para>
   1.308 -
   1.309 -    </sect2>
   1.310 +    </sect2>
   1.311 +
   1.312      <sect2 id="sec:hook:prechangegroup">
   1.313        <title><literal
   1.314  	  role="hook">prechangegroup</literal>&emdash;before starting
   1.315 @@ -1692,8 +1582,8 @@
   1.316  	  role="hook">pretxnchangegroup</literal> (<xref
   1.317  	  linkend="sec:hook:pretxnchangegroup"/>)
   1.318        </para>
   1.319 -
   1.320 -    </sect2>
   1.321 +    </sect2>
   1.322 +
   1.323      <sect2 id="sec:hook:precommit">
   1.324        <title><literal role="hook">precommit</literal>&emdash;before
   1.325  	starting to commit a changeset</title>
   1.326 @@ -1732,8 +1622,8 @@
   1.327  	  role="hook">pretxncommit</literal> (<xref
   1.328  	  linkend="sec:hook:pretxncommit"/>)
   1.329        </para>
   1.330 -
   1.331 -    </sect2>
   1.332 +    </sect2>
   1.333 +
   1.334      <sect2 id="sec:hook:preoutgoing">
   1.335        <title><literal role="hook">preoutgoing</literal>&emdash;before
   1.336  	starting to propagate changesets</title>
   1.337 @@ -1769,8 +1659,8 @@
   1.338  	  role="hook">outgoing</literal> (<xref
   1.339  	  linkend="sec:hook:outgoing"/>)
   1.340        </para>
   1.341 -
   1.342 -    </sect2>
   1.343 +    </sect2>
   1.344 +
   1.345      <sect2 id="sec:hook:pretag">
   1.346        <title><literal role="hook">pretag</literal>&emdash;before
   1.347  	tagging a changeset</title>
   1.348 @@ -1811,6 +1701,7 @@
   1.349  	(<xref linkend="sec:hook:tag"/>)
   1.350        </para>
   1.351      </sect2>
   1.352 +
   1.353      <sect2 id="sec:hook:pretxnchangegroup">
   1.354        <title><literal
   1.355  	  role="hook">pretxnchangegroup</literal>&emdash;before
   1.356 @@ -1875,8 +1766,8 @@
   1.357  	  role="hook">prechangegroup</literal> (<xref
   1.358  	  linkend="sec:hook:prechangegroup"/>)
   1.359        </para>
   1.360 -
   1.361 -    </sect2>
   1.362 +    </sect2>
   1.363 +
   1.364      <sect2 id="sec:hook:pretxncommit">
   1.365        <title><literal role="hook">pretxncommit</literal>&emdash;before
   1.366  	completing commit of new changeset</title>
   1.367 @@ -1901,8 +1792,8 @@
   1.368  	race conditions if you do not take steps to avoid them.
   1.369        </para>
   1.370  
   1.371 -      <para id="x_2d2">Parameters to this hook:
   1.372 -      </para>
   1.373 +      <para id="x_2d2">Parameters to this hook:</para>
   1.374 +
   1.375        <itemizedlist>
   1.376  	<listitem><para id="x_2d3"><literal>node</literal>: A changeset ID.  The
   1.377  	    changeset ID of the newly committed changeset.
   1.378 @@ -1923,8 +1814,8 @@
   1.379  	  role="hook">precommit</literal> (<xref
   1.380  	  linkend="sec:hook:precommit"/>)
   1.381        </para>
   1.382 -
   1.383 -    </sect2>
   1.384 +    </sect2>
   1.385 +
   1.386      <sect2 id="sec:hook:preupdate">
   1.387        <title><literal role="hook">preupdate</literal>&emdash;before
   1.388  	updating or merging working directory</title>
   1.389 @@ -1955,8 +1846,8 @@
   1.390  
   1.391        <para id="x_2db">See also: <literal role="hook">update</literal>
   1.392  	(<xref linkend="sec:hook:update"/>)</para>
   1.393 -
   1.394 -    </sect2>
   1.395 +    </sect2>
   1.396 +
   1.397      <sect2 id="sec:hook:tag">
   1.398        <title><literal role="hook">tag</literal>&emdash;after tagging a
   1.399  	changeset</title>
   1.400 @@ -1992,8 +1883,8 @@
   1.401        <para id="x_2e2">See also: <literal role="hook">pretag</literal>
   1.402  	(<xref linkend="sec:hook:pretag"/>)
   1.403        </para>
   1.404 -
   1.405 -    </sect2>
   1.406 +    </sect2>
   1.407 +
   1.408      <sect2 id="sec:hook:update">
   1.409        <title><literal role="hook">update</literal>&emdash;after
   1.410  	updating or merging working directory</title>