changeset 654:b08f6a61bf15

Merge
author Bryan O'Sullivan <bos@serpentine.com>
date Mon, 09 Feb 2009 22:59:50 -0800
parents 863a82f13901 (diff) 91adcea08b33 (current diff)
children dbb4c40e2609
files en/ch09-undo.tex en/examples/bisect
diffstat 173 files changed, 30901 insertions(+), 9824 deletions(-) [+]
line wrap: on
line diff
--- a/en/00book.tex	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/00book.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -40,27 +40,27 @@
 
 \pagenumbering{arabic}
 
-\include{preface}
-\include{intro}
-\include{tour-basic}
-\include{tour-merge}
-\include{concepts}
-\include{daily}
-\include{collab}
-\include{filenames}
-\include{branch}
-\include{undo}
-\include{hook}
-\include{template}
-\include{mq}
-\include{mq-collab}
-\include{hgext}
+\include{ch00-preface}
+\include{ch01-intro}
+\include{ch02-tour-basic}
+\include{ch03-tour-merge}
+\include{ch04-concepts}
+\include{ch05-daily}
+\include{ch06-collab}
+\include{ch07-filenames}
+\include{ch08-branch}
+\include{ch09-undo}
+\include{ch10-hook}
+\include{ch11-template}
+\include{ch12-mq}
+\include{ch13-mq-collab}
+\include{ch14-hgext}
 
 \appendix
-\include{cmdref}
-\include{mq-ref}
-\include{srcinstall}
-\include{license}
+\include{appA-cmdref}
+\include{appB-mq-ref}
+\include{appC-srcinstall}
+\include{appD-license}
 \addcontentsline{toc}{chapter}{Bibliography}
 \bibliographystyle{alpha}
 \bibliography{99book}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/00book.xml	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
+ "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd"
+[
+<!-- Below are references to files in this directory. -->
+
+<!-- Chapters. -->
+
+<!ENTITY ch01     SYSTEM "ch01-intro.xml">
+<!ENTITY ch02     SYSTEM "ch02-tour-basic.xml">
+
+<!-- Include our standard shortcuts. -->
+
+<!ENTITY % SHORTCUTS SYSTEM "book-shortcuts.xml">
+%SHORTCUTS;
+]>
+
+<book id="hg">
+  <title>Mercurial: The Definitive Guide</title>
+  <bookinfo>
+    <authorgroup>
+      <author>
+        <firstname>Bryan</firstname>
+        <surname>O'Sullivan</surname>
+      </author>
+    </authorgroup>
+
+    <editor>
+      <firstname>Mike</firstname>
+      <surname>Loukides</surname>
+    </editor>
+
+    <copyright>
+      <year>2007</year>
+      <year>2008</year>
+      <holder>Bryan O'Sullivan</holder>
+    </copyright>
+  </bookinfo>
+
+  &ch01;
+  &ch02;
+</book>
--- a/en/99defs.tex	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/99defs.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -136,6 +136,10 @@
 % Reference entry for a command option with only long form.
 \newcommand{\loptref}[2]{\subsubsection{\hgopt{#1}{--#2} option}}
 
+% command to generate a footnote to be used as a translator's note
+\newcommand{\ndt}[1]{\footnote{\textbf{N. del T.} #1}}
+
+
 %%% Local Variables: 
 %%% mode: latex
 %%% TeX-master: "00book"
--- a/en/Makefile	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/Makefile	Mon Feb 09 22:59:50 2009 -0800
@@ -4,26 +4,8 @@
 	00book.tex \
 	99book.bib \
 	99defs.tex \
-	build_id.tex \
-	branch.tex \
-	cmdref.tex \
-	collab.tex \
-	concepts.tex \
-	daily.tex \
-	filenames.tex \
-	hg_id.tex \
-	hgext.tex \
-	hook.tex \
-	intro.tex \
-	mq.tex \
-	mq-collab.tex \
-	mq-ref.tex \
-	preface.tex \
-	srcinstall.tex \
-	template.tex \
-	tour-basic.tex \
-	tour-merge.tex \
-	undo.tex
+	app*.tex \
+	ch*.tex
 
 image-sources := \
 	feature-branches.dot \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/appA-cmdref.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,175 @@
+\chapter{Command reference}
+\label{cmdref}
+
+\cmdref{add}{add files at the next commit}
+\optref{add}{I}{include}
+\optref{add}{X}{exclude}
+\optref{add}{n}{dry-run}
+
+\cmdref{diff}{print changes in history or working directory}
+
+Show differences between revisions for the specified files or
+directories, using the unified diff format.  For a description of the
+unified diff format, see section~\ref{sec:mq:patch}.
+
+By default, this command does not print diffs for files that Mercurial
+considers to contain binary data.  To control this behaviour, see the
+\hgopt{diff}{-a} and \hgopt{diff}{--git} options.
+
+\subsection{Options}
+
+\loptref{diff}{nodates}
+
+Omit date and time information when printing diff headers.
+
+\optref{diff}{B}{ignore-blank-lines}
+
+Do not print changes that only insert or delete blank lines.  A line
+that contains only whitespace is not considered blank.
+
+\optref{diff}{I}{include}
+
+Include files and directories whose names match the given patterns.
+
+\optref{diff}{X}{exclude}
+
+Exclude files and directories whose names match the given patterns.
+
+\optref{diff}{a}{text}
+
+If this option is not specified, \hgcmd{diff} will refuse to print
+diffs for files that it detects as binary. Specifying \hgopt{diff}{-a}
+forces \hgcmd{diff} to treat all files as text, and generate diffs for
+all of them.
+
+This option is useful for files that are ``mostly text'' but have a
+few embedded NUL characters.  If you use it on files that contain a
+lot of binary data, its output will be incomprehensible.
+
+\optref{diff}{b}{ignore-space-change}
+
+Do not print a line if the only change to that line is in the amount
+of white space it contains.
+
+\optref{diff}{g}{git}
+
+Print \command{git}-compatible diffs.  XXX reference a format
+description.
+
+\optref{diff}{p}{show-function}
+
+Display the name of the enclosing function in a hunk header, using a
+simple heuristic.  This functionality is enabled by default, so the
+\hgopt{diff}{-p} option has no effect unless you change the value of
+the \rcitem{diff}{showfunc} config item, as in the following example.
+\interaction{cmdref.diff-p}
+
+\optref{diff}{r}{rev}
+
+Specify one or more revisions to compare.  The \hgcmd{diff} command
+accepts up to two \hgopt{diff}{-r} options to specify the revisions to
+compare.
+
+\begin{enumerate}
+\setcounter{enumi}{0}
+\item Display the differences between the parent revision of the
+  working directory and the working directory.
+\item Display the differences between the specified changeset and the
+  working directory.
+\item Display the differences between the two specified changesets.
+\end{enumerate}
+
+You can specify two revisions using either two \hgopt{diff}{-r}
+options or revision range notation.  For example, the two revision
+specifications below are equivalent.
+\begin{codesample2}
+  hg diff -r 10 -r 20
+  hg diff -r10:20
+\end{codesample2}
+
+When you provide two revisions, Mercurial treats the order of those
+revisions as significant.  Thus, \hgcmdargs{diff}{-r10:20} will
+produce a diff that will transform files from their contents as of
+revision~10 to their contents as of revision~20, while
+\hgcmdargs{diff}{-r20:10} means the opposite: the diff that will
+transform files from their revision~20 contents to their revision~10
+contents.  You cannot reverse the ordering in this way if you are
+diffing against the working directory.
+
+\optref{diff}{w}{ignore-all-space}
+
+\cmdref{version}{print version and copyright information}
+
+This command displays the version of Mercurial you are running, and
+its copyright license.  There are four kinds of version string that
+you may see.
+\begin{itemize}
+\item The string ``\texttt{unknown}''. This version of Mercurial was
+  not built in a Mercurial repository, and cannot determine its own
+  version.
+\item A short numeric string, such as ``\texttt{1.1}''. This is a
+  build of a revision of Mercurial that was identified by a specific
+  tag in the repository where it was built.  (This doesn't necessarily
+  mean that you're running an official release; someone else could
+  have added that tag to any revision in the repository where they
+  built Mercurial.)
+\item A hexadecimal string, such as ``\texttt{875489e31abe}''.  This
+  is a build of the given revision of Mercurial.
+\item A hexadecimal string followed by a date, such as
+  ``\texttt{875489e31abe+20070205}''.  This is a build of the given
+  revision of Mercurial, where the build repository contained some
+  local changes that had not been committed.
+\end{itemize}
+
+\subsection{Tips and tricks}
+
+\subsubsection{Why do the results of \hgcmd{diff} and \hgcmd{status} differ?}
+\label{cmdref:diff-vs-status}
+
+When you run the \hgcmd{status} command, you'll see a list of files
+that Mercurial will record changes for the next time you perform a
+commit.  If you run the \hgcmd{diff} command, you may notice that it
+prints diffs for only a \emph{subset} of the files that \hgcmd{status}
+listed.  There are two possible reasons for this.
+
+The first is that \hgcmd{status} prints some kinds of modifications
+that \hgcmd{diff} doesn't normally display.  The \hgcmd{diff} command
+normally outputs unified diffs, which don't have the ability to
+represent some changes that Mercurial can track.  Most notably,
+traditional diffs can't represent a change in whether or not a file is
+executable, but Mercurial records this information.
+
+If you use the \hgopt{diff}{--git} option to \hgcmd{diff}, it will
+display \command{git}-compatible diffs that \emph{can} display this
+extra information.
+
+The second possible reason that \hgcmd{diff} might be printing diffs
+for a subset of the files displayed by \hgcmd{status} is that if you
+invoke it without any arguments, \hgcmd{diff} prints diffs against the
+first parent of the working directory.  If you have run \hgcmd{merge}
+to merge two changesets, but you haven't yet committed the results of
+the merge, your working directory has two parents (use \hgcmd{parents}
+to see them).  While \hgcmd{status} prints modifications relative to
+\emph{both} parents after an uncommitted merge, \hgcmd{diff} still
+operates relative only to the first parent.  You can get it to print
+diffs relative to the second parent by specifying that parent with the
+\hgopt{diff}{-r} option.  There is no way to print diffs relative to
+both parents.
+
+\subsubsection{Generating safe binary diffs}
+
+If you use the \hgopt{diff}{-a} option to force Mercurial to print
+diffs of files that are either ``mostly text'' or contain lots of
+binary data, those diffs cannot subsequently be applied by either
+Mercurial's \hgcmd{import} command or the system's \command{patch}
+command.  
+
+If you want to generate a diff of a binary file that is safe to use as
+input for \hgcmd{import}, use the \hgcmd{diff}{--git} option when you
+generate the patch.  The system \command{patch} command cannot handle
+binary patches at all.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/appB-mq-ref.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,349 @@
+\chapter{Mercurial Queues reference}
+\label{chap:mqref}
+
+\section{MQ command reference}
+\label{sec:mqref:cmdref}
+
+For an overview of the commands provided by MQ, use the command
+\hgcmdargs{help}{mq}.
+
+\subsection{\hgxcmd{mq}{qapplied}---print applied patches}
+
+The \hgxcmd{mq}{qapplied} command prints the current stack of applied
+patches.  Patches are printed in oldest-to-newest order, so the last
+patch in the list is the ``top'' patch.
+
+\subsection{\hgxcmd{mq}{qcommit}---commit changes in the queue repository}
+
+The \hgxcmd{mq}{qcommit} command commits any outstanding changes in the
+\sdirname{.hg/patches} repository.  This command only works if the
+\sdirname{.hg/patches} directory is a repository, i.e.~you created the
+directory using \hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} or ran
+\hgcmd{init} in the directory after running \hgxcmd{mq}{qinit}.
+
+This command is shorthand for \hgcmdargs{commit}{--cwd .hg/patches}.
+
+\subsection{\hgxcmd{mq}{qdelete}---delete a patch from the
+  \sfilename{series} file}
+
+The \hgxcmd{mq}{qdelete} command removes the entry for a patch from the
+\sfilename{series} file in the \sdirname{.hg/patches} directory.  It
+does not pop the patch if the patch is already applied.  By default,
+it does not delete the patch file; use the \hgxopt{mq}{qdel}{-f} option to
+do that.
+
+Options:
+\begin{itemize}
+\item[\hgxopt{mq}{qdel}{-f}] Delete the patch file.
+\end{itemize}
+
+\subsection{\hgxcmd{mq}{qdiff}---print a diff of the topmost applied patch}
+
+The \hgxcmd{mq}{qdiff} command prints a diff of the topmost applied patch.
+It is equivalent to \hgcmdargs{diff}{-r-2:-1}.
+
+\subsection{\hgxcmd{mq}{qfold}---merge (``fold'') several patches into one}
+
+The \hgxcmd{mq}{qfold} command merges multiple patches into the topmost
+applied patch, so that the topmost applied patch makes the union of
+all of the changes in the patches in question.
+
+The patches to fold must not be applied; \hgxcmd{mq}{qfold} will exit with
+an error if any is.  The order in which patches are folded is
+significant; \hgcmdargs{qfold}{a b} means ``apply the current topmost
+patch, followed by \texttt{a}, followed by \texttt{b}''.
+
+The comments from the folded patches are appended to the comments of
+the destination patch, with each block of comments separated by three
+asterisk (``\texttt{*}'') characters.  Use the \hgxopt{mq}{qfold}{-e}
+option to edit the commit message for the combined patch/changeset
+after the folding has completed.
+
+Options:
+\begin{itemize}
+\item[\hgxopt{mq}{qfold}{-e}] Edit the commit message and patch description
+  for the newly folded patch.
+\item[\hgxopt{mq}{qfold}{-l}] Use the contents of the given file as the new
+  commit message and patch description for the folded patch.
+\item[\hgxopt{mq}{qfold}{-m}] Use the given text as the new commit message
+  and patch description for the folded patch.
+\end{itemize}
+
+\subsection{\hgxcmd{mq}{qheader}---display the header/description of a patch}
+
+The \hgxcmd{mq}{qheader} command prints the header, or description, of a
+patch.  By default, it prints the header of the topmost applied patch.
+Given an argument, it prints the header of the named patch.
+
+\subsection{\hgxcmd{mq}{qimport}---import a third-party patch into the queue}
+
+The \hgxcmd{mq}{qimport} command adds an entry for an external patch to the
+\sfilename{series} file, and copies the patch into the
+\sdirname{.hg/patches} directory.  It adds the entry immediately after
+the topmost applied patch, but does not push the patch.
+
+If the \sdirname{.hg/patches} directory is a repository,
+\hgxcmd{mq}{qimport} automatically does an \hgcmd{add} of the imported
+patch.
+
+\subsection{\hgxcmd{mq}{qinit}---prepare a repository to work with MQ}
+
+The \hgxcmd{mq}{qinit} command prepares a repository to work with MQ.  It
+creates a directory called \sdirname{.hg/patches}.
+
+Options:
+\begin{itemize}
+\item[\hgxopt{mq}{qinit}{-c}] Create \sdirname{.hg/patches} as a repository
+  in its own right.  Also creates a \sfilename{.hgignore} file that
+  will ignore the \sfilename{status} file.
+\end{itemize}
+
+When the \sdirname{.hg/patches} directory is a repository, the
+\hgxcmd{mq}{qimport} and \hgxcmd{mq}{qnew} commands automatically \hgcmd{add}
+new patches.
+
+\subsection{\hgxcmd{mq}{qnew}---create a new patch}
+
+The \hgxcmd{mq}{qnew} command creates a new patch.  It takes one mandatory
+argument, the name to use for the patch file.  The newly created patch
+is created empty by default.  It is added to the \sfilename{series}
+file after the current topmost applied patch, and is immediately
+pushed on top of that patch.
+
+If \hgxcmd{mq}{qnew} finds modified files in the working directory, it will
+refuse to create a new patch unless the \hgxopt{mq}{qnew}{-f} option is
+used (see below).  This behaviour allows you to \hgxcmd{mq}{qrefresh} your
+topmost applied patch before you apply a new patch on top of it.
+
+Options:
+\begin{itemize}
+\item[\hgxopt{mq}{qnew}{-f}] Create a new patch if the contents of the
+  working directory are modified.  Any outstanding modifications are
+  added to the newly created patch, so after this command completes,
+  the working directory will no longer be modified.
+\item[\hgxopt{mq}{qnew}{-m}] Use the given text as the commit message.
+  This text will be stored at the beginning of the patch file, before
+  the patch data.
+\end{itemize}
+
+\subsection{\hgxcmd{mq}{qnext}---print the name of the next patch}
+
+The \hgxcmd{mq}{qnext} command prints the name name of the next patch in
+the \sfilename{series} file after the topmost applied patch.  This
+patch will become the topmost applied patch if you run \hgxcmd{mq}{qpush}.
+
+\subsection{\hgxcmd{mq}{qpop}---pop patches off the stack}
+
+The \hgxcmd{mq}{qpop} command removes applied patches from the top of the
+stack of applied patches.  By default, it removes only one patch.
+
+This command removes the changesets that represent the popped patches
+from the repository, and updates the working directory to undo the
+effects of the patches.
+
+This command takes an optional argument, which it uses as the name or
+index of the patch to pop to.  If given a name, it will pop patches
+until the named patch is the topmost applied patch.  If given a
+number, \hgxcmd{mq}{qpop} treats the number as an index into the entries in
+the series file, counting from zero (empty lines and lines containing
+only comments do not count).  It pops patches until the patch
+identified by the given index is the topmost applied patch.
+
+The \hgxcmd{mq}{qpop} command does not read or write patches or the
+\sfilename{series} file.  It is thus safe to \hgxcmd{mq}{qpop} a patch that
+you have removed from the \sfilename{series} file, or a patch that you
+have renamed or deleted entirely.  In the latter two cases, use the
+name of the patch as it was when you applied it.
+
+By default, the \hgxcmd{mq}{qpop} command will not pop any patches if the
+working directory has been modified.  You can override this behaviour
+using the \hgxopt{mq}{qpop}{-f} option, which reverts all modifications in
+the working directory.
+
+Options:
+\begin{itemize}
+\item[\hgxopt{mq}{qpop}{-a}] Pop all applied patches.  This returns the
+  repository to its state before you applied any patches.
+\item[\hgxopt{mq}{qpop}{-f}] Forcibly revert any modifications to the
+  working directory when popping.
+\item[\hgxopt{mq}{qpop}{-n}] Pop a patch from the named queue.
+\end{itemize}
+
+The \hgxcmd{mq}{qpop} command removes one line from the end of the
+\sfilename{status} file for each patch that it pops.
+
+\subsection{\hgxcmd{mq}{qprev}---print the name of the previous patch}
+
+The \hgxcmd{mq}{qprev} command prints the name of the patch in the
+\sfilename{series} file that comes before the topmost applied patch.
+This will become the topmost applied patch if you run \hgxcmd{mq}{qpop}.
+
+\subsection{\hgxcmd{mq}{qpush}---push patches onto the stack}
+\label{sec:mqref:cmd:qpush}
+
+The \hgxcmd{mq}{qpush} command adds patches onto the applied stack.  By
+default, it adds only one patch.
+
+This command creates a new changeset to represent each applied patch,
+and updates the working directory to apply the effects of the patches.
+
+The default data used when creating a changeset are as follows:
+\begin{itemize}
+\item The commit date and time zone are the current date and time
+  zone.  Because these data are used to compute the identity of a
+  changeset, this means that if you \hgxcmd{mq}{qpop} a patch and
+  \hgxcmd{mq}{qpush} it again, the changeset that you push will have a
+  different identity than the changeset you popped.
+\item The author is the same as the default used by the \hgcmd{commit}
+  command.
+\item The commit message is any text from the patch file that comes
+  before the first diff header.  If there is no such text, a default
+  commit message is used that identifies the name of the patch.
+\end{itemize}
+If a patch contains a Mercurial patch header (XXX add link), the
+information in the patch header overrides these defaults.
+
+Options:
+\begin{itemize}
+\item[\hgxopt{mq}{qpush}{-a}] Push all unapplied patches from the
+  \sfilename{series} file until there are none left to push.
+\item[\hgxopt{mq}{qpush}{-l}] Add the name of the patch to the end
+  of the commit message.
+\item[\hgxopt{mq}{qpush}{-m}] If a patch fails to apply cleanly, use the
+  entry for the patch in another saved queue to compute the parameters
+  for a three-way merge, and perform a three-way merge using the
+  normal Mercurial merge machinery.  Use the resolution of the merge
+  as the new patch content.
+\item[\hgxopt{mq}{qpush}{-n}] Use the named queue if merging while pushing.
+\end{itemize}
+
+The \hgxcmd{mq}{qpush} command reads, but does not modify, the
+\sfilename{series} file.  It appends one line to the \hgcmd{status}
+file for each patch that it pushes.
+
+\subsection{\hgxcmd{mq}{qrefresh}---update the topmost applied patch}
+
+The \hgxcmd{mq}{qrefresh} command updates the topmost applied patch.  It
+modifies the patch, removes the old changeset that represented the
+patch, and creates a new changeset to represent the modified patch.
+
+The \hgxcmd{mq}{qrefresh} command looks for the following modifications:
+\begin{itemize}
+\item Changes to the commit message, i.e.~the text before the first
+  diff header in the patch file, are reflected in the new changeset
+  that represents the patch.
+\item Modifications to tracked files in the working directory are
+  added to the patch.
+\item Changes to the files tracked using \hgcmd{add}, \hgcmd{copy},
+  \hgcmd{remove}, or \hgcmd{rename}.  Added files and copy and rename
+  destinations are added to the patch, while removed files and rename
+  sources are removed.
+\end{itemize}
+
+Even if \hgxcmd{mq}{qrefresh} detects no changes, it still recreates the
+changeset that represents the patch.  This causes the identity of the
+changeset to differ from the previous changeset that identified the
+patch.
+
+Options:
+\begin{itemize}
+\item[\hgxopt{mq}{qrefresh}{-e}] Modify the commit and patch description,
+  using the preferred text editor.
+\item[\hgxopt{mq}{qrefresh}{-m}] Modify the commit message and patch
+  description, using the given text.
+\item[\hgxopt{mq}{qrefresh}{-l}] Modify the commit message and patch
+  description, using text from the given file.
+\end{itemize}
+
+\subsection{\hgxcmd{mq}{qrename}---rename a patch}
+
+The \hgxcmd{mq}{qrename} command renames a patch, and changes the entry for
+the patch in the \sfilename{series} file.
+
+With a single argument, \hgxcmd{mq}{qrename} renames the topmost applied
+patch.  With two arguments, it renames its first argument to its
+second.
+
+\subsection{\hgxcmd{mq}{qrestore}---restore saved queue state}
+
+XXX No idea what this does.
+
+\subsection{\hgxcmd{mq}{qsave}---save current queue state}
+
+XXX Likewise.
+
+\subsection{\hgxcmd{mq}{qseries}---print the entire patch series}
+
+The \hgxcmd{mq}{qseries} command prints the entire patch series from the
+\sfilename{series} file.  It prints only patch names, not empty lines
+or comments.  It prints in order from first to be applied to last.
+
+\subsection{\hgxcmd{mq}{qtop}---print the name of the current patch}
+
+The \hgxcmd{mq}{qtop} prints the name of the topmost currently applied
+patch.
+
+\subsection{\hgxcmd{mq}{qunapplied}---print patches not yet applied}
+
+The \hgxcmd{mq}{qunapplied} command prints the names of patches from the
+\sfilename{series} file that are not yet applied.  It prints them in
+order from the next patch that will be pushed to the last.
+
+\subsection{\hgcmd{strip}---remove a revision and descendants}
+
+The \hgcmd{strip} command removes a revision, and all of its
+descendants, from the repository.  It undoes the effects of the
+removed revisions from the repository, and updates the working
+directory to the first parent of the removed revision.
+
+The \hgcmd{strip} command saves a backup of the removed changesets in
+a bundle, so that they can be reapplied if removed in error.
+
+Options:
+\begin{itemize}
+\item[\hgopt{strip}{-b}] Save unrelated changesets that are intermixed
+  with the stripped changesets in the backup bundle.
+\item[\hgopt{strip}{-f}] If a branch has multiple heads, remove all
+  heads. XXX This should be renamed, and use \texttt{-f} to strip revs
+  when there are pending changes.
+\item[\hgopt{strip}{-n}] Do not save a backup bundle.
+\end{itemize}
+
+\section{MQ file reference}
+
+\subsection{The \sfilename{series} file}
+
+The \sfilename{series} file contains a list of the names of all
+patches that MQ can apply.  It is represented as a list of names, with
+one name saved per line.  Leading and trailing white space in each
+line are ignored.
+
+Lines may contain comments.  A comment begins with the ``\texttt{\#}''
+character, and extends to the end of the line.  Empty lines, and lines
+that contain only comments, are ignored.
+
+You will often need to edit the \sfilename{series} file by hand, hence
+the support for comments and empty lines noted above.  For example,
+you can comment out a patch temporarily, and \hgxcmd{mq}{qpush} will skip
+over that patch when applying patches.  You can also change the order
+in which patches are applied by reordering their entries in the
+\sfilename{series} file.
+
+Placing the \sfilename{series} file under revision control is also
+supported; it is a good idea to place all of the patches that it
+refers to under revision control, as well.  If you create a patch
+directory using the \hgxopt{mq}{qinit}{-c} option to \hgxcmd{mq}{qinit}, this
+will be done for you automatically.
+
+\subsection{The \sfilename{status} file}
+
+The \sfilename{status} file contains the names and changeset hashes of
+all patches that MQ currently has applied.  Unlike the
+\sfilename{series} file, this file is not intended for editing.  You
+should not place this file under revision control, or modify it in any
+way.  It is used by MQ strictly for internal book-keeping.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/appC-srcinstall.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,53 @@
+\chapter{Installing Mercurial from source}
+\label{chap:srcinstall}
+
+\section{On a Unix-like system}
+\label{sec:srcinstall:unixlike}
+
+If you are using a Unix-like system that has a sufficiently recent
+version of Python (2.3~or newer) available, it is easy to install
+Mercurial from source.
+\begin{enumerate}
+\item Download a recent source tarball from
+  \url{http://www.selenic.com/mercurial/download}.
+\item Unpack the tarball:
+  \begin{codesample4}
+    gzip -dc mercurial-\emph{version}.tar.gz | tar xf -
+  \end{codesample4}
+\item Go into the source directory and run the installer script.  This
+  will build Mercurial and install it in your home directory.
+  \begin{codesample4}
+    cd mercurial-\emph{version}
+    python setup.py install --force --home=\$HOME
+  \end{codesample4}
+\end{enumerate}
+Once the install finishes, Mercurial will be in the \texttt{bin}
+subdirectory of your home directory.  Don't forget to make sure that
+this directory is present in your shell's search path.
+
+You will probably need to set the \envar{PYTHONPATH} environment
+variable so that the Mercurial executable can find the rest of the
+Mercurial packages.  For example, on my laptop, I have set it to
+\texttt{/home/bos/lib/python}.  The exact path that you will need to
+use depends on how Python was built for your system, but should be
+easy to figure out.  If you're uncertain, look through the output of
+the installer script above, and see where the contents of the
+\texttt{mercurial} directory were installed to.
+
+\section{On Windows}
+
+Building and installing Mercurial on Windows requires a variety of
+tools, a fair amount of technical knowledge, and considerable
+patience.  I very much \emph{do not recommend} this route if you are a
+``casual user''.  Unless you intend to hack on Mercurial, I strongly
+suggest that you use a binary package instead.
+
+If you are intent on building Mercurial from source on Windows, follow
+the ``hard way'' directions on the Mercurial wiki at
+\url{http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall},
+and expect the process to involve a lot of fiddly work.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/appD-license.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,138 @@
+\chapter{Open Publication License}
+\label{cha:opl}
+
+Version 1.0, 8 June 1999
+
+\section{Requirements on both unmodified and modified versions}
+
+The Open Publication works may be reproduced and distributed in whole
+or in part, in any medium physical or electronic, provided that the
+terms of this license are adhered to, and that this license or an
+incorporation of it by reference (with any options elected by the
+author(s) and/or publisher) is displayed in the reproduction.
+
+Proper form for an incorporation by reference is as follows:
+
+\begin{quote}
+  Copyright (c) \emph{year} by \emph{author's name or designee}. This
+  material may be distributed only subject to the terms and conditions
+  set forth in the Open Publication License, v\emph{x.y} or later (the
+  latest version is presently available at
+  \url{http://www.opencontent.org/openpub/}).
+\end{quote}
+
+The reference must be immediately followed with any options elected by
+the author(s) and/or publisher of the document (see
+section~\ref{sec:opl:options}).
+
+Commercial redistribution of Open Publication-licensed material is
+permitted.
+
+Any publication in standard (paper) book form shall require the
+citation of the original publisher and author. The publisher and
+author's names shall appear on all outer surfaces of the book. On all
+outer surfaces of the book the original publisher's name shall be as
+large as the title of the work and cited as possessive with respect to
+the title.
+
+\section{Copyright}
+
+The copyright to each Open Publication is owned by its author(s) or
+designee.
+
+\section{Scope of license}
+
+The following license terms apply to all Open Publication works,
+unless otherwise explicitly stated in the document.
+
+Mere aggregation of Open Publication works or a portion of an Open
+Publication work with other works or programs on the same media shall
+not cause this license to apply to those other works. The aggregate
+work shall contain a notice specifying the inclusion of the Open
+Publication material and appropriate copyright notice.
+
+\textbf{Severability}. If any part of this license is found to be
+unenforceable in any jurisdiction, the remaining portions of the
+license remain in force.
+
+\textbf{No warranty}. Open Publication works are licensed and provided
+``as is'' without warranty of any kind, express or implied, including,
+but not limited to, the implied warranties of merchantability and
+fitness for a particular purpose or a warranty of non-infringement.
+
+\section{Requirements on modified works}
+
+All modified versions of documents covered by this license, including
+translations, anthologies, compilations and partial documents, must
+meet the following requirements:
+
+\begin{enumerate}
+\item The modified version must be labeled as such.
+\item The person making the modifications must be identified and the
+  modifications dated.
+\item Acknowledgement of the original author and publisher if
+  applicable must be retained according to normal academic citation
+  practices.
+\item The location of the original unmodified document must be
+  identified.
+\item The original author's (or authors') name(s) may not be used to
+  assert or imply endorsement of the resulting document without the
+  original author's (or authors') permission.
+\end{enumerate}
+
+\section{Good-practice recommendations}
+
+In addition to the requirements of this license, it is requested from
+and strongly recommended of redistributors that:
+
+\begin{enumerate}
+\item If you are distributing Open Publication works on hardcopy or
+  CD-ROM, you provide email notification to the authors of your intent
+  to redistribute at least thirty days before your manuscript or media
+  freeze, to give the authors time to provide updated documents. This
+  notification should describe modifications, if any, made to the
+  document.
+\item All substantive modifications (including deletions) be either
+  clearly marked up in the document or else described in an attachment
+  to the document.
+\item Finally, while it is not mandatory under this license, it is
+  considered good form to offer a free copy of any hardcopy and CD-ROM
+  expression of an Open Publication-licensed work to its author(s).
+\end{enumerate}
+
+\section{License options}
+\label{sec:opl:options}
+
+The author(s) and/or publisher of an Open Publication-licensed
+document may elect certain options by appending language to the
+reference to or copy of the license. These options are considered part
+of the license instance and must be included with the license (or its
+incorporation by reference) in derived works.
+
+\begin{enumerate}[A]
+\item To prohibit distribution of substantively modified versions
+  without the explicit permission of the author(s). ``Substantive
+  modification'' is defined as a change to the semantic content of the
+  document, and excludes mere changes in format or typographical
+  corrections.
+
+  To accomplish this, add the phrase ``Distribution of substantively
+  modified versions of this document is prohibited without the
+  explicit permission of the copyright holder.'' to the license
+  reference or copy.
+
+\item To prohibit any publication of this work or derivative works in
+  whole or in part in standard (paper) book form for commercial
+  purposes is prohibited unless prior permission is obtained from the
+  copyright holder.
+
+  To accomplish this, add the phrase ``Distribution of the work or
+  derivative of the work in any standard (paper) book form is
+  prohibited unless prior permission is obtained from the copyright
+  holder.'' to the license reference or copy.
+\end{enumerate}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- a/en/branch.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,392 +0,0 @@
-\chapter{Managing releases and branchy development}
-\label{chap:branch}
-
-Mercurial provides several mechanisms for you to manage a project that
-is making progress on multiple fronts at once.  To understand these
-mechanisms, let's first take a brief look at a fairly normal software
-project structure.
-
-Many software projects issue periodic ``major'' releases that contain
-substantial new features.  In parallel, they may issue ``minor''
-releases.  These are usually identical to the major releases off which
-they're based, but with a few bugs fixed.
-
-In this chapter, we'll start by talking about how to keep records of
-project milestones such as releases.  We'll then continue on to talk
-about the flow of work between different phases of a project, and how
-Mercurial can help you to isolate and manage this work.
-
-\section{Giving a persistent name to a revision}
-
-Once you decide that you'd like to call a particular revision a
-``release'', it's a good idea to record the identity of that revision.
-This will let you reproduce that release at a later date, for whatever
-purpose you might need at the time (reproducing a bug, porting to a
-new platform, etc).
-\interaction{tag.init}
-
-Mercurial lets you give a permanent name to any revision using the
-\hgcmd{tag} command.  Not surprisingly, these names are called
-``tags''.
-\interaction{tag.tag}
-
-A tag is nothing more than a ``symbolic name'' for a revision.  Tags
-exist purely for your convenience, so that you have a handy permanent
-way to refer to a revision; Mercurial doesn't interpret the tag names
-you use in any way.  Neither does Mercurial place any restrictions on
-the name of a tag, beyond a few that are necessary to ensure that a
-tag can be parsed unambiguously.  A tag name cannot contain any of the
-following characters:
-\begin{itemize}
-\item Colon (ASCII 58, ``\texttt{:}'')
-\item Carriage return (ASCII 13, ``\Verb+\r+'')
-\item Newline (ASCII 10, ``\Verb+\n+'')
-\end{itemize}
-
-You can use the \hgcmd{tags} command to display the tags present in
-your repository.  In the output, each tagged revision is identified
-first by its name, then by revision number, and finally by the unique
-hash of the revision.  
-\interaction{tag.tags}
-Notice that \texttt{tip} is listed in the output of \hgcmd{tags}.  The
-\texttt{tip} tag is a special ``floating'' tag, which always
-identifies the newest revision in the repository.
-
-In the output of the \hgcmd{tags} command, tags are listed in reverse
-order, by revision number.  This usually means that recent tags are
-listed before older tags.  It also means that \texttt{tip} is always
-going to be the first tag listed in the output of \hgcmd{tags}.
-
-When you run \hgcmd{log}, if it displays a revision that has tags
-associated with it, it will print those tags.
-\interaction{tag.log}
-
-Any time you need to provide a revision~ID to a Mercurial command, the
-command will accept a tag name in its place.  Internally, Mercurial
-will translate your tag name into the corresponding revision~ID, then
-use that.
-\interaction{tag.log.v1.0}
-
-There's no limit on the number of tags you can have in a repository,
-or on the number of tags that a single revision can have.  As a
-practical matter, it's not a great idea to have ``too many'' (a number
-which will vary from project to project), simply because tags are
-supposed to help you to find revisions.  If you have lots of tags, the
-ease of using them to identify revisions diminishes rapidly.
-
-For example, if your project has milestones as frequent as every few
-days, it's perfectly reasonable to tag each one of those.  But if you
-have a continuous build system that makes sure every revision can be
-built cleanly, you'd be introducing a lot of noise if you were to tag
-every clean build.  Instead, you could tag failed builds (on the
-assumption that they're rare!), or simply not use tags to track
-buildability.
-
-If you want to remove a tag that you no longer want, use
-\hgcmdargs{tag}{--remove}.  
-\interaction{tag.remove}
-You can also modify a tag at any time, so that it identifies a
-different revision, by simply issuing a new \hgcmd{tag} command.
-You'll have to use the \hgopt{tag}{-f} option to tell Mercurial that
-you \emph{really} want to update the tag.
-\interaction{tag.replace}
-There will still be a permanent record of the previous identity of the
-tag, but Mercurial will no longer use it.  There's thus no penalty to
-tagging the wrong revision; all you have to do is turn around and tag
-the correct revision once you discover your error.
-
-Mercurial stores tags in a normal revision-controlled file in your
-repository.  If you've created any tags, you'll find them in a file
-named \sfilename{.hgtags}.  When you run the \hgcmd{tag} command,
-Mercurial modifies this file, then automatically commits the change to
-it.  This means that every time you run \hgcmd{tag}, you'll see a
-corresponding changeset in the output of \hgcmd{log}.
-\interaction{tag.tip}
-
-\subsection{Handling tag conflicts during a merge}
-
-You won't often need to care about the \sfilename{.hgtags} file, but
-it sometimes makes its presence known during a merge.  The format of
-the file is simple: it consists of a series of lines.  Each line
-starts with a changeset hash, followed by a space, followed by the
-name of a tag.
-
-If you're resolving a conflict in the \sfilename{.hgtags} file during
-a merge, there's one twist to modifying the \sfilename{.hgtags} file:
-when Mercurial is parsing the tags in a repository, it \emph{never}
-reads the working copy of the \sfilename{.hgtags} file.  Instead, it
-reads the \emph{most recently committed} revision of the file.
-
-An unfortunate consequence of this design is that you can't actually
-verify that your merged \sfilename{.hgtags} file is correct until
-\emph{after} you've committed a change.  So if you find yourself
-resolving a conflict on \sfilename{.hgtags} during a merge, be sure to
-run \hgcmd{tags} after you commit.  If it finds an error in the
-\sfilename{.hgtags} file, it will report the location of the error,
-which you can then fix and commit.  You should then run \hgcmd{tags}
-again, just to be sure that your fix is correct.
-
-\subsection{Tags and cloning}
-
-You may have noticed that the \hgcmd{clone} command has a
-\hgopt{clone}{-r} option that lets you clone an exact copy of the
-repository as of a particular changeset.  The new clone will not
-contain any project history that comes after the revision you
-specified.  This has an interaction with tags that can surprise the
-unwary.
-
-Recall that a tag is stored as a revision to the \sfilename{.hgtags}
-file, so that when you create a tag, the changeset in which it's
-recorded necessarily refers to an older changeset.  When you run
-\hgcmdargs{clone}{-r foo} to clone a repository as of tag
-\texttt{foo}, the new clone \emph{will not contain the history that
-  created the tag} that you used to clone the repository.  The result
-is that you'll get exactly the right subset of the project's history
-in the new repository, but \emph{not} the tag you might have expected.
-
-\subsection{When permanent tags are too much}
-
-Since Mercurial's tags are revision controlled and carried around with
-a project's history, everyone you work with will see the tags you
-create.  But giving names to revisions has uses beyond simply noting
-that revision \texttt{4237e45506ee} is really \texttt{v2.0.2}.  If
-you're trying to track down a subtle bug, you might want a tag to
-remind you of something like ``Anne saw the symptoms with this
-revision''.
-
-For cases like this, what you might want to use are \emph{local} tags.
-You can create a local tag with the \hgopt{tag}{-l} option to the
-\hgcmd{tag} command.  This will store the tag in a file called
-\sfilename{.hg/localtags}.  Unlike \sfilename{.hgtags},
-\sfilename{.hg/localtags} is not revision controlled.  Any tags you
-create using \hgopt{tag}{-l} remain strictly local to the repository
-you're currently working in.
-
-\section{The flow of changes---big picture vs. little}
-
-To return to the outline I sketched at the beginning of a chapter,
-let's think about a project that has multiple concurrent pieces of
-work under development at once.
-
-There might be a push for a new ``main'' release; a new minor bugfix
-release to the last main release; and an unexpected ``hot fix'' to an
-old release that is now in maintenance mode.
-
-The usual way people refer to these different concurrent directions of
-development is as ``branches''.  However, we've already seen numerous
-times that Mercurial treats \emph{all of history} as a series of
-branches and merges.  Really, what we have here is two ideas that are
-peripherally related, but which happen to share a name.
-\begin{itemize}
-\item ``Big picture'' branches represent the sweep of a project's
-  evolution; people give them names, and talk about them in
-  conversation.
-\item ``Little picture'' branches are artefacts of the day-to-day
-  activity of developing and merging changes.  They expose the
-  narrative of how the code was developed.
-\end{itemize}
-
-\section{Managing big-picture branches in repositories}
-
-The easiest way to isolate a ``big picture'' branch in Mercurial is in
-a dedicated repository.  If you have an existing shared
-repository---let's call it \texttt{myproject}---that reaches a ``1.0''
-milestone, you can start to prepare for future maintenance releases on
-top of version~1.0 by tagging the revision from which you prepared
-the~1.0 release.
-\interaction{branch-repo.tag}
-You can then clone a new shared \texttt{myproject-1.0.1} repository as
-of that tag.
-\interaction{branch-repo.clone}
-
-Afterwards, if someone needs to work on a bug fix that ought to go
-into an upcoming~1.0.1 minor release, they clone the
-\texttt{myproject-1.0.1} repository, make their changes, and push them
-back.
-\interaction{branch-repo.bugfix}
-Meanwhile, development for the next major release can continue,
-isolated and unabated, in the \texttt{myproject} repository.
-\interaction{branch-repo.new}
-
-\section{Don't repeat yourself: merging across branches}
-
-In many cases, if you have a bug to fix on a maintenance branch, the
-chances are good that the bug exists on your project's main branch
-(and possibly other maintenance branches, too).  It's a rare developer
-who wants to fix the same bug multiple times, so let's look at a few
-ways that Mercurial can help you to manage these bugfixes without
-duplicating your work.
-
-In the simplest instance, all you need to do is pull changes from your
-maintenance branch into your local clone of the target branch.
-\interaction{branch-repo.pull}
-You'll then need to merge the heads of the two branches, and push back
-to the main branch.
-\interaction{branch-repo.merge}
-
-\section{Naming branches within one repository}
-
-In most instances, isolating branches in repositories is the right
-approach.  Its simplicity makes it easy to understand; and so it's
-hard to make mistakes.  There's a one-to-one relationship between
-branches you're working in and directories on your system.  This lets
-you use normal (non-Mercurial-aware) tools to work on files within a
-branch/repository.
-
-If you're more in the ``power user'' category (\emph{and} your
-collaborators are too), there is an alternative way of handling
-branches that you can consider.  I've already mentioned the
-human-level distinction between ``small picture'' and ``big picture''
-branches.  While Mercurial works with multiple ``small picture''
-branches in a repository all the time (for example after you pull
-changes in, but before you merge them), it can \emph{also} work with
-multiple ``big picture'' branches.
-
-The key to working this way is that Mercurial lets you assign a
-persistent \emph{name} to a branch.  There always exists a branch
-named \texttt{default}.  Even before you start naming branches
-yourself, you can find traces of the \texttt{default} branch if you
-look for them.
-
-As an example, when you run the \hgcmd{commit} command, and it pops up
-your editor so that you can enter a commit message, look for a line
-that contains the text ``\texttt{HG: branch default}'' at the bottom.
-This is telling you that your commit will occur on the branch named
-\texttt{default}.
-
-To start working with named branches, use the \hgcmd{branches}
-command.  This command lists the named branches already present in
-your repository, telling you which changeset is the tip of each.
-\interaction{branch-named.branches}
-Since you haven't created any named branches yet, the only one that
-exists is \texttt{default}.
-
-To find out what the ``current'' branch is, run the \hgcmd{branch}
-command, giving it no arguments.  This tells you what branch the
-parent of the current changeset is on.
-\interaction{branch-named.branch}
-
-To create a new branch, run the \hgcmd{branch} command again.  This
-time, give it one argument: the name of the branch you want to create.
-\interaction{branch-named.create}
-
-After you've created a branch, you might wonder what effect the
-\hgcmd{branch} command has had.  What do the \hgcmd{status} and
-\hgcmd{tip} commands report?
-\interaction{branch-named.status}
-Nothing has changed in the working directory, and there's been no new
-history created.  As this suggests, running the \hgcmd{branch} command
-has no permanent effect; it only tells Mercurial what branch name to
-use the \emph{next} time you commit a changeset.
-
-When you commit a change, Mercurial records the name of the branch on
-which you committed.  Once you've switched from the \texttt{default}
-branch to another and committed, you'll see the name of the new branch
-show up in the output of \hgcmd{log}, \hgcmd{tip}, and other commands
-that display the same kind of output.
-\interaction{branch-named.commit}
-The \hgcmd{log}-like commands will print the branch name of every
-changeset that's not on the \texttt{default} branch.  As a result, if
-you never use named branches, you'll never see this information.
-
-Once you've named a branch and committed a change with that name,
-every subsequent commit that descends from that change will inherit
-the same branch name.  You can change the name of a branch at any
-time, using the \hgcmd{branch} command.  
-\interaction{branch-named.rebranch}
-In practice, this is something you won't do very often, as branch
-names tend to have fairly long lifetimes.  (This isn't a rule, just an
-observation.)
-
-\section{Dealing with multiple named branches in a repository}
-
-If you have more than one named branch in a repository, Mercurial will
-remember the branch that your working directory on when you start a
-command like \hgcmd{update} or \hgcmdargs{pull}{-u}.  It will update
-the working directory to the tip of this branch, no matter what the
-``repo-wide'' tip is.  To update to a revision that's on a different
-named branch, you may need to use the \hgopt{update}{-C} option to
-\hgcmd{update}.
-
-This behaviour is a little subtle, so let's see it in action.  First,
-let's remind ourselves what branch we're currently on, and what
-branches are in our repository.
-\interaction{branch-named.parents}
-We're on the \texttt{bar} branch, but there also exists an older
-\hgcmd{foo} branch.
-
-We can \hgcmd{update} back and forth between the tips of the
-\texttt{foo} and \texttt{bar} branches without needing to use the
-\hgopt{update}{-C} option, because this only involves going backwards
-and forwards linearly through our change history.
-\interaction{branch-named.update-switchy}
-
-If we go back to the \texttt{foo} branch and then run \hgcmd{update},
-it will keep us on \texttt{foo}, not move us to the tip of
-\texttt{bar}.
-\interaction{branch-named.update-nothing}
-
-Committing a new change on the \texttt{foo} branch introduces a new
-head.
-\interaction{branch-named.foo-commit}
-
-\section{Branch names and merging}
-
-As you've probably noticed, merges in Mercurial are not symmetrical.
-Let's say our repository has two heads, 17 and 23.  If I
-\hgcmd{update} to 17 and then \hgcmd{merge} with 23, Mercurial records
-17 as the first parent of the merge, and 23 as the second.  Whereas if
-I \hgcmd{update} to 23 and then \hgcmd{merge} with 17, it records 23
-as the first parent, and 17 as the second.
-
-This affects Mercurial's choice of branch name when you merge.  After
-a merge, Mercurial will retain the branch name of the first parent
-when you commit the result of the merge.  If your first parent's
-branch name is \texttt{foo}, and you merge with \texttt{bar}, the
-branch name will still be \texttt{foo} after you merge.
-
-It's not unusual for a repository to contain multiple heads, each with
-the same branch name.  Let's say I'm working on the \texttt{foo}
-branch, and so are you.  We commit different changes; I pull your
-changes; I now have two heads, each claiming to be on the \texttt{foo}
-branch.  The result of a merge will be a single head on the
-\texttt{foo} branch, as you might hope.
-
-But if I'm working on the \texttt{bar} branch, and I merge work from
-the \texttt{foo} branch, the result will remain on the \texttt{bar}
-branch.
-\interaction{branch-named.merge}
-
-To give a more concrete example, if I'm working on the
-\texttt{bleeding-edge} branch, and I want to bring in the latest fixes
-from the \texttt{stable} branch, Mercurial will choose the ``right''
-(\texttt{bleeding-edge}) branch name when I pull and merge from
-\texttt{stable}.
-
-\section{Branch naming is generally useful}
-
-You shouldn't think of named branches as applicable only to situations
-where you have multiple long-lived branches cohabiting in a single
-repository.  They're very useful even in the one-branch-per-repository
-case.  
-
-In the simplest case, giving a name to each branch gives you a
-permanent record of which branch a changeset originated on.  This
-gives you more context when you're trying to follow the history of a
-long-lived branchy project.
-
-If you're working with shared repositories, you can set up a
-\hook{pretxnchangegroup} hook on each that will block incoming changes
-that have the ``wrong'' branch name.  This provides a simple, but
-effective, defence against people accidentally pushing changes from a
-``bleeding edge'' branch to a ``stable'' branch.  Such a hook might
-look like this inside the shared repo's \hgrc.
-\begin{codesample2}
-  [hooks]
-  pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch
-\end{codesample2}
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch00-preface.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,67 @@
+\chapter*{Preface}
+\addcontentsline{toc}{chapter}{Preface}
+\label{chap:preface}
+
+Distributed revision control is a relatively new territory, and has
+thus far grown due to people's willingness to strike out into
+ill-charted territory.
+
+I am writing a book about distributed revision control because I
+believe that it is an important subject that deserves a field guide.
+I chose to write about Mercurial because it is the easiest tool to
+learn the terrain with, and yet it scales to the demands of real,
+challenging environments where many other revision control tools fail.
+
+\section{This book is a work in progress}
+
+I am releasing this book while I am still writing it, in the hope that
+it will prove useful to others.  I also hope that readers will
+contribute as they see fit.
+
+\section{About the examples in this book}
+
+This book takes an unusual approach to code samples.  Every example is
+``live''---each one is actually the result of a shell script that
+executes the Mercurial commands you see.  Every time an image of the
+book is built from its sources, all the example scripts are
+automatically run, and their current results compared against their
+expected results.
+
+The advantage of this approach is that the examples are always
+accurate; they describe \emph{exactly} the behaviour of the version of
+Mercurial that's mentioned at the front of the book.  If I update the
+version of Mercurial that I'm documenting, and the output of some
+command changes, the build fails.
+
+There is a small disadvantage to this approach, which is that the
+dates and times you'll see in examples tend to be ``squashed''
+together in a way that they wouldn't be if the same commands were
+being typed by a human.  Where a human can issue no more than one
+command every few seconds, with any resulting timestamps
+correspondingly spread out, my automated example scripts run many
+commands in one second.
+
+As an instance of this, several consecutive commits in an example can
+show up as having occurred during the same second.  You can see this
+occur in the \hgext{bisect} example in section~\ref{sec:undo:bisect},
+for instance.
+
+So when you're reading examples, don't place too much weight on the
+dates or times you see in the output of commands.  But \emph{do} be
+confident that the behaviour you're seeing is consistent and
+reproducible.
+
+\section{Colophon---this book is Free}
+
+This book is licensed under the Open Publication License, and is
+produced entirely using Free Software tools.  It is typeset with
+\LaTeX{}; illustrations are drawn and rendered with
+\href{http://www.inkscape.org/}{Inkscape}.
+
+The complete source code for this book is published as a Mercurial
+repository, at \url{http://hg.serpentine.com/mercurial/book}.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch01-intro.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,560 @@
+\chapter{Introduction}
+\label{chap:intro}
+
+\section{About revision control}
+
+Revision control is the process of managing multiple versions of a
+piece of information.  In its simplest form, this is something that
+many people do by hand: every time you modify a file, save it under a
+new name that contains a number, each one higher than the number of
+the preceding version.
+
+Manually managing multiple versions of even a single file is an
+error-prone task, though, so software tools to help automate this
+process have long been available.  The earliest automated revision
+control tools were intended to help a single user to manage revisions
+of a single file.  Over the past few decades, the scope of revision
+control tools has expanded greatly; they now manage multiple files,
+and help multiple people to work together.  The best modern revision
+control tools have no problem coping with thousands of people working
+together on projects that consist of hundreds of thousands of files.
+
+\subsection{Why use revision control?}
+
+There are a number of reasons why you or your team might want to use
+an automated revision control tool for a project.
+\begin{itemize}
+\item It will track the history and evolution of your project, so you
+  don't have to.  For every change, you'll have a log of \emph{who}
+  made it; \emph{why} they made it; \emph{when} they made it; and
+  \emph{what} the change was.
+\item When you're working with other people, revision control software
+  makes it easier for you to collaborate.  For example, when people
+  more or less simultaneously make potentially incompatible changes,
+  the software will help you to identify and resolve those conflicts.
+\item It can help you to recover from mistakes.  If you make a change
+  that later turns out to be in error, you can revert to an earlier
+  version of one or more files.  In fact, a \emph{really} good
+  revision control tool will even help you to efficiently figure out
+  exactly when a problem was introduced (see
+  section~\ref{sec:undo:bisect} for details).
+\item It will help you to work simultaneously on, and manage the drift
+  between, multiple versions of your project.
+\end{itemize}
+Most of these reasons are equally valid---at least in theory---whether
+you're working on a project by yourself, or with a hundred other
+people.
+
+A key question about the practicality of revision control at these two
+different scales (``lone hacker'' and ``huge team'') is how its
+\emph{benefits} compare to its \emph{costs}.  A revision control tool
+that's difficult to understand or use is going to impose a high cost.
+
+A five-hundred-person project is likely to collapse under its own
+weight almost immediately without a revision control tool and process.
+In this case, the cost of using revision control might hardly seem
+worth considering, since \emph{without} it, failure is almost
+guaranteed.
+
+On the other hand, a one-person ``quick hack'' might seem like a poor
+place to use a revision control tool, because surely the cost of using
+one must be close to the overall cost of the project.  Right?
+
+Mercurial uniquely supports \emph{both} of these scales of
+development.  You can learn the basics in just a few minutes, and due
+to its low overhead, you can apply revision control to the smallest of
+projects with ease.  Its simplicity means you won't have a lot of
+abstruse concepts or command sequences competing for mental space with
+whatever you're \emph{really} trying to do.  At the same time,
+Mercurial's high performance and peer-to-peer nature let you scale
+painlessly to handle large projects.
+
+No revision control tool can rescue a poorly run project, but a good
+choice of tools can make a huge difference to the fluidity with which
+you can work on a project.
+
+\subsection{The many names of revision control}
+
+Revision control is a diverse field, so much so that it doesn't
+actually have a single name or acronym.  Here are a few of the more
+common names and acronyms you'll encounter:
+\begin{itemize}
+\item Revision control (RCS)
+\item Software configuration management (SCM), or configuration management
+\item Source code management
+\item Source code control, or source control
+\item Version control (VCS)
+\end{itemize}
+Some people claim that these terms actually have different meanings,
+but in practice they overlap so much that there's no agreed or even
+useful way to tease them apart.
+
+\section{A short history of revision control}
+
+The best known of the old-time revision control tools is SCCS (Source
+Code Control System), which Marc Rochkind wrote at Bell Labs, in the
+early 1970s.  SCCS operated on individual files, and required every
+person working on a project to have access to a shared workspace on a
+single system.  Only one person could modify a file at any time;
+arbitration for access to files was via locks.  It was common for
+people to lock files, and later forget to unlock them, preventing
+anyone else from modifying those files without the help of an
+administrator.  
+
+Walter Tichy developed a free alternative to SCCS in the early 1980s;
+he called his program RCS (Revison Control System).  Like SCCS, RCS
+required developers to work in a single shared workspace, and to lock
+files to prevent multiple people from modifying them simultaneously.
+
+Later in the 1980s, Dick Grune used RCS as a building block for a set
+of shell scripts he initially called cmt, but then renamed to CVS
+(Concurrent Versions System).  The big innovation of CVS was that it
+let developers work simultaneously and somewhat independently in their
+own personal workspaces.  The personal workspaces prevented developers
+from stepping on each other's toes all the time, as was common with
+SCCS and RCS.  Each developer had a copy of every project file, and
+could modify their copies independently.  They had to merge their
+edits prior to committing changes to the central repository.
+
+Brian Berliner took Grune's original scripts and rewrote them in~C,
+releasing in 1989 the code that has since developed into the modern
+version of CVS.  CVS subsequently acquired the ability to operate over
+a network connection, giving it a client/server architecture.  CVS's
+architecture is centralised; only the server has a copy of the history
+of the project.  Client workspaces just contain copies of recent
+versions of the project's files, and a little metadata to tell them
+where the server is.  CVS has been enormously successful; it is
+probably the world's most widely used revision control system.
+
+In the early 1990s, Sun Microsystems developed an early distributed
+revision control system, called TeamWare.  A TeamWare workspace
+contains a complete copy of the project's history.  TeamWare has no
+notion of a central repository.  (CVS relied upon RCS for its history
+storage; TeamWare used SCCS.)
+
+As the 1990s progressed, awareness grew of a number of problems with
+CVS.  It records simultaneous changes to multiple files individually,
+instead of grouping them together as a single logically atomic
+operation.  It does not manage its file hierarchy well; it is easy to
+make a mess of a repository by renaming files and directories.  Worse,
+its source code is difficult to read and maintain, which made the
+``pain level'' of fixing these architectural problems prohibitive.
+
+In 2001, Jim Blandy and Karl Fogel, two developers who had worked on
+CVS, started a project to replace it with a tool that would have a
+better architecture and cleaner code.  The result, Subversion, does
+not stray from CVS's centralised client/server model, but it adds
+multi-file atomic commits, better namespace management, and a number
+of other features that make it a generally better tool than CVS.
+Since its initial release, it has rapidly grown in popularity.
+
+More or less simultaneously, Graydon Hoare began working on an
+ambitious distributed revision control system that he named Monotone.
+While Monotone addresses many of CVS's design flaws and has a
+peer-to-peer architecture, it goes beyond earlier (and subsequent)
+revision control tools in a number of innovative ways.  It uses
+cryptographic hashes as identifiers, and has an integral notion of
+``trust'' for code from different sources.
+
+Mercurial began life in 2005.  While a few aspects of its design are
+influenced by Monotone, Mercurial focuses on ease of use, high
+performance, and scalability to very large projects.
+
+\section{Trends in revision control}
+
+There has been an unmistakable trend in the development and use of
+revision control tools over the past four decades, as people have
+become familiar with the capabilities of their tools and constrained
+by their limitations.
+
+The first generation began by managing single files on individual
+computers.  Although these tools represented a huge advance over
+ad-hoc manual revision control, their locking model and reliance on a
+single computer limited them to small, tightly-knit teams.
+
+The second generation loosened these constraints by moving to
+network-centered architectures, and managing entire projects at a
+time.  As projects grew larger, they ran into new problems.  With
+clients needing to talk to servers very frequently, server scaling
+became an issue for large projects.  An unreliable network connection
+could prevent remote users from being able to talk to the server at
+all.  As open source projects started making read-only access
+available anonymously to anyone, people without commit privileges
+found that they could not use the tools to interact with a project in
+a natural way, as they could not record their changes.
+
+The current generation of revision control tools is peer-to-peer in
+nature.  All of these systems have dropped the dependency on a single
+central server, and allow people to distribute their revision control
+data to where it's actually needed.  Collaboration over the Internet
+has moved from constrained by technology to a matter of choice and
+consensus.  Modern tools can operate offline indefinitely and
+autonomously, with a network connection only needed when syncing
+changes with another repository.
+
+\section{A few of the advantages of distributed revision control}
+
+Even though distributed revision control tools have for several years
+been as robust and usable as their previous-generation counterparts,
+people using older tools have not yet necessarily woken up to their
+advantages.  There are a number of ways in which distributed tools
+shine relative to centralised ones.
+
+For an individual developer, distributed tools are almost always much
+faster than centralised tools.  This is for a simple reason: a
+centralised tool needs to talk over the network for many common
+operations, because most metadata is stored in a single copy on the
+central server.  A distributed tool stores all of its metadata
+locally.  All else being equal, talking over the network adds overhead
+to a centralised tool.  Don't underestimate the value of a snappy,
+responsive tool: you're going to spend a lot of time interacting with
+your revision control software.
+
+Distributed tools are indifferent to the vagaries of your server
+infrastructure, again because they replicate metadata to so many
+locations.  If you use a centralised system and your server catches
+fire, you'd better hope that your backup media are reliable, and that
+your last backup was recent and actually worked.  With a distributed
+tool, you have many backups available on every contributor's computer.
+
+The reliability of your network will affect distributed tools far less
+than it will centralised tools.  You can't even use a centralised tool
+without a network connection, except for a few highly constrained
+commands.  With a distributed tool, if your network connection goes
+down while you're working, you may not even notice.  The only thing
+you won't be able to do is talk to repositories on other computers,
+something that is relatively rare compared with local operations.  If
+you have a far-flung team of collaborators, this may be significant.
+
+\subsection{Advantages for open source projects}
+
+If you take a shine to an open source project and decide that you
+would like to start hacking on it, and that project uses a distributed
+revision control tool, you are at once a peer with the people who
+consider themselves the ``core'' of that project.  If they publish
+their repositories, you can immediately copy their project history,
+start making changes, and record your work, using the same tools in
+the same ways as insiders.  By contrast, with a centralised tool, you
+must use the software in a ``read only'' mode unless someone grants
+you permission to commit changes to their central server.  Until then,
+you won't be able to record changes, and your local modifications will
+be at risk of corruption any time you try to update your client's view
+of the repository.
+
+\subsubsection{The forking non-problem}
+
+It has been suggested that distributed revision control tools pose
+some sort of risk to open source projects because they make it easy to
+``fork'' the development of a project.  A fork happens when there are
+differences in opinion or attitude between groups of developers that
+cause them to decide that they can't work together any longer.  Each
+side takes a more or less complete copy of the project's source code,
+and goes off in its own direction.
+
+Sometimes the camps in a fork decide to reconcile their differences.
+With a centralised revision control system, the \emph{technical}
+process of reconciliation is painful, and has to be performed largely
+by hand.  You have to decide whose revision history is going to
+``win'', and graft the other team's changes into the tree somehow.
+This usually loses some or all of one side's revision history.
+
+What distributed tools do with respect to forking is they make forking
+the \emph{only} way to develop a project.  Every single change that
+you make is potentially a fork point.  The great strength of this
+approach is that a distributed revision control tool has to be really
+good at \emph{merging} forks, because forks are absolutely
+fundamental: they happen all the time.  
+
+If every piece of work that everybody does, all the time, is framed in
+terms of forking and merging, then what the open source world refers
+to as a ``fork'' becomes \emph{purely} a social issue.  If anything,
+distributed tools \emph{lower} the likelihood of a fork:
+\begin{itemize}
+\item They eliminate the social distinction that centralised tools
+  impose: that between insiders (people with commit access) and
+  outsiders (people without).
+\item They make it easier to reconcile after a social fork, because
+  all that's involved from the perspective of the revision control
+  software is just another merge.
+\end{itemize}
+
+Some people resist distributed tools because they want to retain tight
+control over their projects, and they believe that centralised tools
+give them this control.  However, if you're of this belief, and you
+publish your CVS or Subversion repositories publically, there are
+plenty of tools available that can pull out your entire project's
+history (albeit slowly) and recreate it somewhere that you don't
+control.  So while your control in this case is illusory, you are
+forgoing the ability to fluidly collaborate with whatever people feel
+compelled to mirror and fork your history.
+
+\subsection{Advantages for commercial projects}
+
+Many commercial projects are undertaken by teams that are scattered
+across the globe.  Contributors who are far from a central server will
+see slower command execution and perhaps less reliability.  Commercial
+revision control systems attempt to ameliorate these problems with
+remote-site replication add-ons that are typically expensive to buy
+and cantankerous to administer.  A distributed system doesn't suffer
+from these problems in the first place.  Better yet, you can easily
+set up multiple authoritative servers, say one per site, so that
+there's no redundant communication between repositories over expensive
+long-haul network links.
+
+Centralised revision control systems tend to have relatively low
+scalability.  It's not unusual for an expensive centralised system to
+fall over under the combined load of just a few dozen concurrent
+users.  Once again, the typical response tends to be an expensive and
+clunky replication facility.  Since the load on a central server---if
+you have one at all---is many times lower with a distributed
+tool (because all of the data is replicated everywhere), a single
+cheap server can handle the needs of a much larger team, and
+replication to balance load becomes a simple matter of scripting.
+
+If you have an employee in the field, troubleshooting a problem at a
+customer's site, they'll benefit from distributed revision control.
+The tool will let them generate custom builds, try different fixes in
+isolation from each other, and search efficiently through history for
+the sources of bugs and regressions in the customer's environment, all
+without needing to connect to your company's network.
+
+\section{Why choose Mercurial?}
+
+Mercurial has a unique set of properties that make it a particularly
+good choice as a revision control system.
+\begin{itemize}
+\item It is easy to learn and use.
+\item It is lightweight.
+\item It scales excellently.
+\item It is easy to customise.
+\end{itemize}
+
+If you are at all familiar with revision control systems, you should
+be able to get up and running with Mercurial in less than five
+minutes.  Even if not, it will take no more than a few minutes
+longer.  Mercurial's command and feature sets are generally uniform
+and consistent, so you can keep track of a few general rules instead
+of a host of exceptions.
+
+On a small project, you can start working with Mercurial in moments.
+Creating new changes and branches; transferring changes around
+(whether locally or over a network); and history and status operations
+are all fast.  Mercurial attempts to stay nimble and largely out of
+your way by combining low cognitive overhead with blazingly fast
+operations.
+
+The usefulness of Mercurial is not limited to small projects: it is
+used by projects with hundreds to thousands of contributors, each
+containing tens of thousands of files and hundreds of megabytes of
+source code.
+
+If the core functionality of Mercurial is not enough for you, it's
+easy to build on.  Mercurial is well suited to scripting tasks, and
+its clean internals and implementation in Python make it easy to add
+features in the form of extensions.  There are a number of popular and
+useful extensions already available, ranging from helping to identify
+bugs to improving performance.
+
+\section{Mercurial compared with other tools}
+
+Before you read on, please understand that this section necessarily
+reflects my own experiences, interests, and (dare I say it) biases.  I
+have used every one of the revision control tools listed below, in
+most cases for several years at a time.
+
+
+\subsection{Subversion}
+
+Subversion is a popular revision control tool, developed to replace
+CVS.  It has a centralised client/server architecture.
+
+Subversion and Mercurial have similarly named commands for performing
+the same operations, so if you're familiar with one, it is easy to
+learn to use the other.  Both tools are portable to all popular
+operating systems.
+
+Prior to version 1.5, Subversion had no useful support for merges.
+At the time of writing, its merge tracking capability is new, and known to be
+\href{http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword}{complicated and buggy}.
+
+Mercurial has a substantial performance advantage over Subversion on
+every revision control operation I have benchmarked.  I have measured
+its advantage as ranging from a factor of two to a factor of six when
+compared with Subversion~1.4.3's \emph{ra\_local} file store, which is
+the fastest access method available.  In more realistic deployments
+involving a network-based store, Subversion will be at a substantially
+larger disadvantage.  Because many Subversion commands must talk to
+the server and Subversion does not have useful replication facilities,
+server capacity and network bandwidth become bottlenecks for modestly
+large projects.
+
+Additionally, Subversion incurs substantial storage overhead to avoid
+network transactions for a few common operations, such as finding
+modified files (\texttt{status}) and displaying modifications against
+the current revision (\texttt{diff}).  As a result, a Subversion
+working copy is often the same size as, or larger than, a Mercurial
+repository and working directory, even though the Mercurial repository
+contains a complete history of the project.
+
+Subversion is widely supported by third party tools.  Mercurial
+currently lags considerably in this area.  This gap is closing,
+however, and indeed some of Mercurial's GUI tools now outshine their
+Subversion equivalents.  Like Mercurial, Subversion has an excellent
+user manual.
+
+Because Subversion doesn't store revision history on the client, it is
+well suited to managing projects that deal with lots of large, opaque
+binary files.  If you check in fifty revisions to an incompressible
+10MB file, Subversion's client-side space usage stays constant The
+space used by any distributed SCM will grow rapidly in proportion to
+the number of revisions, because the differences between each revision
+are large.
+
+In addition, it's often difficult or, more usually, impossible to
+merge different versions of a binary file.  Subversion's ability to
+let a user lock a file, so that they temporarily have the exclusive
+right to commit changes to it, can be a significant advantage to a
+project where binary files are widely used.
+
+Mercurial can import revision history from a Subversion repository.
+It can also export revision history to a Subversion repository.  This
+makes it easy to ``test the waters'' and use Mercurial and Subversion
+in parallel before deciding to switch.  History conversion is
+incremental, so you can perform an initial conversion, then small
+additional conversions afterwards to bring in new changes.
+
+
+\subsection{Git}
+
+Git is a distributed revision control tool that was developed for
+managing the Linux kernel source tree.  Like Mercurial, its early
+design was somewhat influenced by Monotone.
+
+Git has a very large command set, with version~1.5.0 providing~139
+individual commands.  It has something of a reputation for being
+difficult to learn.  Compared to Git, Mercurial has a strong focus on
+simplicity.
+
+In terms of performance, Git is extremely fast.  In several cases, it
+is faster than Mercurial, at least on Linux, while Mercurial performs
+better on other operations.  However, on Windows, the performance and
+general level of support that Git provides is, at the time of writing,
+far behind that of Mercurial.
+
+While a Mercurial repository needs no maintenance, a Git repository
+requires frequent manual ``repacks'' of its metadata.  Without these,
+performance degrades, while space usage grows rapidly.  A server that
+contains many Git repositories that are not rigorously and frequently
+repacked will become heavily disk-bound during backups, and there have
+been instances of daily backups taking far longer than~24 hours as a
+result.  A freshly packed Git repository is slightly smaller than a
+Mercurial repository, but an unpacked repository is several orders of
+magnitude larger.
+
+The core of Git is written in C.  Many Git commands are implemented as
+shell or Perl scripts, and the quality of these scripts varies widely.
+I have encountered several instances where scripts charged along
+blindly in the presence of errors that should have been fatal.
+
+Mercurial can import revision history from a Git repository.
+
+
+\subsection{CVS}
+
+CVS is probably the most widely used revision control tool in the
+world.  Due to its age and internal untidiness, it has been only
+lightly maintained for many years.
+
+It has a centralised client/server architecture.  It does not group
+related file changes into atomic commits, making it easy for people to
+``break the build'': one person can successfully commit part of a
+change and then be blocked by the need for a merge, causing other
+people to see only a portion of the work they intended to do.  This
+also affects how you work with project history.  If you want to see
+all of the modifications someone made as part of a task, you will need
+to manually inspect the descriptions and timestamps of the changes
+made to each file involved (if you even know what those files were).
+
+CVS has a muddled notion of tags and branches that I will not attempt
+to even describe.  It does not support renaming of files or
+directories well, making it easy to corrupt a repository.  It has
+almost no internal consistency checking capabilities, so it is usually
+not even possible to tell whether or how a repository is corrupt.  I
+would not recommend CVS for any project, existing or new.
+
+Mercurial can import CVS revision history.  However, there are a few
+caveats that apply; these are true of every other revision control
+tool's CVS importer, too.  Due to CVS's lack of atomic changes and
+unversioned filesystem hierarchy, it is not possible to reconstruct
+CVS history completely accurately; some guesswork is involved, and
+renames will usually not show up.  Because a lot of advanced CVS
+administration has to be done by hand and is hence error-prone, it's
+common for CVS importers to run into multiple problems with corrupted
+repositories (completely bogus revision timestamps and files that have
+remained locked for over a decade are just two of the less interesting
+problems I can recall from personal experience).
+
+Mercurial can import revision history from a CVS repository.
+
+
+\subsection{Commercial tools}
+
+Perforce has a centralised client/server architecture, with no
+client-side caching of any data.  Unlike modern revision control
+tools, Perforce requires that a user run a command to inform the
+server about every file they intend to edit.
+
+The performance of Perforce is quite good for small teams, but it
+falls off rapidly as the number of users grows beyond a few dozen.
+Modestly large Perforce installations require the deployment of
+proxies to cope with the load their users generate.
+
+
+\subsection{Choosing a revision control tool}
+
+With the exception of CVS, all of the tools listed above have unique
+strengths that suit them to particular styles of work.  There is no
+single revision control tool that is best in all situations.
+
+As an example, Subversion is a good choice for working with frequently
+edited binary files, due to its centralised nature and support for
+file locking.
+
+I personally find Mercurial's properties of simplicity, performance,
+and good merge support to be a compelling combination that has served
+me well for several years.
+
+
+\section{Switching from another tool to Mercurial}
+
+Mercurial is bundled with an extension named \hgext{convert}, which
+can incrementally import revision history from several other revision
+control tools.  By ``incremental'', I mean that you can convert all of
+a project's history to date in one go, then rerun the conversion later
+to obtain new changes that happened after the initial conversion.
+
+The revision control tools supported by \hgext{convert} are as
+follows:
+\begin{itemize}
+\item Subversion
+\item CVS
+\item Git
+\item Darcs
+\end{itemize}
+
+In addition, \hgext{convert} can export changes from Mercurial to
+Subversion.  This makes it possible to try Subversion and Mercurial in
+parallel before committing to a switchover, without risking the loss
+of any work.
+
+The \hgxcmd{conver}{convert} command is easy to use.  Simply point it
+at the path or URL of the source repository, optionally give it the
+name of the destination repository, and it will start working.  After
+the initial conversion, just run the same command again to import new
+changes.
+
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch01-intro.xml	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,680 @@
+<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
+
+<chapter>
+  <title>Introduction</title>
+  <para>\label{chap:intro}</para>
+
+  <sect1>
+    <title>About revision control</title>
+
+    <para>Revision control is the process of managing multiple
+      versions of a piece of information.  In its simplest form, this
+      is something that many people do by hand: every time you modify
+      a file, save it under a new name that contains a number, each
+      one higher than the number of the preceding version.</para>
+
+    <para>Manually managing multiple versions of even a single file is
+      an error-prone task, though, so software tools to help automate
+      this process have long been available.  The earliest automated
+      revision control tools were intended to help a single user to
+      manage revisions of a single file.  Over the past few decades,
+      the scope of revision control tools has expanded greatly; they
+      now manage multiple files, and help multiple people to work
+      together.  The best modern revision control tools have no
+      problem coping with thousands of people working together on
+      projects that consist of hundreds of thousands of files.</para>
+
+    <sect2>
+      <title>Why use revision control?</title>
+
+      <para>There are a number of reasons why you or your team might
+	want to use an automated revision control tool for a
+	project.</para>
+      <itemizedlist>
+	<listitem><para>It will track the history and evolution of
+	    your project, so you don't have to.  For every change,
+	    you'll have a log of <emphasis>who</emphasis> made it;
+	    <emphasis>why</emphasis> they made it;
+	    <emphasis>when</emphasis> they made it; and
+	    <emphasis>what</emphasis> the change
+	    was.</para></listitem>
+	<listitem><para>When you're working with other people,
+	    revision control software makes it easier for you to
+	    collaborate.  For example, when people more or less
+	    simultaneously make potentially incompatible changes, the
+	    software will help you to identify and resolve those
+	    conflicts.</para></listitem>
+	<listitem><para>It can help you to recover from mistakes.  If
+	    you make a change that later turns out to be in error, you
+	    can revert to an earlier version of one or more files.  In
+	    fact, a <emphasis>really</emphasis> good revision control
+	    tool will even help you to efficiently figure out exactly
+	    when a problem was introduced (see section <xref
+	      id="sec:undo:bisect"/> for details).</para></listitem>
+	<listitem><para>It will help you to work simultaneously on,
+	    and manage the drift between, multiple versions of your
+	    project.</para></listitem></itemizedlist>
+      <para>Most of these reasons are equally valid---at least in
+	theory---whether you're working on a project by yourself, or
+	with a hundred other people.</para>
+
+      <para>A key question about the practicality of revision control
+	at these two different scales (<quote>lone hacker</quote> and
+	<quote>huge team</quote>) is how its
+	<emphasis>benefits</emphasis> compare to its
+	<emphasis>costs</emphasis>.  A revision control tool that's
+	difficult to understand or use is going to impose a high
+	cost.</para>
+
+      <para>A five-hundred-person project is likely to collapse under
+	its own weight almost immediately without a revision control
+	tool and process. In this case, the cost of using revision
+	control might hardly seem worth considering, since
+	<emphasis>without</emphasis> it, failure is almost
+	guaranteed.</para>
+
+      <para>On the other hand, a one-person <quote>quick hack</quote>
+	might seem like a poor place to use a revision control tool,
+	because surely the cost of using one must be close to the
+	overall cost of the project.  Right?</para>
+
+      <para>Mercurial uniquely supports <emphasis>both</emphasis> of
+	these scales of development.  You can learn the basics in just
+	a few minutes, and due to its low overhead, you can apply
+	revision control to the smallest of projects with ease.  Its
+	simplicity means you won't have a lot of abstruse concepts or
+	command sequences competing for mental space with whatever
+	you're <emphasis>really</emphasis> trying to do.  At the same
+	time, Mercurial's high performance and peer-to-peer nature let
+	you scale painlessly to handle large projects.</para>
+
+      <para>No revision control tool can rescue a poorly run project,
+	but a good choice of tools can make a huge difference to the
+	fluidity with which you can work on a project.</para>
+
+    </sect2>
+    <sect2>
+      <title>The many names of revision control</title>
+
+      <para>Revision control is a diverse field, so much so that it
+	doesn't actually have a single name or acronym.  Here are a
+	few of the more common names and acronyms you'll
+	encounter:</para>
+      <itemizedlist>
+	<listitem><para>Revision control (RCS)</para></listitem>
+	<listitem><para>Software configuration management (SCM), or
+	    configuration management</para></listitem>
+	<listitem><para>Source code management</para></listitem>
+	<listitem><para>Source code control, or source
+	    control</para></listitem>
+	<listitem><para>Version control
+	    (VCS)</para></listitem></itemizedlist>
+      <para>Some people claim that these terms actually have different
+	meanings, but in practice they overlap so much that there's no
+	agreed or even useful way to tease them apart.</para>
+
+    </sect2>
+  </sect1>
+  <sect1>
+    <title>A short history of revision control</title>
+
+    <para>The best known of the old-time revision control tools is
+      SCCS (Source Code Control System), which Marc Rochkind wrote at
+      Bell Labs, in the early 1970s.  SCCS operated on individual
+      files, and required every person working on a project to have
+      access to a shared workspace on a single system.  Only one
+      person could modify a file at any time; arbitration for access
+      to files was via locks.  It was common for people to lock files,
+      and later forget to unlock them, preventing anyone else from
+      modifying those files without the help of an
+      administrator.</para>
+
+    <para>Walter Tichy developed a free alternative to SCCS in the
+      early 1980s; he called his program RCS (Revison Control System).
+      Like SCCS, RCS required developers to work in a single shared
+      workspace, and to lock files to prevent multiple people from
+      modifying them simultaneously.</para>
+
+    <para>Later in the 1980s, Dick Grune used RCS as a building block
+      for a set of shell scripts he initially called cmt, but then
+      renamed to CVS (Concurrent Versions System).  The big innovation
+      of CVS was that it let developers work simultaneously and
+      somewhat independently in their own personal workspaces.  The
+      personal workspaces prevented developers from stepping on each
+      other's toes all the time, as was common with SCCS and RCS. Each
+      developer had a copy of every project file, and could modify
+      their copies independently.  They had to merge their edits prior
+      to committing changes to the central repository.</para>
+
+    <para>Brian Berliner took Grune's original scripts and rewrote
+      them in C, releasing in 1989 the code that has since developed
+      into the modern version of CVS.  CVS subsequently acquired the
+      ability to operate over a network connection, giving it a
+      client/server architecture.  CVS's architecture is centralised;
+      only the server has a copy of the history of the project. Client
+      workspaces just contain copies of recent versions of the
+      project's files, and a little metadata to tell them where the
+      server is.  CVS has been enormously successful; it is probably
+      the world's most widely used revision control system.</para>
+
+    <para>In the early 1990s, Sun Microsystems developed an early
+      distributed revision control system, called TeamWare.  A
+      TeamWare workspace contains a complete copy of the project's
+      history.  TeamWare has no notion of a central repository.  (CVS
+      relied upon RCS for its history storage; TeamWare used
+      SCCS.)</para>
+
+    <para>As the 1990s progressed, awareness grew of a number of
+      problems with CVS.  It records simultaneous changes to multiple
+      files individually, instead of grouping them together as a
+      single logically atomic operation.  It does not manage its file
+      hierarchy well; it is easy to make a mess of a repository by
+      renaming files and directories.  Worse, its source code is
+      difficult to read and maintain, which made the <quote>pain
+	level</quote> of fixing these architectural problems
+      prohibitive.</para>
+
+    <para>In 2001, Jim Blandy and Karl Fogel, two developers who had
+      worked on CVS, started a project to replace it with a tool that
+      would have a better architecture and cleaner code.  The result,
+      Subversion, does not stray from CVS's centralised client/server
+      model, but it adds multi-file atomic commits, better namespace
+      management, and a number of other features that make it a
+      generally better tool than CVS. Since its initial release, it
+      has rapidly grown in popularity.</para>
+
+    <para>More or less simultaneously, Graydon Hoare began working on
+      an ambitious distributed revision control system that he named
+      Monotone. While Monotone addresses many of CVS's design flaws
+      and has a peer-to-peer architecture, it goes beyond earlier (and
+      subsequent) revision control tools in a number of innovative
+      ways.  It uses cryptographic hashes as identifiers, and has an
+      integral notion of <quote>trust</quote> for code from different
+      sources.</para>
+
+    <para>Mercurial began life in 2005.  While a few aspects of its
+      design are influenced by Monotone, Mercurial focuses on ease of
+      use, high performance, and scalability to very large
+      projects.</para>
+
+  </sect1>
+  <sect1>
+    <title>Trends in revision control</title>
+
+    <para>There has been an unmistakable trend in the development and
+      use of revision control tools over the past four decades, as
+      people have become familiar with the capabilities of their tools
+      and constrained by their limitations.</para>
+
+    <para>The first generation began by managing single files on
+      individual computers.  Although these tools represented a huge
+      advance over ad-hoc manual revision control, their locking model
+      and reliance on a single computer limited them to small,
+      tightly-knit teams.</para>
+
+    <para>The second generation loosened these constraints by moving
+      to network-centered architectures, and managing entire projects
+      at a time.  As projects grew larger, they ran into new problems.
+      With clients needing to talk to servers very frequently, server
+      scaling became an issue for large projects.  An unreliable
+      network connection could prevent remote users from being able to
+      talk to the server at all.  As open source projects started
+      making read-only access available anonymously to anyone, people
+      without commit privileges found that they could not use the
+      tools to interact with a project in a natural way, as they could
+      not record their changes.</para>
+
+    <para>The current generation of revision control tools is
+      peer-to-peer in nature.  All of these systems have dropped the
+      dependency on a single central server, and allow people to
+      distribute their revision control data to where it's actually
+      needed.  Collaboration over the Internet has moved from
+      constrained by technology to a matter of choice and consensus.
+      Modern tools can operate offline indefinitely and autonomously,
+      with a network connection only needed when syncing changes with
+      another repository.</para>
+
+  </sect1>
+  <sect1>
+    <title>A few of the advantages of distributed revision
+      control</title>
+
+    <para>Even though distributed revision control tools have for
+      several years been as robust and usable as their
+      previous-generation counterparts, people using older tools have
+      not yet necessarily woken up to their advantages.  There are a
+      number of ways in which distributed tools shine relative to
+      centralised ones.</para>
+
+    <para>For an individual developer, distributed tools are almost
+      always much faster than centralised tools.  This is for a simple
+      reason: a centralised tool needs to talk over the network for
+      many common operations, because most metadata is stored in a
+      single copy on the central server.  A distributed tool stores
+      all of its metadata locally.  All else being equal, talking over
+      the network adds overhead to a centralised tool.  Don't
+      underestimate the value of a snappy, responsive tool: you're
+      going to spend a lot of time interacting with your revision
+      control software.</para>
+
+    <para>Distributed tools are indifferent to the vagaries of your
+      server infrastructure, again because they replicate metadata to
+      so many locations.  If you use a centralised system and your
+      server catches fire, you'd better hope that your backup media
+      are reliable, and that your last backup was recent and actually
+      worked.  With a distributed tool, you have many backups
+      available on every contributor's computer.</para>
+
+    <para>The reliability of your network will affect distributed
+      tools far less than it will centralised tools.  You can't even
+      use a centralised tool without a network connection, except for
+      a few highly constrained commands.  With a distributed tool, if
+      your network connection goes down while you're working, you may
+      not even notice.  The only thing you won't be able to do is talk
+      to repositories on other computers, something that is relatively
+      rare compared with local operations.  If you have a far-flung
+      team of collaborators, this may be significant.</para>
+
+    <sect2>
+      <title>Advantages for open source projects</title>
+
+      <para>If you take a shine to an open source project and decide
+	that you would like to start hacking on it, and that project
+	uses a distributed revision control tool, you are at once a
+	peer with the people who consider themselves the
+	<quote>core</quote> of that project.  If they publish their
+	repositories, you can immediately copy their project history,
+	start making changes, and record your work, using the same
+	tools in the same ways as insiders.  By contrast, with a
+	centralised tool, you must use the software in a <quote>read
+	  only</quote> mode unless someone grants you permission to
+	commit changes to their central server.  Until then, you won't
+	be able to record changes, and your local modifications will
+	be at risk of corruption any time you try to update your
+	client's view of the repository.</para>
+
+      <sect3>
+	<title>The forking non-problem</title>
+
+	<para>It has been suggested that distributed revision control
+	  tools pose some sort of risk to open source projects because
+	  they make it easy to <quote>fork</quote> the development of
+	  a project.  A fork happens when there are differences in
+	  opinion or attitude between groups of developers that cause
+	  them to decide that they can't work together any longer.
+	  Each side takes a more or less complete copy of the
+	  project's source code, and goes off in its own
+	  direction.</para>
+
+	<para>Sometimes the camps in a fork decide to reconcile their
+	  differences. With a centralised revision control system, the
+	  <emphasis>technical</emphasis> process of reconciliation is
+	  painful, and has to be performed largely by hand.  You have
+	  to decide whose revision history is going to
+	  <quote>win</quote>, and graft the other team's changes into
+	  the tree somehow. This usually loses some or all of one
+	  side's revision history.</para>
+
+	<para>What distributed tools do with respect to forking is
+	  they make forking the <emphasis>only</emphasis> way to
+	  develop a project.  Every single change that you make is
+	  potentially a fork point.  The great strength of this
+	  approach is that a distributed revision control tool has to
+	  be really good at <emphasis>merging</emphasis> forks,
+	  because forks are absolutely fundamental: they happen all
+	  the time.</para>
+
+	<para>If every piece of work that everybody does, all the
+	  time, is framed in terms of forking and merging, then what
+	  the open source world refers to as a <quote>fork</quote>
+	  becomes <emphasis>purely</emphasis> a social issue.  If
+	  anything, distributed tools <emphasis>lower</emphasis> the
+	  likelihood of a fork:</para>
+	<itemizedlist>
+	  <listitem><para>They eliminate the social distinction that
+	      centralised tools impose: that between insiders (people
+	      with commit access) and outsiders (people
+	      without).</para></listitem>
+	  <listitem><para>They make it easier to reconcile after a
+	      social fork, because all that's involved from the
+	      perspective of the revision control software is just
+	      another merge.</para></listitem></itemizedlist>
+
+	<para>Some people resist distributed tools because they want
+	  to retain tight control over their projects, and they
+	  believe that centralised tools give them this control.
+	  However, if you're of this belief, and you publish your CVS
+	  or Subversion repositories publically, there are plenty of
+	  tools available that can pull out your entire project's
+	  history (albeit slowly) and recreate it somewhere that you
+	  don't control.  So while your control in this case is
+	  illusory, you are forgoing the ability to fluidly
+	  collaborate with whatever people feel compelled to mirror
+	  and fork your history.</para>
+
+      </sect3>
+    </sect2>
+    <sect2>
+      <title>Advantages for commercial projects</title>
+
+      <para>Many commercial projects are undertaken by teams that are
+	scattered across the globe.  Contributors who are far from a
+	central server will see slower command execution and perhaps
+	less reliability.  Commercial revision control systems attempt
+	to ameliorate these problems with remote-site replication
+	add-ons that are typically expensive to buy and cantankerous
+	to administer.  A distributed system doesn't suffer from these
+	problems in the first place.  Better yet, you can easily set
+	up multiple authoritative servers, say one per site, so that
+	there's no redundant communication between repositories over
+	expensive long-haul network links.</para>
+
+      <para>Centralised revision control systems tend to have
+	relatively low scalability.  It's not unusual for an expensive
+	centralised system to fall over under the combined load of
+	just a few dozen concurrent users.  Once again, the typical
+	response tends to be an expensive and clunky replication
+	facility.  Since the load on a central server---if you have
+	one at all---is many times lower with a distributed tool
+	(because all of the data is replicated everywhere), a single
+	cheap server can handle the needs of a much larger team, and
+	replication to balance load becomes a simple matter of
+	scripting.</para>
+
+      <para>If you have an employee in the field, troubleshooting a
+	problem at a customer's site, they'll benefit from distributed
+	revision control. The tool will let them generate custom
+	builds, try different fixes in isolation from each other, and
+	search efficiently through history for the sources of bugs and
+	regressions in the customer's environment, all without needing
+	to connect to your company's network.</para>
+
+    </sect2>
+  </sect1>
+  <sect1>
+    <title>Why choose Mercurial?</title>
+
+    <para>Mercurial has a unique set of properties that make it a
+      particularly good choice as a revision control system.</para>
+    <itemizedlist>
+      <listitem><para>It is easy to learn and use.</para></listitem>
+      <listitem><para>It is lightweight.</para></listitem>
+      <listitem><para>It scales excellently.</para></listitem>
+      <listitem><para>It is easy to
+	  customise.</para></listitem></itemizedlist>
+
+    <para>If you are at all familiar with revision control systems,
+      you should be able to get up and running with Mercurial in less
+      than five minutes.  Even if not, it will take no more than a few
+      minutes longer.  Mercurial's command and feature sets are
+      generally uniform and consistent, so you can keep track of a few
+      general rules instead of a host of exceptions.</para>
+
+    <para>On a small project, you can start working with Mercurial in
+      moments. Creating new changes and branches; transferring changes
+      around (whether locally or over a network); and history and
+      status operations are all fast.  Mercurial attempts to stay
+      nimble and largely out of your way by combining low cognitive
+      overhead with blazingly fast operations.</para>
+
+    <para>The usefulness of Mercurial is not limited to small
+      projects: it is used by projects with hundreds to thousands of
+      contributors, each containing tens of thousands of files and
+      hundreds of megabytes of source code.</para>
+
+    <para>If the core functionality of Mercurial is not enough for
+      you, it's easy to build on.  Mercurial is well suited to
+      scripting tasks, and its clean internals and implementation in
+      Python make it easy to add features in the form of extensions.
+      There are a number of popular and useful extensions already
+      available, ranging from helping to identify bugs to improving
+      performance.</para>
+
+  </sect1>
+  <sect1>
+    <title>Mercurial compared with other tools</title>
+
+    <para>Before you read on, please understand that this section
+      necessarily reflects my own experiences, interests, and (dare I
+      say it) biases.  I have used every one of the revision control
+      tools listed below, in most cases for several years at a
+      time.</para>
+
+
+    <sect2>
+      <title>Subversion</title>
+
+      <para>Subversion is a popular revision control tool, developed
+	to replace CVS.  It has a centralised client/server
+	architecture.</para>
+
+      <para>Subversion and Mercurial have similarly named commands for
+	performing the same operations, so if you're familiar with
+	one, it is easy to learn to use the other.  Both tools are
+	portable to all popular operating systems.</para>
+
+      <para>Prior to version 1.5, Subversion had no useful support for
+	merges. At the time of writing, its merge tracking capability
+	is new, and known to be <ulink
+	  url="http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword">complicated 
+	  and buggy</ulink>.</para>
+
+      <para>Mercurial has a substantial performance advantage over
+	Subversion on every revision control operation I have
+	benchmarked.  I have measured its advantage as ranging from a
+	factor of two to a factor of six when compared with Subversion
+	1.4.3's <emphasis>ra_local</emphasis> file store, which is the
+	fastest access method available.  In more realistic
+	deployments involving a network-based store, Subversion will
+	be at a substantially larger disadvantage.  Because many
+	Subversion commands must talk to the server and Subversion
+	does not have useful replication facilities, server capacity
+	and network bandwidth become bottlenecks for modestly large
+	projects.</para>
+
+      <para>Additionally, Subversion incurs substantial storage
+	overhead to avoid network transactions for a few common
+	operations, such as finding modified files
+	(<literal>status</literal>) and displaying modifications
+	against the current revision (<literal>diff</literal>).  As a
+	result, a Subversion working copy is often the same size as,
+	or larger than, a Mercurial repository and working directory,
+	even though the Mercurial repository contains a complete
+	history of the project.</para>
+
+      <para>Subversion is widely supported by third party tools.
+	Mercurial currently lags considerably in this area.  This gap
+	is closing, however, and indeed some of Mercurial's GUI tools
+	now outshine their Subversion equivalents.  Like Mercurial,
+	Subversion has an excellent user manual.</para>
+
+      <para>Because Subversion doesn't store revision history on the
+	client, it is well suited to managing projects that deal with
+	lots of large, opaque binary files.  If you check in fifty
+	revisions to an incompressible 10MB file, Subversion's
+	client-side space usage stays constant The space used by any
+	distributed SCM will grow rapidly in proportion to the number
+	of revisions, because the differences between each revision
+	are large.</para>
+
+      <para>In addition, it's often difficult or, more usually,
+	impossible to merge different versions of a binary file.
+	Subversion's ability to let a user lock a file, so that they
+	temporarily have the exclusive right to commit changes to it,
+	can be a significant advantage to a project where binary files
+	are widely used.</para>
+
+      <para>Mercurial can import revision history from a Subversion
+	repository. It can also export revision history to a
+	Subversion repository.  This makes it easy to <quote>test the
+	  waters</quote> and use Mercurial and Subversion in parallel
+	before deciding to switch.  History conversion is incremental,
+	so you can perform an initial conversion, then small
+	additional conversions afterwards to bring in new
+	changes.</para>
+
+
+    </sect2>
+    <sect2>
+      <title>Git</title>
+
+      <para>Git is a distributed revision control tool that was
+	developed for managing the Linux kernel source tree.  Like
+	Mercurial, its early design was somewhat influenced by
+	Monotone.</para>
+
+      <para>Git has a very large command set, with version 1.5.0
+	providing 139 individual commands.  It has something of a
+	reputation for being difficult to learn.  Compared to Git,
+	Mercurial has a strong focus on simplicity.</para>
+
+      <para>In terms of performance, Git is extremely fast.  In
+	several cases, it is faster than Mercurial, at least on Linux,
+	while Mercurial performs better on other operations.  However,
+	on Windows, the performance and general level of support that
+	Git provides is, at the time of writing, far behind that of
+	Mercurial.</para>
+
+      <para>While a Mercurial repository needs no maintenance, a Git
+	repository requires frequent manual <quote>repacks</quote> of
+	its metadata.  Without these, performance degrades, while
+	space usage grows rapidly.  A server that contains many Git
+	repositories that are not rigorously and frequently repacked
+	will become heavily disk-bound during backups, and there have
+	been instances of daily backups taking far longer than 24
+	hours as a result.  A freshly packed Git repository is
+	slightly smaller than a Mercurial repository, but an unpacked
+	repository is several orders of magnitude larger.</para>
+
+      <para>The core of Git is written in C.  Many Git commands are
+	implemented as shell or Perl scripts, and the quality of these
+	scripts varies widely. I have encountered several instances
+	where scripts charged along blindly in the presence of errors
+	that should have been fatal.</para>
+
+      <para>Mercurial can import revision history from a Git
+	repository.</para>
+
+
+    </sect2>
+    <sect2>
+      <title>CVS</title>
+
+      <para>CVS is probably the most widely used revision control tool
+	in the world.  Due to its age and internal untidiness, it has
+	been only lightly maintained for many years.</para>
+
+      <para>It has a centralised client/server architecture.  It does
+	not group related file changes into atomic commits, making it
+	easy for people to <quote>break the build</quote>: one person
+	can successfully commit part of a change and then be blocked
+	by the need for a merge, causing other people to see only a
+	portion of the work they intended to do.  This also affects
+	how you work with project history.  If you want to see all of
+	the modifications someone made as part of a task, you will
+	need to manually inspect the descriptions and timestamps of
+	the changes made to each file involved (if you even know what
+	those files were).</para>
+
+      <para>CVS has a muddled notion of tags and branches that I will
+	not attempt to even describe.  It does not support renaming of
+	files or directories well, making it easy to corrupt a
+	repository.  It has almost no internal consistency checking
+	capabilities, so it is usually not even possible to tell
+	whether or how a repository is corrupt.  I would not recommend
+	CVS for any project, existing or new.</para>
+
+      <para>Mercurial can import CVS revision history.  However, there
+	are a few caveats that apply; these are true of every other
+	revision control tool's CVS importer, too.  Due to CVS's lack
+	of atomic changes and unversioned filesystem hierarchy, it is
+	not possible to reconstruct CVS history completely accurately;
+	some guesswork is involved, and renames will usually not show
+	up.  Because a lot of advanced CVS administration has to be
+	done by hand and is hence error-prone, it's common for CVS
+	importers to run into multiple problems with corrupted
+	repositories (completely bogus revision timestamps and files
+	that have remained locked for over a decade are just two of
+	the less interesting problems I can recall from personal
+	experience).</para>
+
+      <para>Mercurial can import revision history from a CVS
+	repository.</para>
+
+
+    </sect2>
+    <sect2>
+      <title>Commercial tools</title>
+
+      <para>Perforce has a centralised client/server architecture,
+	with no client-side caching of any data.  Unlike modern
+	revision control tools, Perforce requires that a user run a
+	command to inform the server about every file they intend to
+	edit.</para>
+
+      <para>The performance of Perforce is quite good for small teams,
+	but it falls off rapidly as the number of users grows beyond a
+	few dozen. Modestly large Perforce installations require the
+	deployment of proxies to cope with the load their users
+	generate.</para>
+
+
+    </sect2>
+    <sect2>
+      <title>Choosing a revision control tool</title>
+
+      <para>With the exception of CVS, all of the tools listed above
+	have unique strengths that suit them to particular styles of
+	work.  There is no single revision control tool that is best
+	in all situations.</para>
+
+      <para>As an example, Subversion is a good choice for working
+	with frequently edited binary files, due to its centralised
+	nature and support for file locking.</para>
+
+      <para>I personally find Mercurial's properties of simplicity,
+	performance, and good merge support to be a compelling
+	combination that has served me well for several years.</para>
+
+
+    </sect2>
+  </sect1>
+  <sect1>
+    <title>Switching from another tool to Mercurial</title>
+
+    <para>Mercurial is bundled with an extension named <literal
+	role="hg-ext">convert</literal>, which can incrementally
+      import revision history from several other revision control
+      tools.  By <quote>incremental</quote>, I mean that you can
+      convert all of a project's history to date in one go, then rerun
+      the conversion later to obtain new changes that happened after
+      the initial conversion.</para>
+
+    <para>The revision control tools supported by <literal
+	role="hg-ext">convert</literal> are as follows:</para>
+    <itemizedlist>
+      <listitem><para>Subversion</para></listitem>
+      <listitem><para>CVS</para></listitem>
+      <listitem><para>Git</para></listitem>
+      <listitem><para>Darcs</para></listitem></itemizedlist>
+
+    <para>In addition, <literal role="hg-ext">convert</literal> can
+      export changes from Mercurial to Subversion.  This makes it
+      possible to try Subversion and Mercurial in parallel before
+      committing to a switchover, without risking the loss of any
+      work.</para>
+
+    <para>The <command role="hg-ext-conver">convert</command> command
+      is easy to use.  Simply point it at the path or URL of the
+      source repository, optionally give it the name of the
+      destination repository, and it will start working.  After the
+      initial conversion, just run the same command again to import
+      new changes.</para>
+  </sect1>
+</chapter>
+
+<!--
+local variables: 
+sgml-parent-document: ("00book.xml" "book" "chapter")
+end:
+-->
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch02-tour-basic.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,622 @@
+\chapter{A tour of Mercurial: the basics}
+\label{chap:tour-basic}
+
+\section{Installing Mercurial on your system}
+\label{sec:tour:install}
+
+Prebuilt binary packages of Mercurial are available for every popular
+operating system.  These make it easy to start using Mercurial on your
+computer immediately.
+
+\subsection{Linux}
+
+Because each Linux distribution has its own packaging tools, policies,
+and rate of development, it's difficult to give a comprehensive set of
+instructions on how to install Mercurial binaries.  The version of
+Mercurial that you will end up with can vary depending on how active
+the person is who maintains the package for your distribution.
+
+To keep things simple, I will focus on installing Mercurial from the
+command line under the most popular Linux distributions.  Most of
+these distributions provide graphical package managers that will let
+you install Mercurial with a single click; the package name to look
+for is \texttt{mercurial}.
+
+\begin{itemize}
+\item[Debian]
+  \begin{codesample4}
+    apt-get install mercurial
+  \end{codesample4}
+
+\item[Fedora Core]
+  \begin{codesample4}
+    yum install mercurial
+  \end{codesample4}
+
+\item[Gentoo]
+  \begin{codesample4}
+    emerge mercurial
+  \end{codesample4}
+
+\item[OpenSUSE]
+  \begin{codesample4}
+    yum install mercurial
+  \end{codesample4}
+
+\item[Ubuntu] Ubuntu's Mercurial package is based on Debian's.  To
+  install it, run the following command.
+  \begin{codesample4}
+    apt-get install mercurial
+  \end{codesample4}
+  The Ubuntu package for Mercurial tends to lag behind the Debian
+  version by a considerable time margin (at the time of writing, seven
+  months), which in some cases will mean that on Ubuntu, you may run
+  into problems that have since been fixed in the Debian package.
+\end{itemize}
+
+\subsection{Solaris}
+
+SunFreeWare, at \url{http://www.sunfreeware.com}, is a good source for a
+large number of pre-built Solaris packages for 32 and 64 bit Intel and
+Sparc architectures, including current versions of Mercurial.
+
+\subsection{Mac OS X}
+
+Lee Cantey publishes an installer of Mercurial for Mac OS~X at
+\url{http://mercurial.berkwood.com}.  This package works on both
+Intel-~and Power-based Macs.  Before you can use it, you must install
+a compatible version of Universal MacPython~\cite{web:macpython}.  This
+is easy to do; simply follow the instructions on Lee's site.
+
+It's also possible to install Mercurial using Fink or MacPorts,
+two popular free package managers for Mac OS X.  If you have Fink,
+use \command{sudo apt-get install mercurial-py25}.  If MacPorts,
+\command{sudo port install mercurial}.
+
+\subsection{Windows}
+
+Lee Cantey publishes an installer of Mercurial for Windows at
+\url{http://mercurial.berkwood.com}.  This package has no external
+dependencies; it ``just works''.
+
+\begin{note}
+  The Windows version of Mercurial does not automatically convert line
+  endings between Windows and Unix styles.  If you want to share work
+  with Unix users, you must do a little additional configuration
+  work. XXX Flesh this out.
+\end{note}
+
+\section{Getting started}
+
+To begin, we'll use the \hgcmd{version} command to find out whether
+Mercurial is actually installed properly.  The actual version
+information that it prints isn't so important; it's whether it prints
+anything at all that we care about.
+\interaction{tour.version}
+
+\subsection{Built-in help}
+
+Mercurial provides a built-in help system.  This is invaluable for those
+times when you find yourself stuck trying to remember how to run a
+command.  If you are completely stuck, simply run \hgcmd{help}; it
+will print a brief list of commands, along with a description of what
+each does.  If you ask for help on a specific command (as below), it
+prints more detailed information.
+\interaction{tour.help}
+For a more impressive level of detail (which you won't usually need)
+run \hgcmdargs{help}{\hggopt{-v}}.  The \hggopt{-v} option is short
+for \hggopt{--verbose}, and tells Mercurial to print more information
+than it usually would.
+
+\section{Working with a repository}
+
+In Mercurial, everything happens inside a \emph{repository}.  The
+repository for a project contains all of the files that ``belong to''
+that project, along with a historical record of the project's files.
+
+There's nothing particularly magical about a repository; it is simply
+a directory tree in your filesystem that Mercurial treats as special.
+You can rename or delete a repository any time you like, using either the
+command line or your file browser.
+
+\subsection{Making a local copy of a repository}
+
+\emph{Copying} a repository is just a little bit special.  While you
+could use a normal file copying command to make a copy of a
+repository, it's best to use a built-in command that Mercurial
+provides.  This command is called \hgcmd{clone}, because it creates an
+identical copy of an existing repository.
+\interaction{tour.clone}
+If our clone succeeded, we should now have a local directory called
+\dirname{hello}.  This directory will contain some files.
+\interaction{tour.ls}
+These files have the same contents and history in our repository as
+they do in the repository we cloned.
+
+Every Mercurial repository is complete, self-contained, and
+independent.  It contains its own private copy of a project's files
+and history.  A cloned repository remembers the location of the
+repository it was cloned from, but it does not communicate with that
+repository, or any other, unless you tell it to.
+
+What this means for now is that we're free to experiment with our
+repository, safe in the knowledge that it's a private ``sandbox'' that
+won't affect anyone else.
+
+\subsection{What's in a repository?}
+
+When we take a more detailed look inside a repository, we can see that
+it contains a directory named \dirname{.hg}.  This is where Mercurial
+keeps all of its metadata for the repository.
+\interaction{tour.ls-a}
+
+The contents of the \dirname{.hg} directory and its subdirectories are
+private to Mercurial.  Every other file and directory in the
+repository is yours to do with as you please.
+
+To introduce a little terminology, the \dirname{.hg} directory is the
+``real'' repository, and all of the files and directories that coexist
+with it are said to live in the \emph{working directory}.  An easy way
+to remember the distinction is that the \emph{repository} contains the
+\emph{history} of your project, while the \emph{working directory}
+contains a \emph{snapshot} of your project at a particular point in
+history.
+
+\section{A tour through history}
+
+One of the first things we might want to do with a new, unfamiliar
+repository is understand its history.  The \hgcmd{log} command gives
+us a view of history.
+\interaction{tour.log}
+By default, this command prints a brief paragraph of output for each
+change to the project that was recorded.  In Mercurial terminology, we
+call each of these recorded events a \emph{changeset}, because it can
+contain a record of changes to several files.
+
+The fields in a record of output from \hgcmd{log} are as follows.
+\begin{itemize}
+\item[\texttt{changeset}] This field has the format of a number,
+  followed by a colon, followed by a hexadecimal string.  These are
+  \emph{identifiers} for the changeset.  There are two identifiers
+  because the number is shorter and easier to type than the hex
+  string.
+\item[\texttt{user}] The identity of the person who created the
+  changeset.  This is a free-form field, but it most often contains a
+  person's name and email address.
+\item[\texttt{date}] The date and time on which the changeset was
+  created, and the timezone in which it was created.  (The date and
+  time are local to that timezone; they display what time and date it
+  was for the person who created the changeset.)
+\item[\texttt{summary}] The first line of the text message that the
+  creator of the changeset entered to describe the changeset.
+\end{itemize}
+The default output printed by \hgcmd{log} is purely a summary; it is
+missing a lot of detail.
+
+Figure~\ref{fig:tour-basic:history} provides a graphical representation of
+the history of the \dirname{hello} repository, to make it a little
+easier to see which direction history is ``flowing'' in.  We'll be
+returning to this figure several times in this chapter and the chapter
+that follows.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{tour-history}
+  \caption{Graphical history of the \dirname{hello} repository}
+  \label{fig:tour-basic:history}
+\end{figure}
+
+\subsection{Changesets, revisions, and talking to other people}
+
+As English is a notoriously sloppy language, and computer science has
+a hallowed history of terminological confusion (why use one term when
+four will do?), revision control has a variety of words and phrases
+that mean the same thing.  If you are talking about Mercurial history
+with other people, you will find that the word ``changeset'' is often
+compressed to ``change'' or (when written) ``cset'', and sometimes a
+changeset is referred to as a ``revision'' or a ``rev''.
+
+While it doesn't matter what \emph{word} you use to refer to the
+concept of ``a~changeset'', the \emph{identifier} that you use to
+refer to ``a~\emph{specific} changeset'' is of great importance.
+Recall that the \texttt{changeset} field in the output from
+\hgcmd{log} identifies a changeset using both a number and a
+hexadecimal string.
+\begin{itemize}
+\item The revision number is \emph{only valid in that repository},
+\item while the hex string is the \emph{permanent, unchanging identifier} that will always identify that exact changeset in
+  \emph{every} copy of the repository.
+\end{itemize}
+This distinction is important.  If you send someone an email talking
+about ``revision~33'', there's a high likelihood that their
+revision~33 will \emph{not be the same} as yours.  The reason for this
+is that a revision number depends on the order in which changes
+arrived in a repository, and there is no guarantee that the same
+changes will happen in the same order in different repositories.
+Three changes $a,b,c$ can easily appear in one repository as $0,1,2$,
+while in another as $1,0,2$.
+
+Mercurial uses revision numbers purely as a convenient shorthand.  If
+you need to discuss a changeset with someone, or make a record of a
+changeset for some other reason (for example, in a bug report), use
+the hexadecimal identifier.
+
+\subsection{Viewing specific revisions}
+
+To narrow the output of \hgcmd{log} down to a single revision, use the
+\hgopt{log}{-r} (or \hgopt{log}{--rev}) option.  You can use either a
+revision number or a long-form changeset identifier, and you can
+provide as many revisions as you want.  \interaction{tour.log-r}
+
+If you want to see the history of several revisions without having to
+list each one, you can use \emph{range notation}; this lets you
+express the idea ``I want all revisions between $a$ and $b$,
+inclusive''.
+\interaction{tour.log.range}
+Mercurial also honours the order in which you specify revisions, so
+\hgcmdargs{log}{-r 2:4} prints $2,3,4$ while \hgcmdargs{log}{-r 4:2}
+prints $4,3,2$.
+
+\subsection{More detailed information}
+
+While the summary information printed by \hgcmd{log} is useful if you
+already know what you're looking for, you may need to see a complete
+description of the change, or a list of the files changed, if you're
+trying to decide whether a changeset is the one you're looking for.
+The \hgcmd{log} command's \hggopt{-v} (or \hggopt{--verbose})
+option gives you this extra detail.
+\interaction{tour.log-v}
+
+If you want to see both the description and content of a change, add
+the \hgopt{log}{-p} (or \hgopt{log}{--patch}) option.  This displays
+the content of a change as a \emph{unified diff} (if you've never seen
+a unified diff before, see section~\ref{sec:mq:patch} for an overview).
+\interaction{tour.log-vp}
+
+\section{All about command options}
+
+Let's take a brief break from exploring Mercurial commands to discuss
+a pattern in the way that they work; you may find this useful to keep
+in mind as we continue our tour.
+
+Mercurial has a consistent and straightforward approach to dealing
+with the options that you can pass to commands.  It follows the
+conventions for options that are common to modern Linux and Unix
+systems.
+\begin{itemize}
+\item Every option has a long name.  For example, as we've already
+  seen, the \hgcmd{log} command accepts a \hgopt{log}{--rev} option.
+\item Most options have short names, too.  Instead of
+  \hgopt{log}{--rev}, we can use \hgopt{log}{-r}.  (The reason that
+  some options don't have short names is that the options in question
+  are rarely used.)
+\item Long options start with two dashes (e.g.~\hgopt{log}{--rev}),
+  while short options start with one (e.g.~\hgopt{log}{-r}).
+\item Option naming and usage is consistent across commands.  For
+  example, every command that lets you specify a changeset~ID or
+  revision number accepts both \hgopt{log}{-r} and \hgopt{log}{--rev}
+  arguments.
+\end{itemize}
+In the examples throughout this book, I use short options instead of
+long.  This just reflects my own preference, so don't read anything
+significant into it.
+
+Most commands that print output of some kind will print more output
+when passed a \hggopt{-v} (or \hggopt{--verbose}) option, and less
+when passed \hggopt{-q} (or \hggopt{--quiet}).
+
+\section{Making and reviewing changes}
+
+Now that we have a grasp of viewing history in Mercurial, let's take a
+look at making some changes and examining them.
+
+The first thing we'll do is isolate our experiment in a repository of
+its own.  We use the \hgcmd{clone} command, but we don't need to
+clone a copy of the remote repository.  Since we already have a copy
+of it locally, we can just clone that instead.  This is much faster
+than cloning over the network, and cloning a local repository uses
+less disk space in most cases, too.
+\interaction{tour.reclone}
+As an aside, it's often good practice to keep a ``pristine'' copy of a
+remote repository around, which you can then make temporary clones of
+to create sandboxes for each task you want to work on.  This lets you
+work on multiple tasks in parallel, each isolated from the others
+until it's complete and you're ready to integrate it back.  Because
+local clones are so cheap, there's almost no overhead to cloning and
+destroying repositories whenever you want.
+
+In our \dirname{my-hello} repository, we have a file
+\filename{hello.c} that contains the classic ``hello, world'' program.
+Let's use the ancient and venerable \command{sed} command to edit this
+file so that it prints a second line of output.  (I'm only using
+\command{sed} to do this because it's easy to write a scripted example
+this way.  Since you're not under the same constraint, you probably
+won't want to use \command{sed}; simply use your preferred text editor to
+do the same thing.)
+\interaction{tour.sed}
+
+Mercurial's \hgcmd{status} command will tell us what Mercurial knows
+about the files in the repository.
+\interaction{tour.status}
+The \hgcmd{status} command prints no output for some files, but a line
+starting with ``\texttt{M}'' for \filename{hello.c}.  Unless you tell
+it to, \hgcmd{status} will not print any output for files that have
+not been modified.  
+
+The ``\texttt{M}'' indicates that Mercurial has noticed that we
+modified \filename{hello.c}.  We didn't need to \emph{inform}
+Mercurial that we were going to modify the file before we started, or
+that we had modified the file after we were done; it was able to
+figure this out itself.
+
+It's a little bit helpful to know that we've modified
+\filename{hello.c}, but we might prefer to know exactly \emph{what}
+changes we've made to it.  To do this, we use the \hgcmd{diff}
+command.
+\interaction{tour.diff}
+
+\section{Recording changes in a new changeset}
+
+We can modify files, build and test our changes, and use
+\hgcmd{status} and \hgcmd{diff} to review our changes, until we're
+satisfied with what we've done and arrive at a natural stopping point
+where we want to record our work in a new changeset.
+
+The \hgcmd{commit} command lets us create a new changeset; we'll
+usually refer to this as ``making a commit'' or ``committing''.  
+
+\subsection{Setting up a username}
+
+When you try to run \hgcmd{commit} for the first time, it is not
+guaranteed to succeed.  Mercurial records your name and address with
+each change that you commit, so that you and others will later be able
+to tell who made each change.  Mercurial tries to automatically figure
+out a sensible username to commit the change with.  It will attempt
+each of the following methods, in order:
+\begin{enumerate}
+\item If you specify a \hgopt{commit}{-u} option to the \hgcmd{commit}
+  command on the command line, followed by a username, this is always
+  given the highest precedence.
+\item If you have set the \envar{HGUSER} environment variable, this is
+  checked next.
+\item If you create a file in your home directory called
+  \sfilename{.hgrc}, with a \rcitem{ui}{username} entry, that will be
+  used next.  To see what the contents of this file should look like,
+  refer to section~\ref{sec:tour-basic:username} below.
+\item If you have set the \envar{EMAIL} environment variable, this
+  will be used next.
+\item Mercurial will query your system to find out your local user
+  name and host name, and construct a username from these components.
+  Since this often results in a username that is not very useful, it
+  will print a warning if it has to do this.
+\end{enumerate}
+If all of these mechanisms fail, Mercurial will fail, printing an
+error message.  In this case, it will not let you commit until you set
+up a username.
+
+You should think of the \envar{HGUSER} environment variable and the
+\hgopt{commit}{-u} option to the \hgcmd{commit} command as ways to
+\emph{override} Mercurial's default selection of username.  For normal
+use, the simplest and most robust way to set a username for yourself
+is by creating a \sfilename{.hgrc} file; see below for details.
+
+\subsubsection{Creating a Mercurial configuration file}
+\label{sec:tour-basic:username}
+
+To set a user name, use your favourite editor to create a file called
+\sfilename{.hgrc} in your home directory.  Mercurial will use this
+file to look up your personalised configuration settings.  The initial
+contents of your \sfilename{.hgrc} should look like this.
+\begin{codesample2}
+  # This is a Mercurial configuration file.
+  [ui]
+  username = Firstname Lastname <email.address@domain.net>
+\end{codesample2}
+The ``\texttt{[ui]}'' line begins a \emph{section} of the config file,
+so you can read the ``\texttt{username = ...}'' line as meaning ``set
+the value of the \texttt{username} item in the \texttt{ui} section''.
+A section continues until a new section begins, or the end of the
+file.  Mercurial ignores empty lines and treats any text from
+``\texttt{\#}'' to the end of a line as a comment.
+
+\subsubsection{Choosing a user name}
+
+You can use any text you like as the value of the \texttt{username}
+config item, since this information is for reading by other people,
+but for interpreting by Mercurial.  The convention that most people
+follow is to use their name and email address, as in the example
+above.
+
+\begin{note}
+  Mercurial's built-in web server obfuscates email addresses, to make
+  it more difficult for the email harvesting tools that spammers use.
+  This reduces the likelihood that you'll start receiving more junk
+  email if you publish a Mercurial repository on the web.
+\end{note}
+
+\subsection{Writing a commit message}
+
+When we commit a change, Mercurial drops us into a text editor, to
+enter a message that will describe the modifications we've made in
+this changeset.  This is called the \emph{commit message}.  It will be
+a record for readers of what we did and why, and it will be printed by
+\hgcmd{log} after we've finished committing.
+\interaction{tour.commit}
+
+The editor that the \hgcmd{commit} command drops us into will contain
+an empty line, followed by a number of lines starting with
+``\texttt{HG:}''.
+\begin{codesample2}
+  \emph{empty line}
+  HG: changed hello.c
+\end{codesample2}
+Mercurial ignores the lines that start with ``\texttt{HG:}''; it uses
+them only to tell us which files it's recording changes to.  Modifying
+or deleting these lines has no effect.
+
+\subsection{Writing a good commit message}
+
+Since \hgcmd{log} only prints the first line of a commit message by
+default, it's best to write a commit message whose first line stands
+alone.  Here's a real example of a commit message that \emph{doesn't}
+follow this guideline, and hence has a summary that is not readable.
+\begin{codesample2}
+  changeset:   73:584af0e231be
+  user:        Censored Person <censored.person@example.org>
+  date:        Tue Sep 26 21:37:07 2006 -0700
+  summary:     include buildmeister/commondefs.   Add an exports and install
+\end{codesample2}
+
+As far as the remainder of the contents of the commit message are
+concerned, there are no hard-and-fast rules.  Mercurial itself doesn't
+interpret or care about the contents of the commit message, though
+your project may have policies that dictate a certain kind of
+formatting.
+
+My personal preference is for short, but informative, commit messages
+that tell me something that I can't figure out with a quick glance at
+the output of \hgcmdargs{log}{--patch}.
+
+\subsection{Aborting a commit}
+
+If you decide that you don't want to commit while in the middle of
+editing a commit message, simply exit from your editor without saving
+the file that it's editing.  This will cause nothing to happen to
+either the repository or the working directory.
+
+If we run the \hgcmd{commit} command without any arguments, it records
+all of the changes we've made, as reported by \hgcmd{status} and
+\hgcmd{diff}.
+
+\subsection{Admiring our new handiwork}
+
+Once we've finished the commit, we can use the \hgcmd{tip} command to
+display the changeset we just created.  This command produces output
+that is identical to \hgcmd{log}, but it only displays the newest
+revision in the repository.
+\interaction{tour.tip}
+We refer to the newest revision in the repository as the tip revision,
+or simply the tip.
+
+\section{Sharing changes}
+
+We mentioned earlier that repositories in Mercurial are
+self-contained.  This means that the changeset we just created exists
+only in our \dirname{my-hello} repository.  Let's look at a few ways
+that we can propagate this change into other repositories.
+
+\subsection{Pulling changes from another repository}
+\label{sec:tour:pull}
+
+To get started, let's clone our original \dirname{hello} repository,
+which does not contain the change we just committed.  We'll call our
+temporary repository \dirname{hello-pull}.
+\interaction{tour.clone-pull}
+
+We'll use the \hgcmd{pull} command to bring changes from
+\dirname{my-hello} into \dirname{hello-pull}.  However, blindly
+pulling unknown changes into a repository is a somewhat scary
+prospect.  Mercurial provides the \hgcmd{incoming} command to tell us
+what changes the \hgcmd{pull} command \emph{would} pull into the
+repository, without actually pulling the changes in.
+\interaction{tour.incoming}
+(Of course, someone could cause more changesets to appear in the
+repository that we ran \hgcmd{incoming} in, before we get a chance to
+\hgcmd{pull} the changes, so that we could end up pulling changes that we
+didn't expect.)
+
+Bringing changes into a repository is a simple matter of running the
+\hgcmd{pull} command, and telling it which repository to pull from.
+\interaction{tour.pull}
+As you can see from the before-and-after output of \hgcmd{tip}, we
+have successfully pulled changes into our repository.  There remains
+one step before we can see these changes in the working directory.
+
+\subsection{Updating the working directory}
+
+We have so far glossed over the relationship between a repository and
+its working directory.  The \hgcmd{pull} command that we ran in
+section~\ref{sec:tour:pull} brought changes into the repository, but
+if we check, there's no sign of those changes in the working
+directory.  This is because \hgcmd{pull} does not (by default) touch
+the working directory.  Instead, we use the \hgcmd{update} command to
+do this.
+\interaction{tour.update}
+
+It might seem a bit strange that \hgcmd{pull} doesn't update the
+working directory automatically.  There's actually a good reason for
+this: you can use \hgcmd{update} to update the working directory to
+the state it was in at \emph{any revision} in the history of the
+repository.  If you had the working directory updated to an old
+revision---to hunt down the origin of a bug, say---and ran a
+\hgcmd{pull} which automatically updated the working directory to a
+new revision, you might not be terribly happy.
+
+However, since pull-then-update is such a common thing to do,
+Mercurial lets you combine the two by passing the \hgopt{pull}{-u}
+option to \hgcmd{pull}.
+\begin{codesample2}
+  hg pull -u
+\end{codesample2}
+If you look back at the output of \hgcmd{pull} in
+section~\ref{sec:tour:pull} when we ran it without \hgopt{pull}{-u},
+you can see that it printed a helpful reminder that we'd have to take
+an explicit step to update the working directory:
+\begin{codesample2}
+  (run 'hg update' to get a working copy)
+\end{codesample2}
+
+To find out what revision the working directory is at, use the
+\hgcmd{parents} command.
+\interaction{tour.parents}
+If you look back at figure~\ref{fig:tour-basic:history}, you'll see
+arrows connecting each changeset.  The node that the arrow leads
+\emph{from} in each case is a parent, and the node that the arrow
+leads \emph{to} is its child.  The working directory has a parent in
+just the same way; this is the changeset that the working directory
+currently contains.
+
+To update the working directory to a particular revision, give a
+revision number or changeset~ID to the \hgcmd{update} command.
+\interaction{tour.older}
+If you omit an explicit revision, \hgcmd{update} will update to the
+tip revision, as shown by the second call to \hgcmd{update} in the
+example above.
+
+\subsection{Pushing changes to another repository}
+
+Mercurial lets us push changes to another repository, from the
+repository we're currently visiting.  As with the example of
+\hgcmd{pull} above, we'll create a temporary repository to push our
+changes into.
+\interaction{tour.clone-push}
+The \hgcmd{outgoing} command tells us what changes would be pushed
+into another repository.
+\interaction{tour.outgoing}
+And the \hgcmd{push} command does the actual push.
+\interaction{tour.push}
+As with \hgcmd{pull}, the \hgcmd{push} command does not update the
+working directory in the repository that it's pushing changes into.
+(Unlike \hgcmd{pull}, \hgcmd{push} does not provide a \texttt{-u}
+option that updates the other repository's working directory.)
+
+What happens if we try to pull or push changes and the receiving
+repository already has those changes?  Nothing too exciting.
+\interaction{tour.push.nothing}
+
+\subsection{Sharing changes over a network}
+
+The commands we have covered in the previous few sections are not
+limited to working with local repositories.  Each works in exactly the
+same fashion over a network connection; simply pass in a URL instead
+of a local path.
+\interaction{tour.outgoing.net}
+In this example, we can see what changes we could push to the remote
+repository, but the repository is understandably not set up to let
+anonymous users push to it.
+\interaction{tour.push.net}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch02-tour-basic.xml	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,787 @@
+<!-- vim: set filetype=docbkxml shiftwidth=2 autoindent expandtab tw=77 : -->
+
+<chapter>
+  <title>A tour of Mercurial: the basics</title>
+  <para>\label{chap:tour-basic}</para>
+
+  <sect1>
+    <title>Installing Mercurial on your system</title>
+    <para>\label{sec:tour:install}</para>
+
+    <para>Prebuilt binary packages of Mercurial are available for
+      every popular operating system.  These make it easy to start
+      using Mercurial on your computer immediately.</para>
+
+    <sect2>
+      <title>Linux</title>
+
+      <para>Because each Linux distribution has its own packaging
+	tools, policies, and rate of development, it's difficult to
+	give a comprehensive set of instructions on how to install
+	Mercurial binaries.  The version of Mercurial that you will
+	end up with can vary depending on how active the person is who
+	maintains the package for your distribution.</para>
+
+      <para>To keep things simple, I will focus on installing
+	Mercurial from the command line under the most popular Linux
+	distributions.  Most of these distributions provide graphical
+	package managers that will let you install Mercurial with a
+	single click; the package name to look for is
+	<literal>mercurial</literal>.</para>
+
+      <itemizedlist>
+	<listitem><para>Debian:</para>
+	  <programlisting>apt-get install
+	    mercurial</programlisting></listitem>
+	<listitem><para>Fedora Core:</para>
+	  <programlisting>yum install
+	    mercurial</programlisting></listitem>
+	<listitem><para>Gentoo:</para>
+	  <programlisting>emerge mercurial</programlisting></listitem>
+	<listitem><para>OpenSUSE:</para>
+	  <programlisting>yum install
+	    mercurial</programlisting></listitem>
+	<listitem><para>Ubuntu: Ubuntu's Mercurial package is based on
+	    Debian's.  To install it, run the following
+	    command.</para>
+	  <programlisting>apt-get install
+	    mercurial</programlisting></listitem>
+      </itemizedlist>
+
+    </sect2>
+    <sect2>
+      <title>Solaris</title>
+
+      <para>SunFreeWare, at <ulink
+	  url="http://www.sunfreeware.com">http://www.sunfreeware.com</ulink>, 
+	is a good source for a large number of pre-built Solaris
+	packages for 32 and 64 bit Intel and Sparc architectures,
+	including current versions of Mercurial.</para>
+
+    </sect2>
+    <sect2>
+      <title>Mac OS X</title>
+
+      <para>Lee Cantey publishes an installer of Mercurial for Mac OS
+	X at <ulink
+	  url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>. 
+	This package works on both Intel- and Power-based Macs.
+	Before you can use it, you must install a compatible version
+	of Universal MacPython <citation>web:macpython</citation>.
+	This is easy to do; simply follow the instructions on Lee's
+	site.</para>
+
+      <para>It's also possible to install Mercurial using Fink or
+	MacPorts, two popular free package managers for Mac OS X.  If
+	you have Fink, use <command>sudo apt-get install
+	  mercurial-py25</command>.  If MacPorts, <command>sudo port
+	  install mercurial</command>.</para>
+
+    </sect2>
+    <sect2>
+      <title>Windows</title>
+
+      <para>Lee Cantey publishes an installer of Mercurial for Windows
+	at <ulink
+	  url="http://mercurial.berkwood.com">http://mercurial.berkwood.com</ulink>. 
+	This package has no external dependencies; it <quote>just
+	  works</quote>.</para>
+
+      <note>
+	<para>  The Windows version of Mercurial does not
+	  automatically convert line endings between Windows and Unix
+	  styles.  If you want to share work with Unix users, you must
+	  do a little additional configuration work. XXX Flesh this
+	  out.</para>
+      </note>
+
+    </sect2>
+  </sect1>
+  <sect1>
+    <title>Getting started</title>
+
+    <para>To begin, we'll use the <command role="hg-cmd">hg
+	version</command> command to find out whether Mercurial is
+      actually installed properly.  The actual version information
+      that it prints isn't so important; it's whether it prints
+      anything at all that we care about. <!--
+      &interaction.tour.version; --></para>
+
+    <sect2>
+      <title>Built-in help</title>
+
+      <para>Mercurial provides a built-in help system.  This is
+	invaluable for those times when you find yourself stuck trying
+	to remember how to run a command.  If you are completely
+	stuck, simply run <command role="hg-cmd">hg help</command>; it
+	will print a brief list of commands, along with a description
+	of what each does.  If you ask for help on a specific command
+	(as below), it prints more detailed information. <!--
+	&interaction.tour.help; --> For a more impressive level of
+	detail (which you won't usually need) run <command
+	  role="hg-cmd">hg help <option
+	    role="hg-opt-global">-v</option></command>.  The <option
+	  role="hg-opt-global">-v</option> option is short for <option
+	  role="hg-opt-global">--verbose</option>, and tells Mercurial
+	to print more information than it usually would.</para>
+
+    </sect2>
+  </sect1>
+  <sect1>
+    <title>Working with a repository</title>
+
+    <para>In Mercurial, everything happens inside a
+      <emphasis>repository</emphasis>.  The repository for a project
+      contains all of the files that <quote>belong to</quote> that
+      project, along with a historical record of the project's
+      files.</para>
+
+    <para>There's nothing particularly magical about a repository; it
+      is simply a directory tree in your filesystem that Mercurial
+      treats as special. You can rename or delete a repository any
+      time you like, using either the command line or your file
+      browser.</para>
+
+    <sect2>
+      <title>Making a local copy of a repository</title>
+
+      <para><emphasis>Copying</emphasis> a repository is just a little
+	bit special.  While you could use a normal file copying
+	command to make a copy of a repository, it's best to use a
+	built-in command that Mercurial provides.  This command is
+	called <command role="hg-cmd">hg clone</command>, because it
+	creates an identical copy of an existing repository. <!--
+	&interaction.tour.clone; --> If our clone succeeded, we should
+	now have a local directory called <filename
+	  class="directory">hello</filename>.  This directory will
+	contain some files. <!-- &interaction.tour.ls; --> These files
+	have the same contents and history in our repository as they
+	do in the repository we cloned.</para>
+
+      <para>Every Mercurial repository is complete, self-contained,
+	and independent.  It contains its own private copy of a
+	project's files and history.  A cloned repository remembers
+	the location of the repository it was cloned from, but it does
+	not communicate with that repository, or any other, unless you
+	tell it to.</para>
+
+      <para>What this means for now is that we're free to experiment
+	with our repository, safe in the knowledge that it's a private
+	<quote>sandbox</quote> that won't affect anyone else.</para>
+
+    </sect2>
+    <sect2>
+      <title>What's in a repository?</title>
+
+      <para>When we take a more detailed look inside a repository, we
+	can see that it contains a directory named <filename
+	  class="directory">.hg</filename>.  This is where Mercurial
+	keeps all of its metadata for the repository. <!--
+	&interaction.tour.ls-a; --></para>
+
+      <para>The contents of the <filename
+	  class="directory">.hg</filename> directory and its
+	subdirectories are private to Mercurial.  Every other file and
+	directory in the repository is yours to do with as you
+	please.</para>
+
+      <para>To introduce a little terminology, the <filename
+	  class="directory">.hg</filename> directory is the
+	<quote>real</quote> repository, and all of the files and
+	directories that coexist with it are said to live in the
+	<emphasis>working directory</emphasis>.  An easy way to
+	remember the distinction is that the
+	<emphasis>repository</emphasis> contains the
+	<emphasis>history</emphasis> of your project, while the
+	<emphasis>working directory</emphasis> contains a
+	<emphasis>snapshot</emphasis> of your project at a particular
+	point in history.</para>
+
+    </sect2>
+  </sect1>
+  <sect1>
+    <title>A tour through history</title>
+
+    <para>One of the first things we might want to do with a new,
+      unfamiliar repository is understand its history.  The <command
+	role="hg-cmd">hg log</command> command gives us a view of
+      history. <!-- &interaction.tour.log; --> By default, this
+      command prints a brief paragraph of output for each change to
+      the project that was recorded.  In Mercurial terminology, we
+      call each of these recorded events a
+      <emphasis>changeset</emphasis>, because it can contain a record
+      of changes to several files.</para>
+
+    <para>The fields in a record of output from <command
+	role="hg-cmd">hg log</command> are as follows.</para>
+    <itemizedlist>
+      <listitem><para><literal>changeset</literal>: This field has the
+	  format of a number, followed by a colon, followed by a
+	  hexadecimal string.  These are
+	  <emphasis>identifiers</emphasis> for the changeset.  There
+	  are two identifiers because the number is shorter and easier
+	  to type than the hex string.</para></listitem>
+      <listitem><para><literal>user</literal>: The identity of the
+	  person who created the changeset.  This is a free-form
+	  field, but it most often contains a person's name and email
+	  address.</para></listitem>
+      <listitem><para><literal>date</literal>: The date and time on
+	  which the changeset was created, and the timezone in which
+	  it was created.  (The date and time are local to that
+	  timezone; they display what time and date it was for the
+	  person who created the changeset.)</para></listitem>
+      <listitem><para><literal>summary</literal>: The first line of
+	  the text message that the creator of the changeset entered
+	  to describe the changeset.</para></listitem></itemizedlist>
+    <para>The default output printed by <command role="hg-cmd">hg
+	log</command> is purely a summary; it is missing a lot of
+      detail.</para>
+
+    <para>Figure <xref id="fig:tour-basic:history"/> provides a
+      graphical representation of the history of the <filename
+	class="directory">hello</filename> repository, to make it a
+      little easier to see which direction history is
+      <quote>flowing</quote> in.  We'll be returning to this figure
+      several times in this chapter and the chapter that
+      follows.</para>
+
+    <figure>
+
+      <para>  <mediaobject><imageobject><imagedata
+					  fileref="tour-history"/></imageobject><textobject><phrase>XXX 
+	      add text</phrase></textobject></mediaobject>
+	<caption>Graphical history of the <filename
+	  class="directory">hello</filename> repository</caption>
+	\label{fig:tour-basic:history}</para>
+    </figure>
+
+    <sect2>
+      <title>Changesets, revisions, and talking to other
+	people</title>
+
+      <para>As English is a notoriously sloppy language, and computer
+	science has a hallowed history of terminological confusion
+	(why use one term when four will do?), revision control has a
+	variety of words and phrases that mean the same thing.  If you
+	are talking about Mercurial history with other people, you
+	will find that the word <quote>changeset</quote> is often
+	compressed to <quote>change</quote> or (when written)
+	<quote>cset</quote>, and sometimes a changeset is referred to
+	as a <quote>revision</quote> or a <quote>rev</quote>.</para>
+
+      <para>While it doesn't matter what <emphasis>word</emphasis> you
+	use to refer to the concept of <quote>a changeset</quote>, the
+	<emphasis>identifier</emphasis> that you use to refer to
+	<quote>a <emphasis>specific</emphasis> changeset</quote> is of
+	great importance. Recall that the <literal>changeset</literal>
+	field in the output from <command role="hg-cmd">hg
+	  log</command> identifies a changeset using both a number and
+	a hexadecimal string.</para>
+      <itemizedlist>
+	<listitem><para>The revision number is <emphasis>only valid in
+	      that repository</emphasis>,</para></listitem>
+	<listitem><para>while the hex string is the
+	    <emphasis>permanent, unchanging identifier</emphasis> that
+	    will always identify that exact changeset in
+	    <emphasis>every</emphasis> copy of the
+	    repository.</para></listitem></itemizedlist>
+      <para>This distinction is important.  If you send someone an
+	email talking about <quote>revision 33</quote>, there's a high
+	likelihood that their revision 33 will <emphasis>not be the
+	  same</emphasis> as yours.  The reason for this is that a
+	revision number depends on the order in which changes arrived
+	in a repository, and there is no guarantee that the same
+	changes will happen in the same order in different
+	repositories. Three changes $a,b,c$ can easily appear in one
+	repository as $0,1,2$, while in another as $1,0,2$.</para>
+
+      <para>Mercurial uses revision numbers purely as a convenient
+	shorthand.  If you need to discuss a changeset with someone,
+	or make a record of a changeset for some other reason (for
+	example, in a bug report), use the hexadecimal
+	identifier.</para>
+
+    </sect2>
+    <sect2>
+      <title>Viewing specific revisions</title>
+
+      <para>To narrow the output of <command role="hg-cmd">hg
+	  log</command> down to a single revision, use the <option
+	  role="hg-opt-log">-r</option> (or <option
+	  role="hg-opt-log">--rev</option>) option.  You can use
+	either a revision number or a long-form changeset identifier,
+	and you can provide as many revisions as you want.  <!--
+	&interaction.tour.log-r; --></para>
+
+      <para>If you want to see the history of several revisions
+	without having to list each one, you can use <emphasis>range
+	  notation</emphasis>; this lets you express the idea <quote>I
+	  want all revisions between $a$ and $b$, inclusive</quote>.
+	<!-- &interaction.tour.log.range; --> Mercurial also honours
+	the order in which you specify revisions, so <command
+	  role="hg-cmd">hg log -r 2:4</command> prints $2,3,4$ while
+	<command role="hg-cmd">hg log -r 4:2</command> prints
+	$4,3,2$.</para>
+
+    </sect2>
+    <sect2>
+      <title>More detailed information</title>
+
+      <para>While the summary information printed by <command
+	  role="hg-cmd">hg log</command> is useful if you already know
+	what you're looking for, you may need to see a complete
+	description of the change, or a list of the files changed, if
+	you're trying to decide whether a changeset is the one you're
+	looking for. The <command role="hg-cmd">hg log</command>
+	command's <option role="hg-opt-global">-v</option> (or <option
+	  role="hg-opt-global">--verbose</option>) option gives you
+	this extra detail. <!-- &interaction.tour.log-v; --></para>
+
+      <para>If you want to see both the description and content of a
+	change, add the <option role="hg-opt-log">-p</option> (or
+	<option role="hg-opt-log">--patch</option>) option.  This
+	displays the content of a change as a <emphasis>unified
+	  diff</emphasis> (if you've never seen a unified diff before,
+	see section <xref id="sec:mq:patch"/> for an
+	overview). <!-- &interaction.tour.log-vp; --></para>
+
+    </sect2>
+  </sect1>
+  <sect1>
+    <title>All about command options</title>
+
+    <para>Let's take a brief break from exploring Mercurial commands
+      to discuss a pattern in the way that they work; you may find
+      this useful to keep in mind as we continue our tour.</para>
+
+    <para>Mercurial has a consistent and straightforward approach to
+      dealing with the options that you can pass to commands.  It
+      follows the conventions for options that are common to modern
+      Linux and Unix systems.</para>
+    <itemizedlist>
+      <listitem><para>Every option has a long name.  For example, as
+	  we've already seen, the <command role="hg-cmd">hg
+	    log</command> command accepts a <option
+	    role="hg-opt-log">--rev</option> option.</para></listitem>
+      <listitem><para>Most options have short names, too.  Instead of
+	  <option role="hg-opt-log">--rev</option>, we can use <option
+	    role="hg-opt-log">-r</option>.  (The reason that some
+	  options don't have short names is that the options in
+	  question are rarely used.)</para></listitem>
+      <listitem><para>Long options start with two dashes (e.g. <option
+	    role="hg-opt-log">--rev</option>), while short options
+	  start with one (e.g. <option
+	    role="hg-opt-log">-r</option>).</para></listitem>
+      <listitem><para>Option naming and usage is consistent across
+	  commands.  For example, every command that lets you specify
+	  a changeset ID or revision number accepts both <option
+	    role="hg-opt-log">-r</option> and <option
+	    role="hg-opt-log">--rev</option>
+	  arguments.</para></listitem></itemizedlist>
+    <para>In the examples throughout this book, I use short options
+      instead of long.  This just reflects my own preference, so don't
+      read anything significant into it.</para>
+
+    <para>Most commands that print output of some kind will print more
+      output when passed a <option role="hg-opt-global">-v</option>
+      (or <option role="hg-opt-global">--verbose</option>) option, and
+      less when passed <option role="hg-opt-global">-q</option> (or
+      <option role="hg-opt-global">--quiet</option>).</para>
+
+  </sect1>
+  <sect1>
+    <title>Making and reviewing changes</title>
+
+    <para>Now that we have a grasp of viewing history in Mercurial,
+      let's take a look at making some changes and examining
+      them.</para>
+
+    <para>The first thing we'll do is isolate our experiment in a
+      repository of its own.  We use the <command role="hg-cmd">hg
+	clone</command> command, but we don't need to clone a copy of
+      the remote repository.  Since we already have a copy of it
+      locally, we can just clone that instead.  This is much faster
+      than cloning over the network, and cloning a local repository
+      uses less disk space in most cases, too. <!--
+      &interaction.tour.reclone; --> As an aside, it's often good
+      practice to keep a <quote>pristine</quote> copy of a remote
+      repository around, which you can then make temporary clones of
+      to create sandboxes for each task you want to work on.  This
+      lets you work on multiple tasks in parallel, each isolated from
+      the others until it's complete and you're ready to integrate it
+      back.  Because local clones are so cheap, there's almost no
+      overhead to cloning and destroying repositories whenever you
+      want.</para>
+
+    <para>In our <filename class="directory">my-hello</filename>
+      repository, we have a file <filename>hello.c</filename> that
+      contains the classic <quote>hello, world</quote> program. Let's
+      use the ancient and venerable <command>sed</command> command to
+      edit this file so that it prints a second line of output.  (I'm
+      only using <command>sed</command> to do this because it's easy
+      to write a scripted example this way.  Since you're not under
+      the same constraint, you probably won't want to use
+      <command>sed</command>; simply use your preferred text editor to
+      do the same thing.) <!-- &interaction.tour.sed; --></para>
+
+    <para>Mercurial's <command role="hg-cmd">hg status</command>
+      command will tell us what Mercurial knows about the files in the
+      repository. <!-- &interaction.tour.status; --> The <command
+	role="hg-cmd">hg status</command> command prints no output for
+      some files, but a line starting with
+      <quote><literal>M</literal></quote> for
+      <filename>hello.c</filename>.  Unless you tell it to, <command
+	role="hg-cmd">hg status</command> will not print any output
+      for files that have not been modified.</para>
+
+    <para>The <quote><literal>M</literal></quote> indicates that
+      Mercurial has noticed that we modified
+      <filename>hello.c</filename>.  We didn't need to
+      <emphasis>inform</emphasis> Mercurial that we were going to
+      modify the file before we started, or that we had modified the
+      file after we were done; it was able to figure this out
+      itself.</para>
+
+    <para>It's a little bit helpful to know that we've modified
+      <filename>hello.c</filename>, but we might prefer to know
+      exactly <emphasis>what</emphasis> changes we've made to it.  To
+      do this, we use the <command role="hg-cmd">hg diff</command>
+      command. <!-- &interaction.tour.diff; --></para>
+
+  </sect1>
+  <sect1>
+    <title>Recording changes in a new changeset</title>
+
+    <para>We can modify files, build and test our changes, and use
+      <command role="hg-cmd">hg status</command> and <command
+	role="hg-cmd">hg diff</command> to review our changes, until
+      we're satisfied with what we've done and arrive at a natural
+      stopping point where we want to record our work in a new
+      changeset.</para>
+
+    <para>The <command role="hg-cmd">hg commit</command> command lets
+      us create a new changeset; we'll usually refer to this as
+      <quote>making a commit</quote> or
+      <quote>committing</quote>.</para>
+
+    <sect2>
+      <title>Setting up a username</title>
+
+      <para>When you try to run <command role="hg-cmd">hg
+	  commit</command> for the first time, it is not guaranteed to
+	succeed.  Mercurial records your name and address with each
+	change that you commit, so that you and others will later be
+	able to tell who made each change.  Mercurial tries to
+	automatically figure out a sensible username to commit the
+	change with.  It will attempt each of the following methods,
+	in order:</para>
+      <orderedlist>
+	<listitem><para>If you specify a <option
+	      role="hg-opt-commit">-u</option> option to the <command
+	      role="hg-cmd">hg commit</command> command on the command
+	    line, followed by a username, this is always given the
+	    highest precedence.</para></listitem>
+	<listitem><para>If you have set the <envar>HGUSER</envar>
+	    environment variable, this is checked
+	    next.</para></listitem>
+	<listitem><para>If you create a file in your home directory
+	    called <filename role="special">.hgrc</filename>, with a
+	    <envar role="rc-item-ui">username</envar> entry, that will
+	    be used next.  To see what the contents of this file
+	    should look like, refer to section <xref
+	      id="sec:tour-basic:username"/>
+	    below.</para></listitem>
+	<listitem><para>If you have set the <envar>EMAIL</envar>
+	    environment variable, this will be used
+	    next.</para></listitem>
+	<listitem><para>Mercurial will query your system to find out
+	    your local user name and host name, and construct a
+	    username from these components. Since this often results
+	    in a username that is not very useful, it will print a
+	    warning if it has to do
+	    this.</para></listitem></orderedlist>
+      <listitem><para>If all of these mechanisms fail, Mercurial will
+	  fail, printing an error message.  In this case, it will not
+	  let you commit until you set up a
+	  username.</para></listitem>
+      <listitem><para>You should think of the <envar>HGUSER</envar>
+	  environment variable and the <option
+	    role="hg-opt-commit">-u</option> option to the <command
+	    role="hg-cmd">hg commit</command> command as ways to
+	  <emphasis>override</emphasis> Mercurial's default selection
+	  of username.  For normal use, the simplest and most robust
+	  way to set a username for yourself is by creating a
+	  <filename role="special">.hgrc</filename> file; see below
+	  for details.</para></listitem>
+      <sect3>
+	<title>Creating a Mercurial configuration file</title>
+	<listitem><para>\label{sec:tour-basic:username}</para></listitem>
+	<listitem><para>To set a user name, use your favourite editor
+	    to create a file called <filename
+	      role="special">.hgrc</filename> in your home directory.
+	    Mercurial will use this file to look up your personalised
+	    configuration settings.  The initial contents of your
+	    <filename role="special">.hgrc</filename> should look like
+	    this.</para></listitem><programlisting>
+	  <listitem><para>  # This is a Mercurial configuration file.
+	      [ui] username = Firstname Lastname
+	      &lt;email.address@domain.net&gt;</para></listitem></programlisting>
+	<listitem><para>The <quote><literal>[ui]</literal></quote>
+	    line begins a <emphasis>section</emphasis> of the config
+	    file, so you can read the <quote><literal>username =
+		...</literal></quote> line as meaning <quote>set the
+	      value of the <literal>username</literal> item in the
+	      <literal>ui</literal> section</quote>. A section
+	    continues until a new section begins, or the end of the
+	    file.  Mercurial ignores empty lines and treats any text
+	    from <quote><literal>#</literal></quote> to the end of a
+	    line as a comment.</para></listitem>
+      </sect3>
+      <sect3>
+	<title>Choosing a user name</title>
+
+	<listitem><para>You can use any text you like as the value of
+	    the <literal>username</literal> config item, since this
+	    information is for reading by other people, but for
+	    interpreting by Mercurial.  The convention that most
+	    people follow is to use their name and email address, as
+	    in the example above.</para></listitem>
+	<note>
+	  <listitem><para>  Mercurial's built-in web server obfuscates
+	      email addresses, to make it more difficult for the email
+	      harvesting tools that spammers use. This reduces the
+	      likelihood that you'll start receiving more junk email
+	      if you publish a Mercurial repository on the
+	      web.</para></listitem></note>
+
+      </sect3>
+    </sect2>
+    <sect2>
+      <title>Writing a commit message</title>
+
+      <listitem><para>When we commit a change, Mercurial drops us into
+	  a text editor, to enter a message that will describe the
+	  modifications we've made in this changeset.  This is called
+	  the <emphasis>commit message</emphasis>.  It will be a
+	  record for readers of what we did and why, and it will be
+	  printed by <command role="hg-cmd">hg log</command> after
+	  we've finished committing. <!-- &interaction.tour.commit;
+	  --></para></listitem>
+      <listitem><para>The editor that the <command role="hg-cmd">hg
+	    commit</command> command drops us into will contain an
+	  empty line, followed by a number of lines starting with
+	  <quote><literal>HG:</literal></quote>.</para></listitem><programlisting>
+	<listitem><para>  <emphasis>empty line</emphasis> HG: changed
+	    hello.c</para></listitem></programlisting>
+      <listitem><para>Mercurial ignores the lines that start with
+	  <quote><literal>HG:</literal></quote>; it uses them only to
+	  tell us which files it's recording changes to.  Modifying or
+	  deleting these lines has no effect.</para></listitem>
+    </sect2>
+    <sect2>
+      <title>Writing a good commit message</title>
+
+      <listitem><para>Since <command role="hg-cmd">hg log</command>
+	  only prints the first line of a commit message by default,
+	  it's best to write a commit message whose first line stands
+	  alone.  Here's a real example of a commit message that
+	  <emphasis>doesn't</emphasis> follow this guideline, and
+	  hence has a summary that is not
+	  readable.</para></listitem><programlisting>
+	<listitem><para>  changeset:   73:584af0e231be user: Censored
+	    Person &lt;censored.person@example.org&gt; date: Tue Sep
+	    26 21:37:07 2006 -0700 summary:     include
+	    buildmeister/commondefs.   Add an exports and
+	    install</para></listitem></programlisting>
+
+      <listitem><para>As far as the remainder of the contents of the
+	  commit message are concerned, there are no hard-and-fast
+	  rules.  Mercurial itself doesn't interpret or care about the
+	  contents of the commit message, though your project may have
+	  policies that dictate a certain kind of
+	  formatting.</para></listitem>
+      <listitem><para>My personal preference is for short, but
+	  informative, commit messages that tell me something that I
+	  can't figure out with a quick glance at the output of
+	  <command role="hg-cmd">hg log
+	    --patch</command>.</para></listitem>
+    </sect2>
+    <sect2>
+      <title>Aborting a commit</title>
+
+      <listitem><para>If you decide that you don't want to commit
+	  while in the middle of editing a commit message, simply exit
+	  from your editor without saving the file that it's editing.
+	  This will cause nothing to happen to either the repository
+	  or the working directory.</para></listitem>
+      <listitem><para>If we run the <command role="hg-cmd">hg
+	    commit</command> command without any arguments, it records
+	  all of the changes we've made, as reported by <command
+	    role="hg-cmd">hg status</command> and <command
+	    role="hg-cmd">hg diff</command>.</para></listitem>
+    </sect2>
+    <sect2>
+      <title>Admiring our new handiwork</title>
+
+      <listitem><para>Once we've finished the commit, we can use the
+	  <command role="hg-cmd">hg tip</command> command to display
+	  the changeset we just created.  This command produces output
+	  that is identical to <command role="hg-cmd">hg
+	    log</command>, but it only displays the newest revision in
+	  the repository. <!-- &interaction.tour.tip; --> We refer to
+	  the newest revision in the repository as the tip revision,
+	  or simply the tip.</para></listitem>
+    </sect2>
+  </sect1>
+  <sect1>
+    <title>Sharing changes</title>
+
+    <listitem><para>We mentioned earlier that repositories in
+	Mercurial are self-contained.  This means that the changeset
+	we just created exists only in our <filename
+	  class="directory">my-hello</filename> repository.  Let's
+	look at a few ways that we can propagate this change into
+	other repositories.</para></listitem>
+    <sect2>
+      <title>Pulling changes from another repository</title>
+      <listitem><para>\label{sec:tour:pull}</para></listitem>
+      <listitem><para>To get started, let's clone our original
+	  <filename class="directory">hello</filename> repository,
+	  which does not contain the change we just committed.  We'll
+	  call our temporary repository <filename
+	    class="directory">hello-pull</filename>. <!--
+	  &interaction.tour.clone-pull; --></para></listitem>
+      <listitem><para>We'll use the <command role="hg-cmd">hg
+	    pull</command> command to bring changes from <filename
+	    class="directory">my-hello</filename> into <filename
+	    class="directory">hello-pull</filename>.  However, blindly
+	  pulling unknown changes into a repository is a somewhat
+	  scary prospect.  Mercurial provides the <command
+	    role="hg-cmd">hg incoming</command> command to tell us
+	  what changes the <command role="hg-cmd">hg pull</command>
+	  command <emphasis>would</emphasis> pull into the repository,
+	  without actually pulling the changes in. <!--
+	  &interaction.tour.incoming; --> (Of course, someone could
+	  cause more changesets to appear in the repository that we
+	  ran <command role="hg-cmd">hg incoming</command> in, before
+	  we get a chance to <command role="hg-cmd">hg pull</command>
+	  the changes, so that we could end up pulling changes that we
+	  didn't expect.)</para></listitem>
+      <listitem><para>Bringing changes into a repository is a simple
+	  matter of running the <command role="hg-cmd">hg
+	    pull</command> command, and telling it which repository to
+	  pull from. <!-- &interaction.tour.pull; --> As you can see
+	  from the before-and-after output of <command
+	    role="hg-cmd">hg tip</command>, we have successfully
+	  pulled changes into our repository.  There remains one step
+	  before we can see these changes in the working
+	  directory.</para></listitem>
+    </sect2>
+    <sect2>
+      <title>Updating the working directory</title>
+
+      <listitem><para>We have so far glossed over the relationship
+	  between a repository and its working directory.  The
+	  <command role="hg-cmd">hg pull</command> command that we ran
+	  in section <xref id="sec:tour:pull"/> brought changes into
+	  the
+	  repository, but if we check, there's no sign of those
+	  changes in the working directory.  This is because <command
+	    role="hg-cmd">hg pull</command> does not (by default)
+	  touch the working directory.  Instead, we use the <command
+	    role="hg-cmd">hg update</command> command to do this. <!--
+	  &interaction.tour.update; --></para></listitem>
+      <listitem><para>It might seem a bit strange that <command
+	    role="hg-cmd">hg pull</command> doesn't update the working
+	  directory automatically.  There's actually a good reason for
+	  this: you can use <command role="hg-cmd">hg update</command>
+	  to update the working directory to the state it was in at
+	  <emphasis>any revision</emphasis> in the history of the
+	  repository.  If you had the working directory updated to an
+	  old revision---to hunt down the origin of a bug, say---and
+	  ran a <command role="hg-cmd">hg pull</command> which
+	  automatically updated the working directory to a new
+	  revision, you might not be terribly happy.</para></listitem>
+      <listitem><para>However, since pull-then-update is such a common
+	  thing to do, Mercurial lets you combine the two by passing
+	  the <option role="hg-opt-pull">-u</option> option to
+	  <command role="hg-cmd">hg
+	    pull</command>.</para></listitem><programlisting>
+	<listitem><para>  hg pull
+	    -u</para></listitem></programlisting>
+      <listitem><para>If you look back at the output of <command
+	    role="hg-cmd">hg pull</command> in section <xref
+	    id="sec:tour:pull"/> when we ran it without <option
+	    role="hg-opt-pull">-u</option>, you can see that it
+	  printed a helpful reminder that we'd have to take an
+	  explicit step to update the working
+	  directory:</para></listitem><programlisting>
+	<listitem><para>  (run 'hg update' to get a working
+	    copy)</para></listitem></programlisting>
+
+      <listitem><para>To find out what revision the working directory
+	  is at, use the <command role="hg-cmd">hg parents</command>
+	  command. <!-- &interaction.tour.parents; --> If you look
+	  back at figure <xref id="fig:tour-basic:history"/>, you'll
+	  see arrows connecting each changeset.  The node that the
+	  arrow leads <emphasis>from</emphasis> in each case is a
+	  parent, and the node that the arrow leads
+	  <emphasis>to</emphasis> is its child.  The working directory
+	  has a parent in just the same way; this is the changeset
+	  that the working directory currently
+	  contains.</para></listitem>
+      <listitem><para>To update the working directory to a particular
+	  revision, give a revision number or changeset ID to the
+	  <command role="hg-cmd">hg update</command> command. <!--
+	  &interaction.tour.older; --> If you omit an explicit
+	  revision, <command role="hg-cmd">hg update</command> will
+	  update to the tip revision, as shown by the second call to
+	  <command role="hg-cmd">hg update</command> in the example
+	  above.</para></listitem>
+    </sect2>
+    <sect2>
+      <title>Pushing changes to another repository</title>
+
+      <listitem><para>Mercurial lets us push changes to another
+	  repository, from the repository we're currently visiting.
+	  As with the example of <command role="hg-cmd">hg
+	    pull</command> above, we'll create a temporary repository
+	  to push our changes into. <!-- &interaction.tour.clone-push;
+	  --> The <command role="hg-cmd">hg outgoing</command> command
+	  tells us what changes would be pushed into another
+	  repository. <!-- &interaction.tour.outgoing; --> And the
+	  <command role="hg-cmd">hg push</command> command does the
+	  actual push. <!-- &interaction.tour.push; --> As with
+	  <command role="hg-cmd">hg pull</command>, the <command
+	    role="hg-cmd">hg push</command> command does not update
+	  the working directory in the repository that it's pushing
+	  changes into. (Unlike <command role="hg-cmd">hg
+	    pull</command>, <command role="hg-cmd">hg push</command>
+	  does not provide a <literal>-u</literal> option that updates
+	  the other repository's working directory.)</para></listitem>
+      <listitem><para>What happens if we try to pull or push changes
+	  and the receiving repository already has those changes?
+	  Nothing too exciting. <!-- &interaction.tour.push.nothing;
+	  --></para></listitem>
+    </sect2>
+    <sect2>
+      <title>Sharing changes over a network</title>
+
+      <listitem><para>The commands we have covered in the previous few
+	  sections are not limited to working with local repositories.
+	  Each works in exactly the same fashion over a network
+	  connection; simply pass in a URL instead of a local path.
+	  <!-- &interaction.tour.outgoing.net; --> In this example, we
+	  can see what changes we could push to the remote repository,
+	  but the repository is understandably not set up to let
+	  anonymous users push to it. <!-- &interaction.tour.push.net;
+	  --></para></listitem>
+    </sect2>
+  </sect1>
+</chapter>
+
+<!--
+local variables: 
+sgml-parent-document: ("00book.xml" "book" "chapter")
+end:
+-->
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch03-tour-merge.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,285 @@
+\chapter{A tour of Mercurial: merging work}
+\label{chap:tour-merge}
+
+We've now covered cloning a repository, making changes in a
+repository, and pulling or pushing changes from one repository into
+another.  Our next step is \emph{merging} changes from separate
+repositories.
+
+\section{Merging streams of work}
+
+Merging is a fundamental part of working with a distributed revision
+control tool.
+\begin{itemize}
+\item Alice and Bob each have a personal copy of a repository for a
+  project they're collaborating on.  Alice fixes a bug in her
+  repository; Bob adds a new feature in his.  They want the shared
+  repository to contain both the bug fix and the new feature.
+\item I frequently work on several different tasks for a single
+  project at once, each safely isolated in its own repository.
+  Working this way means that I often need to merge one piece of my
+  own work with another.
+\end{itemize}
+
+Because merging is such a common thing to need to do, Mercurial makes
+it easy.  Let's walk through the process.  We'll begin by cloning yet
+another repository (see how often they spring up?) and making a change
+in it.
+\interaction{tour.merge.clone}
+We should now have two copies of \filename{hello.c} with different
+contents.  The histories of the two repositories have also diverged,
+as illustrated in figure~\ref{fig:tour-merge:sep-repos}.
+\interaction{tour.merge.cat}
+
+\begin{figure}[ht]
+  \centering
+  \grafix{tour-merge-sep-repos}
+  \caption{Divergent recent histories of the \dirname{my-hello} and
+    \dirname{my-new-hello} repositories}
+  \label{fig:tour-merge:sep-repos}
+\end{figure}
+
+We already know that pulling changes from our \dirname{my-hello}
+repository will have no effect on the working directory.
+\interaction{tour.merge.pull}
+However, the \hgcmd{pull} command says something about ``heads''.  
+
+\subsection{Head changesets}
+
+A head is a change that has no descendants, or children, as they're
+also known.  The tip revision is thus a head, because the newest
+revision in a repository doesn't have any children, but a repository
+can contain more than one head.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{tour-merge-pull}
+  \caption{Repository contents after pulling from \dirname{my-hello} into
+    \dirname{my-new-hello}}
+  \label{fig:tour-merge:pull}
+\end{figure}
+
+In figure~\ref{fig:tour-merge:pull}, you can see the effect of the
+pull from \dirname{my-hello} into \dirname{my-new-hello}.  The history
+that was already present in \dirname{my-new-hello} is untouched, but a
+new revision has been added.  By referring to
+figure~\ref{fig:tour-merge:sep-repos}, we can see that the
+\emph{changeset ID} remains the same in the new repository, but the
+\emph{revision number} has changed.  (This, incidentally, is a fine
+example of why it's not safe to use revision numbers when discussing
+changesets.)  We can view the heads in a repository using the
+\hgcmd{heads} command.
+\interaction{tour.merge.heads}
+
+\subsection{Performing the merge}
+
+What happens if we try to use the normal \hgcmd{update} command to
+update to the new tip?
+\interaction{tour.merge.update}
+Mercurial is telling us that the \hgcmd{update} command won't do a
+merge; it won't update the working directory when it thinks we might
+be wanting to do a merge, unless we force it to do so.  Instead, we
+use the \hgcmd{merge} command to merge the two heads.
+\interaction{tour.merge.merge}
+
+\begin{figure}[ht]
+  \centering
+  \grafix{tour-merge-merge}
+  \caption{Working directory and repository during merge, and following commit}
+  \label{fig:tour-merge:merge}
+\end{figure}
+
+This updates the working directory so that it contains changes from
+\emph{both} heads, which is reflected in both the output of
+\hgcmd{parents} and the contents of \filename{hello.c}.
+\interaction{tour.merge.parents}
+
+\subsection{Committing the results of the merge}
+
+Whenever we've done a merge, \hgcmd{parents} will display two parents
+until we \hgcmd{commit} the results of the merge.
+\interaction{tour.merge.commit}
+We now have a new tip revision; notice that it has \emph{both} of
+our former heads as its parents.  These are the same revisions that
+were previously displayed by \hgcmd{parents}.
+\interaction{tour.merge.tip}
+In figure~\ref{fig:tour-merge:merge}, you can see a representation of
+what happens to the working directory during the merge, and how this
+affects the repository when the commit happens.  During the merge, the
+working directory has two parent changesets, and these become the
+parents of the new changeset.
+
+\section{Merging conflicting changes}
+
+Most merges are simple affairs, but sometimes you'll find yourself
+merging changes where each modifies the same portions of the same
+files.  Unless both modifications are identical, this results in a
+\emph{conflict}, where you have to decide how to reconcile the
+different changes into something coherent.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{tour-merge-conflict}
+  \caption{Conflicting changes to a document}
+  \label{fig:tour-merge:conflict}
+\end{figure}
+
+Figure~\ref{fig:tour-merge:conflict} illustrates an instance of two
+conflicting changes to a document.  We started with a single version
+of the file; then we made some changes; while someone else made
+different changes to the same text.  Our task in resolving the
+conflicting changes is to decide what the file should look like.
+
+Mercurial doesn't have a built-in facility for handling conflicts.
+Instead, it runs an external program called \command{hgmerge}.  This
+is a shell script that is bundled with Mercurial; you can change it to
+behave however you please.  What it does by default is try to find one
+of several different merging tools that are likely to be installed on
+your system.  It first tries a few fully automatic merging tools; if
+these don't succeed (because the resolution process requires human
+guidance) or aren't present, the script tries a few different
+graphical merging tools.
+
+It's also possible to get Mercurial to run another program or script
+instead of \command{hgmerge}, by setting the \envar{HGMERGE}
+environment variable to the name of your preferred program.
+
+\subsection{Using a graphical merge tool}
+
+My preferred graphical merge tool is \command{kdiff3}, which I'll use
+to describe the features that are common to graphical file merging
+tools.  You can see a screenshot of \command{kdiff3} in action in
+figure~\ref{fig:tour-merge:kdiff3}.  The kind of merge it is
+performing is called a \emph{three-way merge}, because there are three
+different versions of the file of interest to us.  The tool thus
+splits the upper portion of the window into three panes:
+\begin{itemize}
+\item At the left is the \emph{base} version of the file, i.e.~the
+  most recent version from which the two versions we're trying to
+  merge are descended.
+\item In the middle is ``our'' version of the file, with the contents
+  that we modified.
+\item On the right is ``their'' version of the file, the one that
+  from the changeset that we're trying to merge with.
+\end{itemize}
+In the pane below these is the current \emph{result} of the merge.
+Our task is to replace all of the red text, which indicates unresolved
+conflicts, with some sensible merger of the ``ours'' and ``theirs''
+versions of the file.
+
+All four of these panes are \emph{locked together}; if we scroll
+vertically or horizontally in any of them, the others are updated to
+display the corresponding sections of their respective files.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{kdiff3}
+  \caption{Using \command{kdiff3} to merge versions of a file}
+  \label{fig:tour-merge:kdiff3}
+\end{figure}
+
+For each conflicting portion of the file, we can choose to resolve
+the conflict using some combination of text from the base version,
+ours, or theirs.  We can also manually edit the merged file at any
+time, in case we need to make further modifications.
+
+There are \emph{many} file merging tools available, too many to cover
+here.  They vary in which platforms they are available for, and in
+their particular strengths and weaknesses.  Most are tuned for merging
+files containing plain text, while a few are aimed at specialised file
+formats (generally XML).
+
+\subsection{A worked example}
+
+In this example, we will reproduce the file modification history of
+figure~\ref{fig:tour-merge:conflict} above.  Let's begin by creating a
+repository with a base version of our document.
+\interaction{tour-merge-conflict.wife}
+We'll clone the repository and make a change to the file.
+\interaction{tour-merge-conflict.cousin}
+And another clone, to simulate someone else making a change to the
+file.  (This hints at the idea that it's not all that unusual to merge
+with yourself when you isolate tasks in separate repositories, and
+indeed to find and resolve conflicts while doing so.)
+\interaction{tour-merge-conflict.son}
+Having created two different versions of the file, we'll set up an
+environment suitable for running our merge.
+\interaction{tour-merge-conflict.pull}
+
+In this example, I won't use Mercurial's normal \command{hgmerge}
+program to do the merge, because it would drop my nice automated
+example-running tool into a graphical user interface.  Instead, I'll
+set \envar{HGMERGE} to tell Mercurial to use the non-interactive
+\command{merge} command.  This is bundled with many Unix-like systems.
+If you're following this example on your computer, don't bother
+setting \envar{HGMERGE}.
+
+\textbf{XXX FIX THIS EXAMPLE.}
+
+\interaction{tour-merge-conflict.merge}
+Because \command{merge} can't resolve the conflicting changes, it
+leaves \emph{merge markers} inside the file that has conflicts,
+indicating which lines have conflicts, and whether they came from our
+version of the file or theirs.
+
+Mercurial can tell from the way \command{merge} exits that it wasn't
+able to merge successfully, so it tells us what commands we'll need to
+run if we want to redo the merging operation.  This could be useful
+if, for example, we were running a graphical merge tool and quit
+because we were confused or realised we had made a mistake.
+
+If automatic or manual merges fail, there's nothing to prevent us from
+``fixing up'' the affected files ourselves, and committing the results
+of our merge:
+\interaction{tour-merge-conflict.commit}
+
+\section{Simplifying the pull-merge-commit sequence}
+\label{sec:tour-merge:fetch}
+
+The process of merging changes as outlined above is straightforward,
+but requires running three commands in sequence.
+\begin{codesample2}
+  hg pull
+  hg merge
+  hg commit -m 'Merged remote changes'
+\end{codesample2}
+In the case of the final commit, you also need to enter a commit
+message, which is almost always going to be a piece of uninteresting
+``boilerplate'' text.
+
+It would be nice to reduce the number of steps needed, if this were
+possible.  Indeed, Mercurial is distributed with an extension called
+\hgext{fetch} that does just this.
+
+Mercurial provides a flexible extension mechanism that lets people
+extend its functionality, while keeping the core of Mercurial small
+and easy to deal with.  Some extensions add new commands that you can
+use from the command line, while others work ``behind the scenes,''
+for example adding capabilities to the server.
+
+The \hgext{fetch} extension adds a new command called, not
+surprisingly, \hgcmd{fetch}.  This extension acts as a combination of
+\hgcmd{pull}, \hgcmd{update} and \hgcmd{merge}.  It begins by pulling
+changes from another repository into the current repository.  If it
+finds that the changes added a new head to the repository, it begins a
+merge, then commits the result of the merge with an
+automatically-generated commit message.  If no new heads were added,
+it updates the working directory to the new tip changeset.
+
+Enabling the \hgext{fetch} extension is easy.  Edit your
+\sfilename{.hgrc}, and either go to the \rcsection{extensions} section
+or create an \rcsection{extensions} section.  Then add a line that
+simply reads ``\Verb+fetch +''.
+\begin{codesample2}
+  [extensions]
+  fetch =
+\end{codesample2}
+(Normally, on the right-hand side of the ``\texttt{=}'' would appear
+the location of the extension, but since the \hgext{fetch} extension
+is in the standard distribution, Mercurial knows where to search for
+it.)
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch04-concepts.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,574 @@
+\chapter{Behind the scenes}
+\label{chap:concepts}
+
+Unlike many revision control systems, the concepts upon which
+Mercurial is built are simple enough that it's easy to understand how
+the software really works.  Knowing this certainly isn't necessary,
+but I find it useful to have a ``mental model'' of what's going on.
+
+This understanding gives me confidence that Mercurial has been
+carefully designed to be both \emph{safe} and \emph{efficient}.  And
+just as importantly, if it's easy for me to retain a good idea of what
+the software is doing when I perform a revision control task, I'm less
+likely to be surprised by its behaviour.
+
+In this chapter, we'll initially cover the core concepts behind
+Mercurial's design, then continue to discuss some of the interesting
+details of its implementation.
+
+\section{Mercurial's historical record}
+
+\subsection{Tracking the history of a single file}
+
+When Mercurial tracks modifications to a file, it stores the history
+of that file in a metadata object called a \emph{filelog}.  Each entry
+in the filelog contains enough information to reconstruct one revision
+of the file that is being tracked.  Filelogs are stored as files in
+the \sdirname{.hg/store/data} directory.  A filelog contains two kinds
+of information: revision data, and an index to help Mercurial to find
+a revision efficiently.
+
+A file that is large, or has a lot of history, has its filelog stored
+in separate data (``\texttt{.d}'' suffix) and index (``\texttt{.i}''
+suffix) files.  For small files without much history, the revision
+data and index are combined in a single ``\texttt{.i}'' file.  The
+correspondence between a file in the working directory and the filelog
+that tracks its history in the repository is illustrated in
+figure~\ref{fig:concepts:filelog}.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{filelog}
+  \caption{Relationships between files in working directory and filelogs in repository}
+  \label{fig:concepts:filelog}
+\end{figure}
+
+\subsection{Managing tracked files}
+
+Mercurial uses a structure called a \emph{manifest} to collect
+together information about the files that it tracks.  Each entry in
+the manifest contains information about the files present in a single
+changeset.  An entry records which files are present in the changeset,
+the revision of each file, and a few other pieces of file metadata.
+
+\subsection{Recording changeset information}
+
+The \emph{changelog} contains information about each changeset.  Each
+revision records who committed a change, the changeset comment, other
+pieces of changeset-related information, and the revision of the
+manifest to use.
+
+\subsection{Relationships between revisions}
+
+Within a changelog, a manifest, or a filelog, each revision stores a
+pointer to its immediate parent (or to its two parents, if it's a
+merge revision).  As I mentioned above, there are also relationships
+between revisions \emph{across} these structures, and they are
+hierarchical in nature.
+
+For every changeset in a repository, there is exactly one revision
+stored in the changelog.  Each revision of the changelog contains a
+pointer to a single revision of the manifest.  A revision of the
+manifest stores a pointer to a single revision of each filelog tracked
+when that changeset was created.  These relationships are illustrated
+in figure~\ref{fig:concepts:metadata}.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{metadata}
+  \caption{Metadata relationships}
+  \label{fig:concepts:metadata}
+\end{figure}
+
+As the illustration shows, there is \emph{not} a ``one to one''
+relationship between revisions in the changelog, manifest, or filelog.
+If the manifest hasn't changed between two changesets, the changelog
+entries for those changesets will point to the same revision of the
+manifest.  If a file that Mercurial tracks hasn't changed between two
+changesets, the entry for that file in the two revisions of the
+manifest will point to the same revision of its filelog.
+
+\section{Safe, efficient storage}
+
+The underpinnings of changelogs, manifests, and filelogs are provided
+by a single structure called the \emph{revlog}.
+
+\subsection{Efficient storage}
+
+The revlog provides efficient storage of revisions using a
+\emph{delta} mechanism.  Instead of storing a complete copy of a file
+for each revision, it stores the changes needed to transform an older
+revision into the new revision.  For many kinds of file data, these
+deltas are typically a fraction of a percent of the size of a full
+copy of a file.
+
+Some obsolete revision control systems can only work with deltas of
+text files.  They must either store binary files as complete snapshots
+or encoded into a text representation, both of which are wasteful
+approaches.  Mercurial can efficiently handle deltas of files with
+arbitrary binary contents; it doesn't need to treat text as special.
+
+\subsection{Safe operation}
+\label{sec:concepts:txn}
+
+Mercurial only ever \emph{appends} data to the end of a revlog file.
+It never modifies a section of a file after it has written it.  This
+is both more robust and efficient than schemes that need to modify or
+rewrite data.
+
+In addition, Mercurial treats every write as part of a
+\emph{transaction} that can span a number of files.  A transaction is
+\emph{atomic}: either the entire transaction succeeds and its effects
+are all visible to readers in one go, or the whole thing is undone.
+This guarantee of atomicity means that if you're running two copies of
+Mercurial, where one is reading data and one is writing it, the reader
+will never see a partially written result that might confuse it.
+
+The fact that Mercurial only appends to files makes it easier to
+provide this transactional guarantee.  The easier it is to do stuff
+like this, the more confident you should be that it's done correctly.
+
+\subsection{Fast retrieval}
+
+Mercurial cleverly avoids a pitfall common to all earlier
+revision control systems: the problem of \emph{inefficient retrieval}.
+Most revision control systems store the contents of a revision as an
+incremental series of modifications against a ``snapshot''.  To
+reconstruct a specific revision, you must first read the snapshot, and
+then every one of the revisions between the snapshot and your target
+revision.  The more history that a file accumulates, the more
+revisions you must read, hence the longer it takes to reconstruct a
+particular revision.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{snapshot}
+  \caption{Snapshot of a revlog, with incremental deltas}
+  \label{fig:concepts:snapshot}
+\end{figure}
+
+The innovation that Mercurial applies to this problem is simple but
+effective.  Once the cumulative amount of delta information stored
+since the last snapshot exceeds a fixed threshold, it stores a new
+snapshot (compressed, of course), instead of another delta.  This
+makes it possible to reconstruct \emph{any} revision of a file
+quickly.  This approach works so well that it has since been copied by
+several other revision control systems.
+
+Figure~\ref{fig:concepts:snapshot} illustrates the idea.  In an entry
+in a revlog's index file, Mercurial stores the range of entries from
+the data file that it must read to reconstruct a particular revision.
+
+\subsubsection{Aside: the influence of video compression}
+
+If you're familiar with video compression or have ever watched a TV
+feed through a digital cable or satellite service, you may know that
+most video compression schemes store each frame of video as a delta
+against its predecessor frame.  In addition, these schemes use
+``lossy'' compression techniques to increase the compression ratio, so
+visual errors accumulate over the course of a number of inter-frame
+deltas.
+
+Because it's possible for a video stream to ``drop out'' occasionally
+due to signal glitches, and to limit the accumulation of artefacts
+introduced by the lossy compression process, video encoders
+periodically insert a complete frame (called a ``key frame'') into the
+video stream; the next delta is generated against that frame.  This
+means that if the video signal gets interrupted, it will resume once
+the next key frame is received.  Also, the accumulation of encoding
+errors restarts anew with each key frame.
+
+\subsection{Identification and strong integrity}
+
+Along with delta or snapshot information, a revlog entry contains a
+cryptographic hash of the data that it represents.  This makes it
+difficult to forge the contents of a revision, and easy to detect
+accidental corruption.  
+
+Hashes provide more than a mere check against corruption; they are
+used as the identifiers for revisions.  The changeset identification
+hashes that you see as an end user are from revisions of the
+changelog.  Although filelogs and the manifest also use hashes,
+Mercurial only uses these behind the scenes.
+
+Mercurial verifies that hashes are correct when it retrieves file
+revisions and when it pulls changes from another repository.  If it
+encounters an integrity problem, it will complain and stop whatever
+it's doing.
+
+In addition to the effect it has on retrieval efficiency, Mercurial's
+use of periodic snapshots makes it more robust against partial data
+corruption.  If a revlog becomes partly corrupted due to a hardware
+error or system bug, it's often possible to reconstruct some or most
+revisions from the uncorrupted sections of the revlog, both before and
+after the corrupted section.  This would not be possible with a
+delta-only storage model.
+
+\section{Revision history, branching, and merging}
+
+Every entry in a Mercurial revlog knows the identity of its immediate
+ancestor revision, usually referred to as its \emph{parent}.  In fact,
+a revision contains room for not one parent, but two.  Mercurial uses
+a special hash, called the ``null ID'', to represent the idea ``there
+is no parent here''.  This hash is simply a string of zeroes.
+
+In figure~\ref{fig:concepts:revlog}, you can see an example of the
+conceptual structure of a revlog.  Filelogs, manifests, and changelogs
+all have this same structure; they differ only in the kind of data
+stored in each delta or snapshot.
+
+The first revision in a revlog (at the bottom of the image) has the
+null ID in both of its parent slots.  For a ``normal'' revision, its
+first parent slot contains the ID of its parent revision, and its
+second contains the null ID, indicating that the revision has only one
+real parent.  Any two revisions that have the same parent ID are
+branches.  A revision that represents a merge between branches has two
+normal revision IDs in its parent slots.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{revlog}
+  \caption{}
+  \label{fig:concepts:revlog}
+\end{figure}
+
+\section{The working directory}
+
+In the working directory, Mercurial stores a snapshot of the files
+from the repository as of a particular changeset.
+
+The working directory ``knows'' which changeset it contains.  When you
+update the working directory to contain a particular changeset,
+Mercurial looks up the appropriate revision of the manifest to find
+out which files it was tracking at the time that changeset was
+committed, and which revision of each file was then current.  It then
+recreates a copy of each of those files, with the same contents it had
+when the changeset was committed.
+
+The \emph{dirstate} contains Mercurial's knowledge of the working
+directory.  This details which changeset the working directory is
+updated to, and all of the files that Mercurial is tracking in the
+working directory.
+
+Just as a revision of a revlog has room for two parents, so that it
+can represent either a normal revision (with one parent) or a merge of
+two earlier revisions, the dirstate has slots for two parents.  When
+you use the \hgcmd{update} command, the changeset that you update to
+is stored in the ``first parent'' slot, and the null ID in the second.
+When you \hgcmd{merge} with another changeset, the first parent
+remains unchanged, and the second parent is filled in with the
+changeset you're merging with.  The \hgcmd{parents} command tells you
+what the parents of the dirstate are.
+
+\subsection{What happens when you commit}
+
+The dirstate stores parent information for more than just book-keeping
+purposes.  Mercurial uses the parents of the dirstate as \emph{the parents of a new changeset} when you perform a commit.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{wdir}
+  \caption{The working directory can have two parents}
+  \label{fig:concepts:wdir}
+\end{figure}
+
+Figure~\ref{fig:concepts:wdir} shows the normal state of the working
+directory, where it has a single changeset as parent.  That changeset
+is the \emph{tip}, the newest changeset in the repository that has no
+children.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{wdir-after-commit}
+  \caption{The working directory gains new parents after a commit}
+  \label{fig:concepts:wdir-after-commit}
+\end{figure}
+
+It's useful to think of the working directory as ``the changeset I'm
+about to commit''.  Any files that you tell Mercurial that you've
+added, removed, renamed, or copied will be reflected in that
+changeset, as will modifications to any files that Mercurial is
+already tracking; the new changeset will have the parents of the
+working directory as its parents.
+
+After a commit, Mercurial will update the parents of the working
+directory, so that the first parent is the ID of the new changeset,
+and the second is the null ID.  This is shown in
+figure~\ref{fig:concepts:wdir-after-commit}.  Mercurial doesn't touch
+any of the files in the working directory when you commit; it just
+modifies the dirstate to note its new parents.
+
+\subsection{Creating a new head}
+
+It's perfectly normal to update the working directory to a changeset
+other than the current tip.  For example, you might want to know what
+your project looked like last Tuesday, or you could be looking through
+changesets to see which one introduced a bug.  In cases like this, the
+natural thing to do is update the working directory to the changeset
+you're interested in, and then examine the files in the working
+directory directly to see their contents as they were when you
+committed that changeset.  The effect of this is shown in
+figure~\ref{fig:concepts:wdir-pre-branch}.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{wdir-pre-branch}
+  \caption{The working directory, updated to an older changeset}
+  \label{fig:concepts:wdir-pre-branch}
+\end{figure}
+
+Having updated the working directory to an older changeset, what
+happens if you make some changes, and then commit?  Mercurial behaves
+in the same way as I outlined above.  The parents of the working
+directory become the parents of the new changeset.  This new changeset
+has no children, so it becomes the new tip.  And the repository now
+contains two changesets that have no children; we call these
+\emph{heads}.  You can see the structure that this creates in
+figure~\ref{fig:concepts:wdir-branch}.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{wdir-branch}
+  \caption{After a commit made while synced to an older changeset}
+  \label{fig:concepts:wdir-branch}
+\end{figure}
+
+\begin{note}
+  If you're new to Mercurial, you should keep in mind a common
+  ``error'', which is to use the \hgcmd{pull} command without any
+  options.  By default, the \hgcmd{pull} command \emph{does not}
+  update the working directory, so you'll bring new changesets into
+  your repository, but the working directory will stay synced at the
+  same changeset as before the pull.  If you make some changes and
+  commit afterwards, you'll thus create a new head, because your
+  working directory isn't synced to whatever the current tip is.
+
+  I put the word ``error'' in quotes because all that you need to do
+  to rectify this situation is \hgcmd{merge}, then \hgcmd{commit}.  In
+  other words, this almost never has negative consequences; it just
+  surprises people.  I'll discuss other ways to avoid this behaviour,
+  and why Mercurial behaves in this initially surprising way, later
+  on.
+\end{note}
+
+\subsection{Merging heads}
+
+When you run the \hgcmd{merge} command, Mercurial leaves the first
+parent of the working directory unchanged, and sets the second parent
+to the changeset you're merging with, as shown in
+figure~\ref{fig:concepts:wdir-merge}.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{wdir-merge}
+  \caption{Merging two heads}
+  \label{fig:concepts:wdir-merge}
+\end{figure}
+
+Mercurial also has to modify the working directory, to merge the files
+managed in the two changesets.  Simplified a little, the merging
+process goes like this, for every file in the manifests of both
+changesets.
+\begin{itemize}
+\item If neither changeset has modified a file, do nothing with that
+  file.
+\item If one changeset has modified a file, and the other hasn't,
+  create the modified copy of the file in the working directory.
+\item If one changeset has removed a file, and the other hasn't (or
+  has also deleted it), delete the file from the working directory.
+\item If one changeset has removed a file, but the other has modified
+  the file, ask the user what to do: keep the modified file, or remove
+  it?
+\item If both changesets have modified a file, invoke an external
+  merge program to choose the new contents for the merged file.  This
+  may require input from the user.
+\item If one changeset has modified a file, and the other has renamed
+  or copied the file, make sure that the changes follow the new name
+  of the file.
+\end{itemize}
+There are more details---merging has plenty of corner cases---but
+these are the most common choices that are involved in a merge.  As
+you can see, most cases are completely automatic, and indeed most
+merges finish automatically, without requiring your input to resolve
+any conflicts.
+
+When you're thinking about what happens when you commit after a merge,
+once again the working directory is ``the changeset I'm about to
+commit''.  After the \hgcmd{merge} command completes, the working
+directory has two parents; these will become the parents of the new
+changeset.
+
+Mercurial lets you perform multiple merges, but you must commit the
+results of each individual merge as you go.  This is necessary because
+Mercurial only tracks two parents for both revisions and the working
+directory.  While it would be technically possible to merge multiple
+changesets at once, the prospect of user confusion and making a
+terrible mess of a merge immediately becomes overwhelming.
+
+\section{Other interesting design features}
+
+In the sections above, I've tried to highlight some of the most
+important aspects of Mercurial's design, to illustrate that it pays
+careful attention to reliability and performance.  However, the
+attention to detail doesn't stop there.  There are a number of other
+aspects of Mercurial's construction that I personally find
+interesting.  I'll detail a few of them here, separate from the ``big
+ticket'' items above, so that if you're interested, you can gain a
+better idea of the amount of thinking that goes into a well-designed
+system.
+
+\subsection{Clever compression}
+
+When appropriate, Mercurial will store both snapshots and deltas in
+compressed form.  It does this by always \emph{trying to} compress a
+snapshot or delta, but only storing the compressed version if it's
+smaller than the uncompressed version.
+
+This means that Mercurial does ``the right thing'' when storing a file
+whose native form is compressed, such as a \texttt{zip} archive or a
+JPEG image.  When these types of files are compressed a second time,
+the resulting file is usually bigger than the once-compressed form,
+and so Mercurial will store the plain \texttt{zip} or JPEG.
+
+Deltas between revisions of a compressed file are usually larger than
+snapshots of the file, and Mercurial again does ``the right thing'' in
+these cases.  It finds that such a delta exceeds the threshold at
+which it should store a complete snapshot of the file, so it stores
+the snapshot, again saving space compared to a naive delta-only
+approach.
+
+\subsubsection{Network recompression}
+
+When storing revisions on disk, Mercurial uses the ``deflate''
+compression algorithm (the same one used by the popular \texttt{zip}
+archive format), which balances good speed with a respectable
+compression ratio.  However, when transmitting revision data over a
+network connection, Mercurial uncompresses the compressed revision
+data.
+
+If the connection is over HTTP, Mercurial recompresses the entire
+stream of data using a compression algorithm that gives a better
+compression ratio (the Burrows-Wheeler algorithm from the widely used
+\texttt{bzip2} compression package).  This combination of algorithm
+and compression of the entire stream (instead of a revision at a time)
+substantially reduces the number of bytes to be transferred, yielding
+better network performance over almost all kinds of network.
+
+(If the connection is over \command{ssh}, Mercurial \emph{doesn't}
+recompress the stream, because \command{ssh} can already do this
+itself.)
+
+\subsection{Read/write ordering and atomicity}
+
+Appending to files isn't the whole story when it comes to guaranteeing
+that a reader won't see a partial write.  If you recall
+figure~\ref{fig:concepts:metadata}, revisions in the changelog point to
+revisions in the manifest, and revisions in the manifest point to
+revisions in filelogs.  This hierarchy is deliberate.
+
+A writer starts a transaction by writing filelog and manifest data,
+and doesn't write any changelog data until those are finished.  A
+reader starts by reading changelog data, then manifest data, followed
+by filelog data.
+
+Since the writer has always finished writing filelog and manifest data
+before it writes to the changelog, a reader will never read a pointer
+to a partially written manifest revision from the changelog, and it will
+never read a pointer to a partially written filelog revision from the
+manifest.
+
+\subsection{Concurrent access}
+
+The read/write ordering and atomicity guarantees mean that Mercurial
+never needs to \emph{lock} a repository when it's reading data, even
+if the repository is being written to while the read is occurring.
+This has a big effect on scalability; you can have an arbitrary number
+of Mercurial processes safely reading data from a repository safely
+all at once, no matter whether it's being written to or not.
+
+The lockless nature of reading means that if you're sharing a
+repository on a multi-user system, you don't need to grant other local
+users permission to \emph{write} to your repository in order for them
+to be able to clone it or pull changes from it; they only need
+\emph{read} permission.  (This is \emph{not} a common feature among
+revision control systems, so don't take it for granted!  Most require
+readers to be able to lock a repository to access it safely, and this
+requires write permission on at least one directory, which of course
+makes for all kinds of nasty and annoying security and administrative
+problems.)
+
+Mercurial uses locks to ensure that only one process can write to a
+repository at a time (the locking mechanism is safe even over
+filesystems that are notoriously hostile to locking, such as NFS).  If
+a repository is locked, a writer will wait for a while to retry if the
+repository becomes unlocked, but if the repository remains locked for
+too long, the process attempting to write will time out after a while.
+This means that your daily automated scripts won't get stuck forever
+and pile up if a system crashes unnoticed, for example.  (Yes, the
+timeout is configurable, from zero to infinity.)
+
+\subsubsection{Safe dirstate access}
+
+As with revision data, Mercurial doesn't take a lock to read the
+dirstate file; it does acquire a lock to write it.  To avoid the
+possibility of reading a partially written copy of the dirstate file,
+Mercurial writes to a file with a unique name in the same directory as
+the dirstate file, then renames the temporary file atomically to
+\filename{dirstate}.  The file named \filename{dirstate} is thus
+guaranteed to be complete, not partially written.
+
+\subsection{Avoiding seeks}
+
+Critical to Mercurial's performance is the avoidance of seeks of the
+disk head, since any seek is far more expensive than even a
+comparatively large read operation.
+
+This is why, for example, the dirstate is stored in a single file.  If
+there were a dirstate file per directory that Mercurial tracked, the
+disk would seek once per directory.  Instead, Mercurial reads the
+entire single dirstate file in one step.
+
+Mercurial also uses a ``copy on write'' scheme when cloning a
+repository on local storage.  Instead of copying every revlog file
+from the old repository into the new repository, it makes a ``hard
+link'', which is a shorthand way to say ``these two names point to the
+same file''.  When Mercurial is about to write to one of a revlog's
+files, it checks to see if the number of names pointing at the file is
+greater than one.  If it is, more than one repository is using the
+file, so Mercurial makes a new copy of the file that is private to
+this repository.
+
+A few revision control developers have pointed out that this idea of
+making a complete private copy of a file is not very efficient in its
+use of storage.  While this is true, storage is cheap, and this method
+gives the highest performance while deferring most book-keeping to the
+operating system.  An alternative scheme would most likely reduce
+performance and increase the complexity of the software, each of which
+is much more important to the ``feel'' of day-to-day use.
+
+\subsection{Other contents of the dirstate}
+
+Because Mercurial doesn't force you to tell it when you're modifying a
+file, it uses the dirstate to store some extra information so it can
+determine efficiently whether you have modified a file.  For each file
+in the working directory, it stores the time that it last modified the
+file itself, and the size of the file at that time.  
+
+When you explicitly \hgcmd{add}, \hgcmd{remove}, \hgcmd{rename} or
+\hgcmd{copy} files, Mercurial updates the dirstate so that it knows
+what to do with those files when you commit.
+
+When Mercurial is checking the states of files in the working
+directory, it first checks a file's modification time.  If that has
+not changed, the file must not have been modified.  If the file's size
+has changed, the file must have been modified.  If the modification
+time has changed, but the size has not, only then does Mercurial need
+to read the actual contents of the file to see if they've changed.
+Storing these few extra pieces of information dramatically reduces the
+amount of data that Mercurial needs to read, which yields large
+performance improvements compared to other revision control systems.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch05-daily.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,379 @@
+\chapter{Mercurial in daily use}
+\label{chap:daily}
+
+\section{Telling Mercurial which files to track}
+
+Mercurial does not work with files in your repository unless you tell
+it to manage them.  The \hgcmd{status} command will tell you which
+files Mercurial doesn't know about; it uses a ``\texttt{?}'' to
+display such files.
+
+To tell Mercurial to track a file, use the \hgcmd{add} command.  Once
+you have added a file, the entry in the output of \hgcmd{status} for
+that file changes from ``\texttt{?}'' to ``\texttt{A}''.
+\interaction{daily.files.add}
+
+After you run a \hgcmd{commit}, the files that you added before the
+commit will no longer be listed in the output of \hgcmd{status}.  The
+reason for this is that \hgcmd{status} only tells you about
+``interesting'' files---those that you have modified or told Mercurial
+to do something with---by default.  If you have a repository that
+contains thousands of files, you will rarely want to know about files
+that Mercurial is tracking, but that have not changed.  (You can still
+get this information; we'll return to this later.)
+
+Once you add a file, Mercurial doesn't do anything with it
+immediately.  Instead, it will take a snapshot of the file's state the
+next time you perform a commit.  It will then continue to track the
+changes you make to the file every time you commit, until you remove
+the file.
+
+\subsection{Explicit versus implicit file naming}
+
+A useful behaviour that Mercurial has is that if you pass the name of
+a directory to a command, every Mercurial command will treat this as
+``I want to operate on every file in this directory and its
+subdirectories''.
+\interaction{daily.files.add-dir}
+Notice in this example that Mercurial printed the names of the files
+it added, whereas it didn't do so when we added the file named
+\filename{a} in the earlier example.
+
+What's going on is that in the former case, we explicitly named the
+file to add on the command line, so the assumption that Mercurial
+makes in such cases is that you know what you were doing, and it
+doesn't print any output.
+
+However, when we \emph{imply} the names of files by giving the name of
+a directory, Mercurial takes the extra step of printing the name of
+each file that it does something with.  This makes it more clear what
+is happening, and reduces the likelihood of a silent and nasty
+surprise.  This behaviour is common to most Mercurial commands.
+
+\subsection{Aside: Mercurial tracks files, not directories}
+
+Mercurial does not track directory information.  Instead, it tracks
+the path to a file.  Before creating a file, it first creates any
+missing directory components of the path.  After it deletes a file, it
+then deletes any empty directories that were in the deleted file's
+path.  This sounds like a trivial distinction, but it has one minor
+practical consequence: it is not possible to represent a completely
+empty directory in Mercurial.
+
+Empty directories are rarely useful, and there are unintrusive
+workarounds that you can use to achieve an appropriate effect.  The
+developers of Mercurial thus felt that the complexity that would be
+required to manage empty directories was not worth the limited benefit
+this feature would bring.
+
+If you need an empty directory in your repository, there are a few
+ways to achieve this. One is to create a directory, then \hgcmd{add} a
+``hidden'' file to that directory.  On Unix-like systems, any file
+name that begins with a period (``\texttt{.}'') is treated as hidden
+by most commands and GUI tools.  This approach is illustrated in
+figure~\ref{ex:daily:hidden}.
+
+\begin{figure}[ht]
+  \interaction{daily.files.hidden}
+  \caption{Simulating an empty directory using a hidden file}
+  \label{ex:daily:hidden}
+\end{figure}
+
+Another way to tackle a need for an empty directory is to simply
+create one in your automated build scripts before they will need it.
+
+\section{How to stop tracking a file}
+
+Once you decide that a file no longer belongs in your repository, use
+the \hgcmd{remove} command; this deletes the file, and tells Mercurial
+to stop tracking it.  A removed file is represented in the output of
+\hgcmd{status} with a ``\texttt{R}''.
+\interaction{daily.files.remove}
+
+After you \hgcmd{remove} a file, Mercurial will no longer track
+changes to that file, even if you recreate a file with the same name
+in your working directory.  If you do recreate a file with the same
+name and want Mercurial to track the new file, simply \hgcmd{add} it.
+Mercurial will know that the newly added file is not related to the
+old file of the same name.
+
+\subsection{Removing a file does not affect its history}
+
+It is important to understand that removing a file has only two
+effects.
+\begin{itemize}
+\item It removes the current version of the file from the working
+  directory.
+\item It stops Mercurial from tracking changes to the file, from the
+  time of the next commit.
+\end{itemize}
+Removing a file \emph{does not} in any way alter the \emph{history} of
+the file.
+
+If you update the working directory to a changeset in which a file
+that you have removed was still tracked, it will reappear in the
+working directory, with the contents it had when you committed that
+changeset.  If you then update the working directory to a later
+changeset, in which the file had been removed, Mercurial will once
+again remove the file from the working directory.
+
+\subsection{Missing files}
+
+Mercurial considers a file that you have deleted, but not used
+\hgcmd{remove} to delete, to be \emph{missing}.  A missing file is
+represented with ``\texttt{!}'' in the output of \hgcmd{status}.
+Mercurial commands will not generally do anything with missing files.
+\interaction{daily.files.missing}
+
+If your repository contains a file that \hgcmd{status} reports as
+missing, and you want the file to stay gone, you can run
+\hgcmdargs{remove}{\hgopt{remove}{--after}} at any time later on, to
+tell Mercurial that you really did mean to remove the file.
+\interaction{daily.files.remove-after}
+
+On the other hand, if you deleted the missing file by accident, use
+\hgcmdargs{revert}{\emph{filename}} to recover the file.  It will
+reappear, in unmodified form.
+\interaction{daily.files.recover-missing}
+
+\subsection{Aside: why tell Mercurial explicitly to remove a file?}
+
+You might wonder why Mercurial requires you to explicitly tell it that
+you are deleting a file.  Early during the development of Mercurial,
+it let you delete a file however you pleased; Mercurial would notice
+the absence of the file automatically when you next ran a
+\hgcmd{commit}, and stop tracking the file.  In practice, this made it
+too easy to accidentally remove a file without noticing.
+
+\subsection{Useful shorthand---adding and removing files in one step}
+
+Mercurial offers a combination command, \hgcmd{addremove}, that adds
+untracked files and marks missing files as removed.  
+\interaction{daily.files.addremove}
+The \hgcmd{commit} command also provides a \hgopt{commit}{-A} option
+that performs this same add-and-remove, immediately followed by a
+commit.
+\interaction{daily.files.commit-addremove}
+
+\section{Copying files}
+
+Mercurial provides a \hgcmd{copy} command that lets you make a new
+copy of a file.  When you copy a file using this command, Mercurial
+makes a record of the fact that the new file is a copy of the original
+file.  It treats these copied files specially when you merge your work
+with someone else's.
+
+\subsection{The results of copying during a merge}
+
+What happens during a merge is that changes ``follow'' a copy.  To
+best illustrate what this means, let's create an example.  We'll start
+with the usual tiny repository that contains a single file.
+\interaction{daily.copy.init}
+We need to do some work in parallel, so that we'll have something to
+merge.  So let's clone our repository.
+\interaction{daily.copy.clone}
+Back in our initial repository, let's use the \hgcmd{copy} command to
+make a copy of the first file we created.
+\interaction{daily.copy.copy}
+
+If we look at the output of the \hgcmd{status} command afterwards, the
+copied file looks just like a normal added file.
+\interaction{daily.copy.status}
+But if we pass the \hgopt{status}{-C} option to \hgcmd{status}, it
+prints another line of output: this is the file that our newly-added
+file was copied \emph{from}.
+\interaction{daily.copy.status-copy}
+
+Now, back in the repository we cloned, let's make a change in
+parallel.  We'll add a line of content to the original file that we
+created.
+\interaction{daily.copy.other}
+Now we have a modified \filename{file} in this repository.  When we
+pull the changes from the first repository, and merge the two heads,
+Mercurial will propagate the changes that we made locally to
+\filename{file} into its copy, \filename{new-file}.
+\interaction{daily.copy.merge}
+
+\subsection{Why should changes follow copies?}
+\label{sec:daily:why-copy}
+
+This behaviour, of changes to a file propagating out to copies of the
+file, might seem esoteric, but in most cases it's highly desirable.
+
+First of all, remember that this propagation \emph{only} happens when
+you merge.  So if you \hgcmd{copy} a file, and subsequently modify the
+original file during the normal course of your work, nothing will
+happen.
+
+The second thing to know is that modifications will only propagate
+across a copy as long as the repository that you're pulling changes
+from \emph{doesn't know} about the copy.
+
+The reason that Mercurial does this is as follows.  Let's say I make
+an important bug fix in a source file, and commit my changes.
+Meanwhile, you've decided to \hgcmd{copy} the file in your repository,
+without knowing about the bug or having seen the fix, and you have
+started hacking on your copy of the file.
+
+If you pulled and merged my changes, and Mercurial \emph{didn't}
+propagate changes across copies, your source file would now contain
+the bug, and unless you remembered to propagate the bug fix by hand,
+the bug would \emph{remain} in your copy of the file.
+
+By automatically propagating the change that fixed the bug from the
+original file to the copy, Mercurial prevents this class of problem.
+To my knowledge, Mercurial is the \emph{only} revision control system
+that propagates changes across copies like this.
+
+Once your change history has a record that the copy and subsequent
+merge occurred, there's usually no further need to propagate changes
+from the original file to the copied file, and that's why Mercurial
+only propagates changes across copies until this point, and no
+further.
+
+\subsection{How to make changes \emph{not} follow a copy}
+
+If, for some reason, you decide that this business of automatically
+propagating changes across copies is not for you, simply use your
+system's normal file copy command (on Unix-like systems, that's
+\command{cp}) to make a copy of a file, then \hgcmd{add} the new copy
+by hand.  Before you do so, though, please do reread
+section~\ref{sec:daily:why-copy}, and make an informed decision that
+this behaviour is not appropriate to your specific case.
+
+\subsection{Behaviour of the \hgcmd{copy} command}
+
+When you use the \hgcmd{copy} command, Mercurial makes a copy of each
+source file as it currently stands in the working directory.  This
+means that if you make some modifications to a file, then \hgcmd{copy}
+it without first having committed those changes, the new copy will
+also contain the modifications you have made up until that point.  (I
+find this behaviour a little counterintuitive, which is why I mention
+it here.)
+
+The \hgcmd{copy} command acts similarly to the Unix \command{cp}
+command (you can use the \hgcmd{cp} alias if you prefer).  The last
+argument is the \emph{destination}, and all prior arguments are
+\emph{sources}.  If you pass it a single file as the source, and the
+destination does not exist, it creates a new file with that name.
+\interaction{daily.copy.simple}
+If the destination is a directory, Mercurial copies its sources into
+that directory.
+\interaction{daily.copy.dir-dest}
+Copying a directory is recursive, and preserves the directory
+structure of the source.
+\interaction{daily.copy.dir-src}
+If the source and destination are both directories, the source tree is
+recreated in the destination directory.
+\interaction{daily.copy.dir-src-dest}
+
+As with the \hgcmd{rename} command, if you copy a file manually and
+then want Mercurial to know that you've copied the file, simply use
+the \hgopt{copy}{--after} option to \hgcmd{copy}.
+\interaction{daily.copy.after}
+
+\section{Renaming files}
+
+It's rather more common to need to rename a file than to make a copy
+of it.  The reason I discussed the \hgcmd{copy} command before talking
+about renaming files is that Mercurial treats a rename in essentially
+the same way as a copy.  Therefore, knowing what Mercurial does when
+you copy a file tells you what to expect when you rename a file.
+
+When you use the \hgcmd{rename} command, Mercurial makes a copy of
+each source file, then deletes it and marks the file as removed.
+\interaction{daily.rename.rename}
+The \hgcmd{status} command shows the newly copied file as added, and
+the copied-from file as removed.
+\interaction{daily.rename.status}
+As with the results of a \hgcmd{copy}, we must use the
+\hgopt{status}{-C} option to \hgcmd{status} to see that the added file
+is really being tracked by Mercurial as a copy of the original, now
+removed, file.
+\interaction{daily.rename.status-copy}
+
+As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about
+a rename after the fact using the \hgopt{rename}{--after} option.  In
+most other respects, the behaviour of the \hgcmd{rename} command, and
+the options it accepts, are similar to the \hgcmd{copy} command.
+
+\subsection{Renaming files and merging changes}
+
+Since Mercurial's rename is implemented as copy-and-remove, the same
+propagation of changes happens when you merge after a rename as after
+a copy.
+
+If I modify a file, and you rename it to a new name, and then we merge
+our respective changes, my modifications to the file under its
+original name will be propagated into the file under its new name.
+(This is something you might expect to ``simply work,'' but not all
+revision control systems actually do this.)
+
+Whereas having changes follow a copy is a feature where you can
+perhaps nod and say ``yes, that might be useful,'' it should be clear
+that having them follow a rename is definitely important.  Without
+this facility, it would simply be too easy for changes to become
+orphaned when files are renamed.
+
+\subsection{Divergent renames and merging}
+
+The case of diverging names occurs when two developers start with a
+file---let's call it \filename{foo}---in their respective
+repositories.
+
+\interaction{rename.divergent.clone}
+Anne renames the file to \filename{bar}.
+\interaction{rename.divergent.rename.anne}
+Meanwhile, Bob renames it to \filename{quux}.
+\interaction{rename.divergent.rename.bob}
+
+I like to think of this as a conflict because each developer has
+expressed different intentions about what the file ought to be named.
+
+What do you think should happen when they merge their work?
+Mercurial's actual behaviour is that it always preserves \emph{both}
+names when it merges changesets that contain divergent renames.
+\interaction{rename.divergent.merge}
+
+Notice that Mercurial does warn about the divergent renames, but it
+leaves it up to you to do something about the divergence after the merge.
+
+\subsection{Convergent renames and merging}
+
+Another kind of rename conflict occurs when two people choose to
+rename different \emph{source} files to the same \emph{destination}.
+In this case, Mercurial runs its normal merge machinery, and lets you
+guide it to a suitable resolution.
+
+\subsection{Other name-related corner cases}
+
+Mercurial has a longstanding bug in which it fails to handle a merge
+where one side has a file with a given name, while another has a
+directory with the same name.  This is documented as~\bug{29}.
+\interaction{issue29.go}
+
+\section{Recovering from mistakes}
+
+Mercurial has some useful commands that will help you to recover from
+some common mistakes.
+
+The \hgcmd{revert} command lets you undo changes that you have made to
+your working directory.  For example, if you \hgcmd{add} a file by
+accident, just run \hgcmd{revert} with the name of the file you added,
+and while the file won't be touched in any way, it won't be tracked
+for adding by Mercurial any longer, either.  You can also use
+\hgcmd{revert} to get rid of erroneous changes to a file.
+
+It's useful to remember that the \hgcmd{revert} command is useful for
+changes that you have not yet committed.  Once you've committed a
+change, if you decide it was a mistake, you can still do something
+about it, though your options may be more limited.
+
+For more information about the \hgcmd{revert} command, and details
+about how to deal with changes you have already committed, see
+chapter~\ref{chap:undo}.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch06-collab.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1117 @@
+\chapter{Collaborating with other people}
+\label{cha:collab}
+
+As a completely decentralised tool, Mercurial doesn't impose any
+policy on how people ought to work with each other.  However, if
+you're new to distributed revision control, it helps to have some
+tools and examples in mind when you're thinking about possible
+workflow models.
+
+\section{Mercurial's web interface}
+
+Mercurial has a powerful web interface that provides several 
+useful capabilities.
+
+For interactive use, the web interface lets you browse a single
+repository or a collection of repositories.  You can view the history
+of a repository, examine each change (comments and diffs), and view
+the contents of each directory and file.
+
+Also for human consumption, the web interface provides an RSS feed of
+the changes in a repository.  This lets you ``subscribe'' to a
+repository using your favourite feed reader, and be automatically
+notified of activity in that repository as soon as it happens.  I find
+this capability much more convenient than the model of subscribing to
+a mailing list to which notifications are sent, as it requires no
+additional configuration on the part of whoever is serving the
+repository.
+
+The web interface also lets remote users clone a repository, pull
+changes from it, and (when the server is configured to permit it) push
+changes back to it.  Mercurial's HTTP tunneling protocol aggressively
+compresses data, so that it works efficiently even over low-bandwidth
+network connections.
+
+The easiest way to get started with the web interface is to use your
+web browser to visit an existing repository, such as the master
+Mercurial repository at
+\url{http://www.selenic.com/repo/hg?style=gitweb}.
+
+If you're interested in providing a web interface to your own
+repositories, Mercurial provides two ways to do this.  The first is
+using the \hgcmd{serve} command, which is best suited to short-term
+``lightweight'' serving.  See section~\ref{sec:collab:serve} below for
+details of how to use this command.  If you have a long-lived
+repository that you'd like to make permanently available, Mercurial
+has built-in support for the CGI (Common Gateway Interface) standard,
+which all common web servers support.  See
+section~\ref{sec:collab:cgi} for details of CGI configuration.
+
+\section{Collaboration models}
+
+With a suitably flexible tool, making decisions about workflow is much
+more of a social engineering challenge than a technical one.
+Mercurial imposes few limitations on how you can structure the flow of
+work in a project, so it's up to you and your group to set up and live
+with a model that matches your own particular needs.
+
+\subsection{Factors to keep in mind}
+
+The most important aspect of any model that you must keep in mind is
+how well it matches the needs and capabilities of the people who will
+be using it.  This might seem self-evident; even so, you still can't
+afford to forget it for a moment.
+
+I once put together a workflow model that seemed to make perfect sense
+to me, but that caused a considerable amount of consternation and
+strife within my development team.  In spite of my attempts to explain
+why we needed a complex set of branches, and how changes ought to flow
+between them, a few team members revolted.  Even though they were
+smart people, they didn't want to pay attention to the constraints we
+were operating under, or face the consequences of those constraints in
+the details of the model that I was advocating.
+
+Don't sweep foreseeable social or technical problems under the rug.
+Whatever scheme you put into effect, you should plan for mistakes and
+problem scenarios.  Consider adding automated machinery to prevent, or
+quickly recover from, trouble that you can anticipate.  As an example,
+if you intend to have a branch with not-for-release changes in it,
+you'd do well to think early about the possibility that someone might
+accidentally merge those changes into a release branch.  You could
+avoid this particular problem by writing a hook that prevents changes
+from being merged from an inappropriate branch.
+
+\subsection{Informal anarchy}
+
+I wouldn't suggest an ``anything goes'' approach as something
+sustainable, but it's a model that's easy to grasp, and it works
+perfectly well in a few unusual situations.
+
+As one example, many projects have a loose-knit group of collaborators
+who rarely physically meet each other.  Some groups like to overcome
+the isolation of working at a distance by organising occasional
+``sprints''.  In a sprint, a number of people get together in a single
+location (a company's conference room, a hotel meeting room, that kind
+of place) and spend several days more or less locked in there, hacking
+intensely on a handful of projects.
+
+A sprint is the perfect place to use the \hgcmd{serve} command, since
+\hgcmd{serve} does not requires any fancy server infrastructure.  You
+can get started with \hgcmd{serve} in moments, by reading
+section~\ref{sec:collab:serve} below.  Then simply tell the person
+next to you that you're running a server, send the URL to them in an
+instant message, and you immediately have a quick-turnaround way to
+work together.  They can type your URL into their web browser and
+quickly review your changes; or they can pull a bugfix from you and
+verify it; or they can clone a branch containing a new feature and try
+it out.
+
+The charm, and the problem, with doing things in an ad hoc fashion
+like this is that only people who know about your changes, and where
+they are, can see them.  Such an informal approach simply doesn't
+scale beyond a handful people, because each individual needs to know
+about $n$ different repositories to pull from.
+
+\subsection{A single central repository}
+
+For smaller projects migrating from a centralised revision control
+tool, perhaps the easiest way to get started is to have changes flow
+through a single shared central repository.  This is also the
+most common ``building block'' for more ambitious workflow schemes.
+
+Contributors start by cloning a copy of this repository.  They can
+pull changes from it whenever they need to, and some (perhaps all)
+developers have permission to push a change back when they're ready
+for other people to see it.
+
+Under this model, it can still often make sense for people to pull
+changes directly from each other, without going through the central
+repository.  Consider a case in which I have a tentative bug fix, but
+I am worried that if I were to publish it to the central repository,
+it might subsequently break everyone else's trees as they pull it.  To
+reduce the potential for damage, I can ask you to clone my repository
+into a temporary repository of your own and test it.  This lets us put
+off publishing the potentially unsafe change until it has had a little
+testing.
+
+In this kind of scenario, people usually use the \command{ssh}
+protocol to securely push changes to the central repository, as
+documented in section~\ref{sec:collab:ssh}.  It's also usual to
+publish a read-only copy of the repository over HTTP using CGI, as in
+section~\ref{sec:collab:cgi}.  Publishing over HTTP satisfies the
+needs of people who don't have push access, and those who want to use
+web browsers to browse the repository's history.
+
+\subsection{Working with multiple branches}
+
+Projects of any significant size naturally tend to make progress on
+several fronts simultaneously.  In the case of software, it's common
+for a project to go through periodic official releases.  A release
+might then go into ``maintenance mode'' for a while after its first
+publication; maintenance releases tend to contain only bug fixes, not
+new features.  In parallel with these maintenance releases, one or
+more future releases may be under development.  People normally use
+the word ``branch'' to refer to one of these many slightly different
+directions in which development is proceeding.
+
+Mercurial is particularly well suited to managing a number of
+simultaneous, but not identical, branches.  Each ``development
+direction'' can live in its own central repository, and you can merge
+changes from one to another as the need arises.  Because repositories
+are independent of each other, unstable changes in a development
+branch will never affect a stable branch unless someone explicitly
+merges those changes in.
+
+Here's an example of how this can work in practice.  Let's say you
+have one ``main branch'' on a central server.
+\interaction{branching.init}
+People clone it, make changes locally, test them, and push them back.
+
+Once the main branch reaches a release milestone, you can use the
+\hgcmd{tag} command to give a permanent name to the milestone
+revision.
+\interaction{branching.tag}
+Let's say some ongoing development occurs on the main branch.
+\interaction{branching.main}
+Using the tag that was recorded at the milestone, people who clone
+that repository at any time in the future can use \hgcmd{update} to
+get a copy of the working directory exactly as it was when that tagged
+revision was committed.  
+\interaction{branching.update}
+
+In addition, immediately after the main branch is tagged, someone can
+then clone the main branch on the server to a new ``stable'' branch,
+also on the server.
+\interaction{branching.clone}
+
+Someone who needs to make a change to the stable branch can then clone
+\emph{that} repository, make their changes, commit, and push their
+changes back there.
+\interaction{branching.stable}
+Because Mercurial repositories are independent, and Mercurial doesn't
+move changes around automatically, the stable and main branches are
+\emph{isolated} from each other.  The changes that you made on the
+main branch don't ``leak'' to the stable branch, and vice versa.
+
+You'll often want all of your bugfixes on the stable branch to show up
+on the main branch, too.  Rather than rewrite a bugfix on the main
+branch, you can simply pull and merge changes from the stable to the
+main branch, and Mercurial will bring those bugfixes in for you.
+\interaction{branching.merge}
+The main branch will still contain changes that are not on the stable
+branch, but it will also contain all of the bugfixes from the stable
+branch.  The stable branch remains unaffected by these changes.
+
+\subsection{Feature branches}
+
+For larger projects, an effective way to manage change is to break up
+a team into smaller groups.  Each group has a shared branch of its
+own, cloned from a single ``master'' branch used by the entire
+project.  People working on an individual branch are typically quite
+isolated from developments on other branches.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{feature-branches}
+  \caption{Feature branches}
+  \label{fig:collab:feature-branches}
+\end{figure}
+
+When a particular feature is deemed to be in suitable shape, someone
+on that feature team pulls and merges from the master branch into the
+feature branch, then pushes back up to the master branch.
+
+\subsection{The release train}
+
+Some projects are organised on a ``train'' basis: a release is
+scheduled to happen every few months, and whatever features are ready
+when the ``train'' is ready to leave are allowed in.
+
+This model resembles working with feature branches.  The difference is
+that when a feature branch misses a train, someone on the feature team
+pulls and merges the changes that went out on that train release into
+the feature branch, and the team continues its work on top of that
+release so that their feature can make the next release.
+
+\subsection{The Linux kernel model}
+
+The development of the Linux kernel has a shallow hierarchical
+structure, surrounded by a cloud of apparent chaos.  Because most
+Linux developers use \command{git}, a distributed revision control
+tool with capabilities similar to Mercurial, it's useful to describe
+the way work flows in that environment; if you like the ideas, the
+approach translates well across tools.
+
+At the center of the community sits Linus Torvalds, the creator of
+Linux.  He publishes a single source repository that is considered the
+``authoritative'' current tree by the entire developer community.
+Anyone can clone Linus's tree, but he is very choosy about whose trees
+he pulls from.
+
+Linus has a number of ``trusted lieutenants''.  As a general rule, he
+pulls whatever changes they publish, in most cases without even
+reviewing those changes.  Some of those lieutenants are generally
+agreed to be ``maintainers'', responsible for specific subsystems
+within the kernel.  If a random kernel hacker wants to make a change
+to a subsystem that they want to end up in Linus's tree, they must
+find out who the subsystem's maintainer is, and ask that maintainer to
+take their change.  If the maintainer reviews their changes and agrees
+to take them, they'll pass them along to Linus in due course.
+
+Individual lieutenants have their own approaches to reviewing,
+accepting, and publishing changes; and for deciding when to feed them
+to Linus.  In addition, there are several well known branches that
+people use for different purposes.  For example, a few people maintain
+``stable'' repositories of older versions of the kernel, to which they
+apply critical fixes as needed.  Some maintainers publish multiple
+trees: one for experimental changes; one for changes that they are
+about to feed upstream; and so on.  Others just publish a single
+tree.
+
+This model has two notable features.  The first is that it's ``pull
+only''.  You have to ask, convince, or beg another developer to take a
+change from you, because there are almost no trees to which more than
+one person can push, and there's no way to push changes into a tree
+that someone else controls.
+
+The second is that it's based on reputation and acclaim.  If you're an
+unknown, Linus will probably ignore changes from you without even
+responding.  But a subsystem maintainer will probably review them, and
+will likely take them if they pass their criteria for suitability.
+The more ``good'' changes you contribute to a maintainer, the more
+likely they are to trust your judgment and accept your changes.  If
+you're well-known and maintain a long-lived branch for something Linus
+hasn't yet accepted, people with similar interests may pull your
+changes regularly to keep up with your work.
+
+Reputation and acclaim don't necessarily cross subsystem or ``people''
+boundaries.  If you're a respected but specialised storage hacker, and
+you try to fix a networking bug, that change will receive a level of
+scrutiny from a network maintainer comparable to a change from a
+complete stranger.
+
+To people who come from more orderly project backgrounds, the
+comparatively chaotic Linux kernel development process often seems
+completely insane.  It's subject to the whims of individuals; people
+make sweeping changes whenever they deem it appropriate; and the pace
+of development is astounding.  And yet Linux is a highly successful,
+well-regarded piece of software.
+
+\subsection{Pull-only versus shared-push collaboration}
+
+A perpetual source of heat in the open source community is whether a
+development model in which people only ever pull changes from others
+is ``better than'' one in which multiple people can push changes to a
+shared repository.
+
+Typically, the backers of the shared-push model use tools that
+actively enforce this approach.  If you're using a centralised
+revision control tool such as Subversion, there's no way to make a
+choice over which model you'll use: the tool gives you shared-push,
+and if you want to do anything else, you'll have to roll your own
+approach on top (such as applying a patch by hand).
+
+A good distributed revision control tool, such as Mercurial, will
+support both models.  You and your collaborators can then structure
+how you work together based on your own needs and preferences, not on
+what contortions your tools force you into.
+
+\subsection{Where collaboration meets branch management}
+
+Once you and your team set up some shared repositories and start
+propagating changes back and forth between local and shared repos, you
+begin to face a related, but slightly different challenge: that of
+managing the multiple directions in which your team may be moving at
+once.  Even though this subject is intimately related to how your team
+collaborates, it's dense enough to merit treatment of its own, in
+chapter~\ref{chap:branch}.
+
+\section{The technical side of sharing}
+
+The remainder of this chapter is devoted to the question of serving
+data to your collaborators.
+
+\section{Informal sharing with \hgcmd{serve}}
+\label{sec:collab:serve}
+
+Mercurial's \hgcmd{serve} command is wonderfully suited to small,
+tight-knit, and fast-paced group environments.  It also provides a
+great way to get a feel for using Mercurial commands over a network.
+
+Run \hgcmd{serve} inside a repository, and in under a second it will
+bring up a specialised HTTP server; this will accept connections from
+any client, and serve up data for that repository until you terminate
+it.  Anyone who knows the URL of the server you just started, and can
+talk to your computer over the network, can then use a web browser or
+Mercurial to read data from that repository.  A URL for a
+\hgcmd{serve} instance running on a laptop is likely to look something
+like \Verb|http://my-laptop.local:8000/|.
+
+The \hgcmd{serve} command is \emph{not} a general-purpose web server.
+It can do only two things:
+\begin{itemize}
+\item Allow people to browse the history of the repository it's
+  serving, from their normal web browsers.
+\item Speak Mercurial's wire protocol, so that people can
+  \hgcmd{clone} or \hgcmd{pull} changes from that repository.
+\end{itemize}
+In particular, \hgcmd{serve} won't allow remote users to \emph{modify}
+your repository.  It's intended for read-only use.
+
+If you're getting started with Mercurial, there's nothing to prevent
+you from using \hgcmd{serve} to serve up a repository on your own
+computer, then use commands like \hgcmd{clone}, \hgcmd{incoming}, and
+so on to talk to that server as if the repository was hosted remotely.
+This can help you to quickly get acquainted with using commands on
+network-hosted repositories.
+
+\subsection{A few things to keep in mind}
+
+Because it provides unauthenticated read access to all clients, you
+should only use \hgcmd{serve} in an environment where you either don't
+care, or have complete control over, who can access your network and
+pull data from your repository.
+
+The \hgcmd{serve} command knows nothing about any firewall software
+you might have installed on your system or network.  It cannot detect
+or control your firewall software.  If other people are unable to talk
+to a running \hgcmd{serve} instance, the second thing you should do
+(\emph{after} you make sure that they're using the correct URL) is
+check your firewall configuration.
+
+By default, \hgcmd{serve} listens for incoming connections on
+port~8000.  If another process is already listening on the port you
+want to use, you can specify a different port to listen on using the
+\hgopt{serve}{-p} option.
+
+Normally, when \hgcmd{serve} starts, it prints no output, which can be
+a bit unnerving.  If you'd like to confirm that it is indeed running
+correctly, and find out what URL you should send to your
+collaborators, start it with the \hggopt{-v} option.
+
+\section{Using the Secure Shell (ssh) protocol}
+\label{sec:collab:ssh}
+
+You can pull and push changes securely over a network connection using
+the Secure Shell (\texttt{ssh}) protocol.  To use this successfully,
+you may have to do a little bit of configuration on the client or
+server sides.
+
+If you're not familiar with ssh, it's a network protocol that lets you
+securely communicate with another computer.  To use it with Mercurial,
+you'll be setting up one or more user accounts on a server so that
+remote users can log in and execute commands.
+
+(If you \emph{are} familiar with ssh, you'll probably find some of the
+material that follows to be elementary in nature.)
+
+\subsection{How to read and write ssh URLs}
+
+An ssh URL tends to look like this:
+\begin{codesample2}
+  ssh://bos@hg.serpentine.com:22/hg/hgbook
+\end{codesample2}
+\begin{enumerate}
+\item The ``\texttt{ssh://}'' part tells Mercurial to use the ssh
+  protocol.
+\item The ``\texttt{bos@}'' component indicates what username to log
+  into the server as.  You can leave this out if the remote username
+  is the same as your local username.
+\item The ``\texttt{hg.serpentine.com}'' gives the hostname of the
+  server to log into.
+\item The ``:22'' identifies the port number to connect to the server
+  on.  The default port is~22, so you only need to specify this part
+  if you're \emph{not} using port~22.
+\item The remainder of the URL is the local path to the repository on
+  the server.
+\end{enumerate}
+
+There's plenty of scope for confusion with the path component of ssh
+URLs, as there is no standard way for tools to interpret it.  Some
+programs behave differently than others when dealing with these paths.
+This isn't an ideal situation, but it's unlikely to change.  Please
+read the following paragraphs carefully.
+
+Mercurial treats the path to a repository on the server as relative to
+the remote user's home directory.  For example, if user \texttt{foo}
+on the server has a home directory of \dirname{/home/foo}, then an ssh
+URL that contains a path component of \dirname{bar}
+\emph{really} refers to the directory \dirname{/home/foo/bar}.
+
+If you want to specify a path relative to another user's home
+directory, you can use a path that starts with a tilde character
+followed by the user's name (let's call them \texttt{otheruser}), like
+this.
+\begin{codesample2}
+  ssh://server/~otheruser/hg/repo
+\end{codesample2}
+
+And if you really want to specify an \emph{absolute} path on the
+server, begin the path component with two slashes, as in this example.
+\begin{codesample2}
+  ssh://server//absolute/path
+\end{codesample2}
+
+\subsection{Finding an ssh client for your system}
+
+Almost every Unix-like system comes with OpenSSH preinstalled.  If
+you're using such a system, run \Verb|which ssh| to find out if
+the \command{ssh} command is installed (it's usually in
+\dirname{/usr/bin}).  In the unlikely event that it isn't present,
+take a look at your system documentation to figure out how to install
+it.
+
+On Windows, you'll first need to download a suitable ssh
+client.  There are two alternatives.
+\begin{itemize}
+\item Simon Tatham's excellent PuTTY package~\cite{web:putty} provides
+  a complete suite of ssh client commands.
+\item If you have a high tolerance for pain, you can use the Cygwin
+  port of OpenSSH.
+\end{itemize}
+In either case, you'll need to edit your \hgini\ file to tell
+Mercurial where to find the actual client command.  For example, if
+you're using PuTTY, you'll need to use the \command{plink} command as
+a command-line ssh client.
+\begin{codesample2}
+  [ui]
+  ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key"
+\end{codesample2}
+
+\begin{note}
+  The path to \command{plink} shouldn't contain any whitespace
+  characters, or Mercurial may not be able to run it correctly (so
+  putting it in \dirname{C:\\Program Files} is probably not a good
+  idea).
+\end{note}
+
+\subsection{Generating a key pair}
+
+To avoid the need to repetitively type a password every time you need
+to use your ssh client, I recommend generating a key pair.  On a
+Unix-like system, the \command{ssh-keygen} command will do the trick.
+On Windows, if you're using PuTTY, the \command{puttygen} command is
+what you'll need.
+
+When you generate a key pair, it's usually \emph{highly} advisable to
+protect it with a passphrase.  (The only time that you might not want
+to do this is when you're using the ssh protocol for automated tasks
+on a secure network.)
+
+Simply generating a key pair isn't enough, however.  You'll need to
+add the public key to the set of authorised keys for whatever user
+you're logging in remotely as.  For servers using OpenSSH (the vast
+majority), this will mean adding the public key to a list in a file
+called \sfilename{authorized\_keys} in their \sdirname{.ssh}
+directory.
+
+On a Unix-like system, your public key will have a \filename{.pub}
+extension.  If you're using \command{puttygen} on Windows, you can
+save the public key to a file of your choosing, or paste it from the
+window it's displayed in straight into the
+\sfilename{authorized\_keys} file.
+
+\subsection{Using an authentication agent}
+
+An authentication agent is a daemon that stores passphrases in memory
+(so it will forget passphrases if you log out and log back in again).
+An ssh client will notice if it's running, and query it for a
+passphrase.  If there's no authentication agent running, or the agent
+doesn't store the necessary passphrase, you'll have to type your
+passphrase every time Mercurial tries to communicate with a server on
+your behalf (e.g.~whenever you pull or push changes).
+
+The downside of storing passphrases in an agent is that it's possible
+for a well-prepared attacker to recover the plain text of your
+passphrases, in some cases even if your system has been power-cycled.
+You should make your own judgment as to whether this is an acceptable
+risk.  It certainly saves a lot of repeated typing.
+
+On Unix-like systems, the agent is called \command{ssh-agent}, and
+it's often run automatically for you when you log in.  You'll need to
+use the \command{ssh-add} command to add passphrases to the agent's
+store.  On Windows, if you're using PuTTY, the \command{pageant}
+command acts as the agent.  It adds an icon to your system tray that
+will let you manage stored passphrases.
+
+\subsection{Configuring the server side properly}
+
+Because ssh can be fiddly to set up if you're new to it, there's a
+variety of things that can go wrong.  Add Mercurial on top, and
+there's plenty more scope for head-scratching.  Most of these
+potential problems occur on the server side, not the client side.  The
+good news is that once you've gotten a configuration working, it will
+usually continue to work indefinitely.
+
+Before you try using Mercurial to talk to an ssh server, it's best to
+make sure that you can use the normal \command{ssh} or \command{putty}
+command to talk to the server first.  If you run into problems with
+using these commands directly, Mercurial surely won't work.  Worse, it
+will obscure the underlying problem.  Any time you want to debug
+ssh-related Mercurial problems, you should drop back to making sure
+that plain ssh client commands work first, \emph{before} you worry
+about whether there's a problem with Mercurial.
+
+The first thing to be sure of on the server side is that you can
+actually log in from another machine at all.  If you can't use
+\command{ssh} or \command{putty} to log in, the error message you get
+may give you a few hints as to what's wrong.  The most common problems
+are as follows.
+\begin{itemize}
+\item If you get a ``connection refused'' error, either there isn't an
+  SSH daemon running on the server at all, or it's inaccessible due to
+  firewall configuration.
+\item If you get a ``no route to host'' error, you either have an
+  incorrect address for the server or a seriously locked down firewall
+  that won't admit its existence at all.
+\item If you get a ``permission denied'' error, you may have mistyped
+  the username on the server, or you could have mistyped your key's
+  passphrase or the remote user's password.
+\end{itemize}
+In summary, if you're having trouble talking to the server's ssh
+daemon, first make sure that one is running at all.  On many systems
+it will be installed, but disabled, by default.  Once you're done with
+this step, you should then check that the server's firewall is
+configured to allow incoming connections on the port the ssh daemon is
+listening on (usually~22).  Don't worry about more exotic
+possibilities for misconfiguration until you've checked these two
+first.
+
+If you're using an authentication agent on the client side to store
+passphrases for your keys, you ought to be able to log into the server
+without being prompted for a passphrase or a password.  If you're
+prompted for a passphrase, there are a few possible culprits.
+\begin{itemize}
+\item You might have forgotten to use \command{ssh-add} or
+  \command{pageant} to store the passphrase.
+\item You might have stored the passphrase for the wrong key.
+\end{itemize}
+If you're being prompted for the remote user's password, there are
+another few possible problems to check.
+\begin{itemize}
+\item Either the user's home directory or their \sdirname{.ssh}
+  directory might have excessively liberal permissions.  As a result,
+  the ssh daemon will not trust or read their
+  \sfilename{authorized\_keys} file.  For example, a group-writable
+  home or \sdirname{.ssh} directory will often cause this symptom.
+\item The user's \sfilename{authorized\_keys} file may have a problem.
+  If anyone other than the user owns or can write to that file, the
+  ssh daemon will not trust or read it.
+\end{itemize}
+
+In the ideal world, you should be able to run the following command
+successfully, and it should print exactly one line of output, the
+current date and time.
+\begin{codesample2}
+  ssh myserver date
+\end{codesample2}
+
+If, on your server, you have login scripts that print banners or other
+junk even when running non-interactive commands like this, you should
+fix them before you continue, so that they only print output if
+they're run interactively.  Otherwise these banners will at least
+clutter up Mercurial's output.  Worse, they could potentially cause
+problems with running Mercurial commands remotely.  Mercurial makes
+tries to detect and ignore banners in non-interactive \command{ssh}
+sessions, but it is not foolproof.  (If you're editing your login
+scripts on your server, the usual way to see if a login script is
+running in an interactive shell is to check the return code from the
+command \Verb|tty -s|.)
+
+Once you've verified that plain old ssh is working with your server,
+the next step is to ensure that Mercurial runs on the server.  The
+following command should run successfully:
+\begin{codesample2}
+  ssh myserver hg version
+\end{codesample2}
+If you see an error message instead of normal \hgcmd{version} output,
+this is usually because you haven't installed Mercurial to
+\dirname{/usr/bin}.  Don't worry if this is the case; you don't need
+to do that.  But you should check for a few possible problems.
+\begin{itemize}
+\item Is Mercurial really installed on the server at all?  I know this
+  sounds trivial, but it's worth checking!
+\item Maybe your shell's search path (usually set via the \envar{PATH}
+  environment variable) is simply misconfigured.
+\item Perhaps your \envar{PATH} environment variable is only being set
+  to point to the location of the \command{hg} executable if the login
+  session is interactive.  This can happen if you're setting the path
+  in the wrong shell login script.  See your shell's documentation for
+  details.
+\item The \envar{PYTHONPATH} environment variable may need to contain
+  the path to the Mercurial Python modules.  It might not be set at
+  all; it could be incorrect; or it may be set only if the login is
+  interactive.
+\end{itemize}
+
+If you can run \hgcmd{version} over an ssh connection, well done!
+You've got the server and client sorted out.  You should now be able
+to use Mercurial to access repositories hosted by that username on
+that server.  If you run into problems with Mercurial and ssh at this
+point, try using the \hggopt{--debug} option to get a clearer picture
+of what's going on.
+
+\subsection{Using compression with ssh}
+
+Mercurial does not compress data when it uses the ssh protocol,
+because the ssh protocol can transparently compress data.  However,
+the default behaviour of ssh clients is \emph{not} to request
+compression.
+
+Over any network other than a fast LAN (even a wireless network),
+using compression is likely to significantly speed up Mercurial's
+network operations.  For example, over a WAN, someone measured
+compression as reducing the amount of time required to clone a
+particularly large repository from~51 minutes to~17 minutes.
+
+Both \command{ssh} and \command{plink} accept a \cmdopt{ssh}{-C}
+option which turns on compression.  You can easily edit your \hgrc\ to
+enable compression for all of Mercurial's uses of the ssh protocol.
+\begin{codesample2}
+  [ui]
+  ssh = ssh -C
+\end{codesample2}
+
+If you use \command{ssh}, you can configure it to always use
+compression when talking to your server.  To do this, edit your
+\sfilename{.ssh/config} file (which may not yet exist), as follows.
+\begin{codesample2}
+  Host hg
+    Compression yes
+    HostName hg.example.com
+\end{codesample2}
+This defines an alias, \texttt{hg}.  When you use it on the
+\command{ssh} command line or in a Mercurial \texttt{ssh}-protocol
+URL, it will cause \command{ssh} to connect to \texttt{hg.example.com}
+and use compression.  This gives you both a shorter name to type and
+compression, each of which is a good thing in its own right.
+
+\section{Serving over HTTP using CGI}
+\label{sec:collab:cgi}
+
+Depending on how ambitious you are, configuring Mercurial's CGI
+interface can take anything from a few moments to several hours.
+
+We'll begin with the simplest of examples, and work our way towards a
+more complex configuration.  Even for the most basic case, you're
+almost certainly going to need to read and modify your web server's
+configuration.
+
+\begin{note}
+  Configuring a web server is a complex, fiddly, and highly
+  system-dependent activity.  I can't possibly give you instructions
+  that will cover anything like all of the cases you will encounter.
+  Please use your discretion and judgment in following the sections
+  below.  Be prepared to make plenty of mistakes, and to spend a lot
+  of time reading your server's error logs.
+\end{note}
+
+\subsection{Web server configuration checklist}
+
+Before you continue, do take a few moments to check a few aspects of
+your system's setup.
+
+\begin{enumerate}
+\item Do you have a web server installed at all?  Mac OS X ships with
+  Apache, but many other systems may not have a web server installed.
+\item If you have a web server installed, is it actually running?  On
+  most systems, even if one is present, it will be disabled by
+  default.
+\item Is your server configured to allow you to run CGI programs in
+  the directory where you plan to do so?  Most servers default to
+  explicitly disabling the ability to run CGI programs.
+\end{enumerate}
+
+If you don't have a web server installed, and don't have substantial
+experience configuring Apache, you should consider using the
+\texttt{lighttpd} web server instead of Apache.  Apache has a
+well-deserved reputation for baroque and confusing configuration.
+While \texttt{lighttpd} is less capable in some ways than Apache, most
+of these capabilities are not relevant to serving Mercurial
+repositories.  And \texttt{lighttpd} is undeniably \emph{much} easier
+to get started with than Apache.
+
+\subsection{Basic CGI configuration}
+
+On Unix-like systems, it's common for users to have a subdirectory
+named something like \dirname{public\_html} in their home directory,
+from which they can serve up web pages.  A file named \filename{foo}
+in this directory will be accessible at a URL of the form
+\texttt{http://www.example.com/\~{}username/foo}.
+
+To get started, find the \sfilename{hgweb.cgi} script that should be
+present in your Mercurial installation.  If you can't quickly find a
+local copy on your system, simply download one from the master
+Mercurial repository at
+\url{http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi}.
+
+You'll need to copy this script into your \dirname{public\_html}
+directory, and ensure that it's executable.
+\begin{codesample2}
+  cp .../hgweb.cgi ~/public_html
+  chmod 755 ~/public_html/hgweb.cgi
+\end{codesample2}
+The \texttt{755} argument to \command{chmod} is a little more general
+than just making the script executable: it ensures that the script is
+executable by anyone, and that ``group'' and ``other'' write
+permissions are \emph{not} set.  If you were to leave those write
+permissions enabled, Apache's \texttt{suexec} subsystem would likely
+refuse to execute the script.  In fact, \texttt{suexec} also insists
+that the \emph{directory} in which the script resides must not be
+writable by others.
+\begin{codesample2}
+  chmod 755 ~/public_html
+\end{codesample2}
+
+\subsubsection{What could \emph{possibly} go wrong?}
+\label{sec:collab:wtf}
+
+Once you've copied the CGI script into place, go into a web browser,
+and try to open the URL \url{http://myhostname/~myuser/hgweb.cgi},
+\emph{but} brace yourself for instant failure.  There's a high
+probability that trying to visit this URL will fail, and there are
+many possible reasons for this.  In fact, you're likely to stumble
+over almost every one of the possible errors below, so please read
+carefully.  The following are all of the problems I ran into on a
+system running Fedora~7, with a fresh installation of Apache, and a
+user account that I created specially to perform this exercise.
+
+Your web server may have per-user directories disabled.  If you're
+using Apache, search your config file for a \texttt{UserDir}
+directive.  If there's none present, per-user directories will be
+disabled.  If one exists, but its value is \texttt{disabled}, then
+per-user directories will be disabled.  Otherwise, the string after
+\texttt{UserDir} gives the name of the subdirectory that Apache will
+look in under your home directory, for example \dirname{public\_html}.
+
+Your file access permissions may be too restrictive.  The web server
+must be able to traverse your home directory and directories under
+your \dirname{public\_html} directory, and read files under the latter
+too.  Here's a quick recipe to help you to make your permissions more
+appropriate.
+\begin{codesample2}
+  chmod 755 ~
+  find ~/public_html -type d -print0 | xargs -0r chmod 755
+  find ~/public_html -type f -print0 | xargs -0r chmod 644
+\end{codesample2}
+
+The other possibility with permissions is that you might get a
+completely empty window when you try to load the script.  In this
+case, it's likely that your access permissions are \emph{too
+  permissive}.  Apache's \texttt{suexec} subsystem won't execute a
+script that's group-~or world-writable, for example.
+
+Your web server may be configured to disallow execution of CGI
+programs in your per-user web directory.  Here's Apache's
+default per-user configuration from my Fedora system.
+\begin{codesample2}
+  <Directory /home/*/public_html>
+      AllowOverride FileInfo AuthConfig Limit
+      Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+      <Limit GET POST OPTIONS>
+          Order allow,deny
+          Allow from all
+      </Limit>
+      <LimitExcept GET POST OPTIONS>
+          Order deny,allow
+          Deny from all
+      </LimitExcept>
+  </Directory>
+\end{codesample2}
+If you find a similar-looking \texttt{Directory} group in your Apache
+configuration, the directive to look at inside it is \texttt{Options}.
+Add \texttt{ExecCGI} to the end of this list if it's missing, and
+restart the web server.
+
+If you find that Apache serves you the text of the CGI script instead
+of executing it, you may need to either uncomment (if already present)
+or add a directive like this.
+\begin{codesample2}
+  AddHandler cgi-script .cgi
+\end{codesample2}
+
+The next possibility is that you might be served with a colourful
+Python backtrace claiming that it can't import a
+\texttt{mercurial}-related module.  This is actually progress!  The
+server is now capable of executing your CGI script.  This error is
+only likely to occur if you're running a private installation of
+Mercurial, instead of a system-wide version.  Remember that the web
+server runs the CGI program without any of the environment variables
+that you take for granted in an interactive session.  If this error
+happens to you, edit your copy of \sfilename{hgweb.cgi} and follow the
+directions inside it to correctly set your \envar{PYTHONPATH}
+environment variable.
+
+Finally, you are \emph{certain} to by served with another colourful
+Python backtrace: this one will complain that it can't find
+\dirname{/path/to/repository}.  Edit your \sfilename{hgweb.cgi} script
+and replace the \dirname{/path/to/repository} string with the complete
+path to the repository you want to serve up.
+
+At this point, when you try to reload the page, you should be
+presented with a nice HTML view of your repository's history.  Whew!
+
+\subsubsection{Configuring lighttpd}
+
+To be exhaustive in my experiments, I tried configuring the
+increasingly popular \texttt{lighttpd} web server to serve the same
+repository as I described with Apache above.  I had already overcome
+all of the problems I outlined with Apache, many of which are not
+server-specific.  As a result, I was fairly sure that my file and
+directory permissions were good, and that my \sfilename{hgweb.cgi}
+script was properly edited.
+
+Once I had Apache running, getting \texttt{lighttpd} to serve the
+repository was a snap (in other words, even if you're trying to use
+\texttt{lighttpd}, you should read the Apache section).  I first had
+to edit the \texttt{mod\_access} section of its config file to enable
+\texttt{mod\_cgi} and \texttt{mod\_userdir}, both of which were
+disabled by default on my system.  I then added a few lines to the end
+of the config file, to configure these modules.
+\begin{codesample2}
+  userdir.path = "public_html"
+  cgi.assign = ( ".cgi" => "" )
+\end{codesample2}
+With this done, \texttt{lighttpd} ran immediately for me.  If I had
+configured \texttt{lighttpd} before Apache, I'd almost certainly have
+run into many of the same system-level configuration problems as I did
+with Apache.  However, I found \texttt{lighttpd} to be noticeably
+easier to configure than Apache, even though I've used Apache for over
+a decade, and this was my first exposure to \texttt{lighttpd}.
+
+\subsection{Sharing multiple repositories with one CGI script}
+
+The \sfilename{hgweb.cgi} script only lets you publish a single
+repository, which is an annoying restriction.  If you want to publish
+more than one without wracking yourself with multiple copies of the
+same script, each with different names, a better choice is to use the
+\sfilename{hgwebdir.cgi} script.
+
+The procedure to configure \sfilename{hgwebdir.cgi} is only a little
+more involved than for \sfilename{hgweb.cgi}.  First, you must obtain
+a copy of the script.  If you don't have one handy, you can download a
+copy from the master Mercurial repository at
+\url{http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi}.
+
+You'll need to copy this script into your \dirname{public\_html}
+directory, and ensure that it's executable.
+\begin{codesample2}
+  cp .../hgwebdir.cgi ~/public_html
+  chmod 755 ~/public_html ~/public_html/hgwebdir.cgi
+\end{codesample2}
+With basic configuration out of the way, try to visit
+\url{http://myhostname/~myuser/hgwebdir.cgi} in your browser.  It
+should display an empty list of repositories.  If you get a blank
+window or error message, try walking through the list of potential
+problems in section~\ref{sec:collab:wtf}.
+
+The \sfilename{hgwebdir.cgi} script relies on an external
+configuration file.  By default, it searches for a file named
+\sfilename{hgweb.config} in the same directory as itself.  You'll need
+to create this file, and make it world-readable.  The format of the
+file is similar to a Windows ``ini'' file, as understood by Python's
+\texttt{ConfigParser}~\cite{web:configparser} module.
+
+The easiest way to configure \sfilename{hgwebdir.cgi} is with a
+section named \texttt{collections}.  This will automatically publish
+\emph{every} repository under the directories you name.  The section
+should look like this:
+\begin{codesample2}
+  [collections]
+  /my/root = /my/root
+\end{codesample2}
+Mercurial interprets this by looking at the directory name on the
+\emph{right} hand side of the ``\texttt{=}'' sign; finding
+repositories in that directory hierarchy; and using the text on the
+\emph{left} to strip off matching text from the names it will actually
+list in the web interface.  The remaining component of a path after
+this stripping has occurred is called a ``virtual path''.
+
+Given the example above, if we have a repository whose local path is
+\dirname{/my/root/this/repo}, the CGI script will strip the leading
+\dirname{/my/root} from the name, and publish the repository with a
+virtual path of \dirname{this/repo}.  If the base URL for our CGI
+script is \url{http://myhostname/~myuser/hgwebdir.cgi}, the complete
+URL for that repository will be
+\url{http://myhostname/~myuser/hgwebdir.cgi/this/repo}.
+
+If we replace \dirname{/my/root} on the left hand side of this example
+with \dirname{/my}, then \sfilename{hgwebdir.cgi} will only strip off
+\dirname{/my} from the repository name, and will give us a virtual
+path of \dirname{root/this/repo} instead of \dirname{this/repo}.
+
+The \sfilename{hgwebdir.cgi} script will recursively search each
+directory listed in the \texttt{collections} section of its
+configuration file, but it will \texttt{not} recurse into the
+repositories it finds.
+
+The \texttt{collections} mechanism makes it easy to publish many
+repositories in a ``fire and forget'' manner.  You only need to set up
+the CGI script and configuration file one time.  Afterwards, you can
+publish or unpublish a repository at any time by simply moving it
+into, or out of, the directory hierarchy in which you've configured
+\sfilename{hgwebdir.cgi} to look.
+
+\subsubsection{Explicitly specifying which repositories to publish}
+
+In addition to the \texttt{collections} mechanism, the
+\sfilename{hgwebdir.cgi} script allows you to publish a specific list
+of repositories.  To do so, create a \texttt{paths} section, with
+contents of the following form.
+\begin{codesample2}
+  [paths]
+  repo1 = /my/path/to/some/repo
+  repo2 = /some/path/to/another
+\end{codesample2}
+In this case, the virtual path (the component that will appear in a
+URL) is on the left hand side of each definition, while the path to
+the repository is on the right.  Notice that there does not need to be
+any relationship between the virtual path you choose and the location
+of a repository in your filesystem.
+
+If you wish, you can use both the \texttt{collections} and
+\texttt{paths} mechanisms simultaneously in a single configuration
+file.
+
+\begin{note}
+  If multiple repositories have the same virtual path,
+  \sfilename{hgwebdir.cgi} will not report an error.  Instead, it will
+  behave unpredictably.
+\end{note}
+
+\subsection{Downloading source archives}
+
+Mercurial's web interface lets users download an archive of any
+revision.  This archive will contain a snapshot of the working
+directory as of that revision, but it will not contain a copy of the
+repository data.
+
+By default, this feature is not enabled.  To enable it, you'll need to
+add an \rcitem{web}{allow\_archive} item to the \rcsection{web}
+section of your \hgrc.
+
+\subsection{Web configuration options}
+
+Mercurial's web interfaces (the \hgcmd{serve} command, and the
+\sfilename{hgweb.cgi} and \sfilename{hgwebdir.cgi} scripts) have a
+number of configuration options that you can set.  These belong in a
+section named \rcsection{web}.
+\begin{itemize}
+\item[\rcitem{web}{allow\_archive}] Determines which (if any) archive
+  download mechanisms Mercurial supports.  If you enable this
+  feature, users of the web interface will be able to download an
+  archive of whatever revision of a repository they are viewing.
+  To enable the archive feature, this item must take the form of a
+  sequence of words drawn from the list below.
+  \begin{itemize}
+  \item[\texttt{bz2}] A \command{tar} archive, compressed using
+    \texttt{bzip2} compression.  This has the best compression ratio,
+    but uses the most CPU time on the server.
+  \item[\texttt{gz}] A \command{tar} archive, compressed using
+    \texttt{gzip} compression.
+  \item[\texttt{zip}] A \command{zip} archive, compressed using LZW
+    compression.  This format has the worst compression ratio, but is
+    widely used in the Windows world.
+  \end{itemize}
+  If you provide an empty list, or don't have an
+  \rcitem{web}{allow\_archive} entry at all, this feature will be
+  disabled.  Here is an example of how to enable all three supported
+  formats.
+  \begin{codesample4}
+    [web]
+    allow_archive = bz2 gz zip
+  \end{codesample4}
+\item[\rcitem{web}{allowpull}] Boolean.  Determines whether the web
+  interface allows remote users to \hgcmd{pull} and \hgcmd{clone} this
+  repository over~HTTP.  If set to \texttt{no} or \texttt{false}, only
+  the ``human-oriented'' portion of the web interface is available.
+\item[\rcitem{web}{contact}] String.  A free-form (but preferably
+  brief) string identifying the person or group in charge of the
+  repository.  This often contains the name and email address of a
+  person or mailing list.  It often makes sense to place this entry in
+  a repository's own \sfilename{.hg/hgrc} file, but it can make sense
+  to use in a global \hgrc\ if every repository has a single
+  maintainer.
+\item[\rcitem{web}{maxchanges}] Integer.  The default maximum number
+  of changesets to display in a single page of output.
+\item[\rcitem{web}{maxfiles}] Integer.  The default maximum number
+  of modified files to display in a single page of output.
+\item[\rcitem{web}{stripes}] Integer.  If the web interface displays
+  alternating ``stripes'' to make it easier to visually align rows
+  when you are looking at a table, this number controls the number of
+  rows in each stripe.
+\item[\rcitem{web}{style}] Controls the template Mercurial uses to
+  display the web interface.  Mercurial ships with two web templates,
+  named \texttt{default} and \texttt{gitweb} (the latter is much more
+  visually attractive).  You can also specify a custom template of
+  your own; see chapter~\ref{chap:template} for details.  Here, you
+  can see how to enable the \texttt{gitweb} style.
+  \begin{codesample4}
+    [web]
+    style = gitweb
+  \end{codesample4}
+\item[\rcitem{web}{templates}] Path.  The directory in which to search
+  for template files.  By default, Mercurial searches in the directory
+  in which it was installed.
+\end{itemize}
+If you are using \sfilename{hgwebdir.cgi}, you can place a few
+configuration items in a \rcsection{web} section of the
+\sfilename{hgweb.config} file instead of a \hgrc\ file, for
+convenience.  These items are \rcitem{web}{motd} and
+\rcitem{web}{style}.
+
+\subsubsection{Options specific to an individual repository}
+
+A few \rcsection{web} configuration items ought to be placed in a
+repository's local \sfilename{.hg/hgrc}, rather than a user's or
+global \hgrc.
+\begin{itemize}
+\item[\rcitem{web}{description}] String.  A free-form (but preferably
+  brief) string that describes the contents or purpose of the
+  repository.
+\item[\rcitem{web}{name}] String.  The name to use for the repository
+  in the web interface.  This overrides the default name, which is the
+  last component of the repository's path.
+\end{itemize}
+
+\subsubsection{Options specific to the \hgcmd{serve} command}
+
+Some of the items in the \rcsection{web} section of a \hgrc\ file are
+only for use with the \hgcmd{serve} command.
+\begin{itemize}
+\item[\rcitem{web}{accesslog}] Path.  The name of a file into which to
+  write an access log.  By default, the \hgcmd{serve} command writes
+  this information to standard output, not to a file.  Log entries are
+  written in the standard ``combined'' file format used by almost all
+  web servers.
+\item[\rcitem{web}{address}] String.  The local address on which the
+  server should listen for incoming connections.  By default, the
+  server listens on all addresses.
+\item[\rcitem{web}{errorlog}] Path.  The name of a file into which to
+  write an error log.  By default, the \hgcmd{serve} command writes this
+  information to standard error, not to a file.
+\item[\rcitem{web}{ipv6}] Boolean.  Whether to use the IPv6 protocol.
+  By default, IPv6 is not used. 
+\item[\rcitem{web}{port}] Integer.  The TCP~port number on which the
+  server should listen.  The default port number used is~8000.
+\end{itemize}
+
+\subsubsection{Choosing the right \hgrc\ file to add \rcsection{web} items to}
+
+It is important to remember that a web server like Apache or
+\texttt{lighttpd} will run under a user~ID that is different to yours.
+CGI scripts run by your server, such as \sfilename{hgweb.cgi}, will
+usually also run under that user~ID.
+
+If you add \rcsection{web} items to your own personal \hgrc\ file, CGI
+scripts won't read that \hgrc\ file.  Those settings will thus only
+affect the behaviour of the \hgcmd{serve} command when you run it.  To
+cause CGI scripts to see your settings, either create a \hgrc\ file in
+the home directory of the user ID that runs your web server, or add
+those settings to a system-wide \hgrc\ file.
+
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch07-filenames.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,305 @@
+\chapter{File names and pattern matching}
+\label{chap:names}
+
+Mercurial provides mechanisms that let you work with file names in a
+consistent and expressive way.
+
+\section{Simple file naming}
+
+Mercurial uses a unified piece of machinery ``under the hood'' to
+handle file names.  Every command behaves uniformly with respect to
+file names.  The way in which commands work with file names is as
+follows.
+
+If you explicitly name real files on the command line, Mercurial works
+with exactly those files, as you would expect.
+\interaction{filenames.files}
+
+When you provide a directory name, Mercurial will interpret this as
+``operate on every file in this directory and its subdirectories''.
+Mercurial traverses the files and subdirectories in a directory in
+alphabetical order.  When it encounters a subdirectory, it will
+traverse that subdirectory before continuing with the current
+directory.
+\interaction{filenames.dirs}
+
+\section{Running commands without any file names}
+
+Mercurial's commands that work with file names have useful default
+behaviours when you invoke them without providing any file names or
+patterns.  What kind of behaviour you should expect depends on what
+the command does.  Here are a few rules of thumb you can use to
+predict what a command is likely to do if you don't give it any names
+to work with.
+\begin{itemize}
+\item Most commands will operate on the entire working directory.
+  This is what the \hgcmd{add} command does, for example.
+\item If the command has effects that are difficult or impossible to
+  reverse, it will force you to explicitly provide at least one name
+  or pattern (see below).  This protects you from accidentally
+  deleting files by running \hgcmd{remove} with no arguments, for
+  example.
+\end{itemize}
+
+It's easy to work around these default behaviours if they don't suit
+you.  If a command normally operates on the whole working directory,
+you can invoke it on just the current directory and its subdirectories
+by giving it the name ``\dirname{.}''.
+\interaction{filenames.wdir-subdir}
+
+Along the same lines, some commands normally print file names relative
+to the root of the repository, even if you're invoking them from a
+subdirectory.  Such a command will print file names relative to your
+subdirectory if you give it explicit names.  Here, we're going to run
+\hgcmd{status} from a subdirectory, and get it to operate on the
+entire working directory while printing file names relative to our
+subdirectory, by passing it the output of the \hgcmd{root} command.
+\interaction{filenames.wdir-relname}
+
+\section{Telling you what's going on}
+
+The \hgcmd{add} example in the preceding section illustrates something
+else that's helpful about Mercurial commands.  If a command operates
+on a file that you didn't name explicitly on the command line, it will
+usually print the name of the file, so that you will not be surprised
+what's going on.
+
+The principle here is of \emph{least surprise}.  If you've exactly
+named a file on the command line, there's no point in repeating it
+back at you.  If Mercurial is acting on a file \emph{implicitly},
+because you provided no names, or a directory, or a pattern (see
+below), it's safest to tell you what it's doing.
+
+For commands that behave this way, you can silence them using the
+\hggopt{-q} option.  You can also get them to print the name of every
+file, even those you've named explicitly, using the \hggopt{-v}
+option.
+
+\section{Using patterns to identify files}
+
+In addition to working with file and directory names, Mercurial lets
+you use \emph{patterns} to identify files.  Mercurial's pattern
+handling is expressive.
+
+On Unix-like systems (Linux, MacOS, etc.), the job of matching file
+names to patterns normally falls to the shell.  On these systems, you
+must explicitly tell Mercurial that a name is a pattern.  On Windows,
+the shell does not expand patterns, so Mercurial will automatically
+identify names that are patterns, and expand them for you.
+
+To provide a pattern in place of a regular name on the command line,
+the mechanism is simple:
+\begin{codesample2}
+  syntax:patternbody
+\end{codesample2}
+That is, a pattern is identified by a short text string that says what
+kind of pattern this is, followed by a colon, followed by the actual
+pattern.
+
+Mercurial supports two kinds of pattern syntax.  The most frequently
+used is called \texttt{glob}; this is the same kind of pattern
+matching used by the Unix shell, and should be familiar to Windows
+command prompt users, too.  
+
+When Mercurial does automatic pattern matching on Windows, it uses
+\texttt{glob} syntax.  You can thus omit the ``\texttt{glob:}'' prefix
+on Windows, but it's safe to use it, too.
+
+The \texttt{re} syntax is more powerful; it lets you specify patterns
+using regular expressions, also known as regexps.
+
+By the way, in the examples that follow, notice that I'm careful to
+wrap all of my patterns in quote characters, so that they won't get
+expanded by the shell before Mercurial sees them.
+
+\subsection{Shell-style \texttt{glob} patterns}
+
+This is an overview of the kinds of patterns you can use when you're
+matching on glob patterns.
+
+The ``\texttt{*}'' character matches any string, within a single
+directory.
+\interaction{filenames.glob.star}
+
+The ``\texttt{**}'' pattern matches any string, and crosses directory
+boundaries.  It's not a standard Unix glob token, but it's accepted by
+several popular Unix shells, and is very useful.
+\interaction{filenames.glob.starstar}
+
+The ``\texttt{?}'' pattern matches any single character.
+\interaction{filenames.glob.question}
+
+The ``\texttt{[}'' character begins a \emph{character class}.  This
+matches any single character within the class.  The class ends with a
+``\texttt{]}'' character.  A class may contain multiple \emph{range}s
+of the form ``\texttt{a-f}'', which is shorthand for
+``\texttt{abcdef}''.
+\interaction{filenames.glob.range}
+If the first character after the ``\texttt{[}'' in a character class
+is a ``\texttt{!}'', it \emph{negates} the class, making it match any
+single character not in the class.
+
+A ``\texttt{\{}'' begins a group of subpatterns, where the whole group
+matches if any subpattern in the group matches.  The ``\texttt{,}''
+character separates subpatterns, and ``\texttt{\}}'' ends the group.
+\interaction{filenames.glob.group}
+
+\subsubsection{Watch out!}
+
+Don't forget that if you want to match a pattern in any directory, you
+should not be using the ``\texttt{*}'' match-any token, as this will
+only match within one directory.  Instead, use the ``\texttt{**}''
+token.  This small example illustrates the difference between the two.
+\interaction{filenames.glob.star-starstar}
+
+\subsection{Regular expression matching with \texttt{re} patterns}
+
+Mercurial accepts the same regular expression syntax as the Python
+programming language (it uses Python's regexp engine internally).
+This is based on the Perl language's regexp syntax, which is the most
+popular dialect in use (it's also used in Java, for example).
+
+I won't discuss Mercurial's regexp dialect in any detail here, as
+regexps are not often used.  Perl-style regexps are in any case
+already exhaustively documented on a multitude of web sites, and in
+many books.  Instead, I will focus here on a few things you should
+know if you find yourself needing to use regexps with Mercurial.
+
+A regexp is matched against an entire file name, relative to the root
+of the repository.  In other words, even if you're already in
+subbdirectory \dirname{foo}, if you want to match files under this
+directory, your pattern must start with ``\texttt{foo/}''.
+
+One thing to note, if you're familiar with Perl-style regexps, is that
+Mercurial's are \emph{rooted}.  That is, a regexp starts matching
+against the beginning of a string; it doesn't look for a match
+anywhere within the string.  To match anywhere in a string, start
+your pattern with ``\texttt{.*}''.
+
+\section{Filtering files}
+
+Not only does Mercurial give you a variety of ways to specify files;
+it lets you further winnow those files using \emph{filters}.  Commands
+that work with file names accept two filtering options.
+\begin{itemize}
+\item \hggopt{-I}, or \hggopt{--include}, lets you specify a pattern
+  that file names must match in order to be processed.
+\item \hggopt{-X}, or \hggopt{--exclude}, gives you a way to
+  \emph{avoid} processing files, if they match this pattern.
+\end{itemize}
+You can provide multiple \hggopt{-I} and \hggopt{-X} options on the
+command line, and intermix them as you please.  Mercurial interprets
+the patterns you provide using glob syntax by default (but you can use
+regexps if you need to).
+
+You can read a \hggopt{-I} filter as ``process only the files that
+match this filter''.
+\interaction{filenames.filter.include}
+The \hggopt{-X} filter is best read as ``process only the files that
+don't match this pattern''.
+\interaction{filenames.filter.exclude}
+
+\section{Ignoring unwanted files and directories}
+
+XXX.
+
+\section{Case sensitivity}
+\label{sec:names:case}
+
+If you're working in a mixed development environment that contains
+both Linux (or other Unix) systems and Macs or Windows systems, you
+should keep in the back of your mind the knowledge that they treat the
+case (``N'' versus ``n'') of file names in incompatible ways.  This is
+not very likely to affect you, and it's easy to deal with if it does,
+but it could surprise you if you don't know about it.
+
+Operating systems and filesystems differ in the way they handle the
+\emph{case} of characters in file and directory names.  There are
+three common ways to handle case in names.
+\begin{itemize}
+\item Completely case insensitive.  Uppercase and lowercase versions
+  of a letter are treated as identical, both when creating a file and
+  during subsequent accesses.  This is common on older DOS-based
+  systems.
+\item Case preserving, but insensitive.  When a file or directory is
+  created, the case of its name is stored, and can be retrieved and
+  displayed by the operating system.  When an existing file is being
+  looked up, its case is ignored.  This is the standard arrangement on
+  Windows and MacOS.  The names \filename{foo} and \filename{FoO}
+  identify the same file.  This treatment of uppercase and lowercase
+  letters as interchangeable is also referred to as \emph{case folding}.
+\item Case sensitive.  The case of a name is significant at all times.
+  The names \filename{foo} and {FoO} identify different files.  This
+  is the way Linux and Unix systems normally work.
+\end{itemize}
+
+On Unix-like systems, it is possible to have any or all of the above
+ways of handling case in action at once.  For example, if you use a
+USB thumb drive formatted with a FAT32 filesystem on a Linux system,
+Linux will handle names on that filesystem in a case preserving, but
+insensitive, way.
+
+\subsection{Safe, portable repository storage}
+
+Mercurial's repository storage mechanism is \emph{case safe}.  It
+translates file names so that they can be safely stored on both case
+sensitive and case insensitive filesystems.  This means that you can
+use normal file copying tools to transfer a Mercurial repository onto,
+for example, a USB thumb drive, and safely move that drive and
+repository back and forth between a Mac, a PC running Windows, and a
+Linux box.
+
+\subsection{Detecting case conflicts}
+
+When operating in the working directory, Mercurial honours the naming
+policy of the filesystem where the working directory is located.  If
+the filesystem is case preserving, but insensitive, Mercurial will
+treat names that differ only in case as the same.
+
+An important aspect of this approach is that it is possible to commit
+a changeset on a case sensitive (typically Linux or Unix) filesystem
+that will cause trouble for users on case insensitive (usually Windows
+and MacOS) users.  If a Linux user commits changes to two files, one
+named \filename{myfile.c} and the other named \filename{MyFile.C},
+they will be stored correctly in the repository.  And in the working
+directories of other Linux users, they will be correctly represented
+as separate files.
+
+If a Windows or Mac user pulls this change, they will not initially
+have a problem, because Mercurial's repository storage mechanism is
+case safe.  However, once they try to \hgcmd{update} the working
+directory to that changeset, or \hgcmd{merge} with that changeset,
+Mercurial will spot the conflict between the two file names that the
+filesystem would treat as the same, and forbid the update or merge
+from occurring.
+
+\subsection{Fixing a case conflict}
+
+If you are using Windows or a Mac in a mixed environment where some of
+your collaborators are using Linux or Unix, and Mercurial reports a
+case folding conflict when you try to \hgcmd{update} or \hgcmd{merge},
+the procedure to fix the problem is simple.
+
+Just find a nearby Linux or Unix box, clone the problem repository
+onto it, and use Mercurial's \hgcmd{rename} command to change the
+names of any offending files or directories so that they will no
+longer cause case folding conflicts.  Commit this change, \hgcmd{pull}
+or \hgcmd{push} it across to your Windows or MacOS system, and
+\hgcmd{update} to the revision with the non-conflicting names.
+
+The changeset with case-conflicting names will remain in your
+project's history, and you still won't be able to \hgcmd{update} your
+working directory to that changeset on a Windows or MacOS system, but
+you can continue development unimpeded.
+
+\begin{note}
+  Prior to version~0.9.3, Mercurial did not use a case safe repository
+  storage mechanism, and did not detect case folding conflicts.  If
+  you are using an older version of Mercurial on Windows or MacOS, I
+  strongly recommend that you upgrade.
+\end{note}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch08-branch.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,391 @@
+\chapter{Managing releases and branchy development}
+\label{chap:branch}
+
+Mercurial provides several mechanisms for you to manage a project that
+is making progress on multiple fronts at once.  To understand these
+mechanisms, let's first take a brief look at a fairly normal software
+project structure.
+
+Many software projects issue periodic ``major'' releases that contain
+substantial new features.  In parallel, they may issue ``minor''
+releases.  These are usually identical to the major releases off which
+they're based, but with a few bugs fixed.
+
+In this chapter, we'll start by talking about how to keep records of
+project milestones such as releases.  We'll then continue on to talk
+about the flow of work between different phases of a project, and how
+Mercurial can help you to isolate and manage this work.
+
+\section{Giving a persistent name to a revision}
+
+Once you decide that you'd like to call a particular revision a
+``release'', it's a good idea to record the identity of that revision.
+This will let you reproduce that release at a later date, for whatever
+purpose you might need at the time (reproducing a bug, porting to a
+new platform, etc).
+\interaction{tag.init}
+
+Mercurial lets you give a permanent name to any revision using the
+\hgcmd{tag} command.  Not surprisingly, these names are called
+``tags''.
+\interaction{tag.tag}
+
+A tag is nothing more than a ``symbolic name'' for a revision.  Tags
+exist purely for your convenience, so that you have a handy permanent
+way to refer to a revision; Mercurial doesn't interpret the tag names
+you use in any way.  Neither does Mercurial place any restrictions on
+the name of a tag, beyond a few that are necessary to ensure that a
+tag can be parsed unambiguously.  A tag name cannot contain any of the
+following characters:
+\begin{itemize}
+\item Colon (ASCII 58, ``\texttt{:}'')
+\item Carriage return (ASCII 13, ``\Verb+\r+'')
+\item Newline (ASCII 10, ``\Verb+\n+'')
+\end{itemize}
+
+You can use the \hgcmd{tags} command to display the tags present in
+your repository.  In the output, each tagged revision is identified
+first by its name, then by revision number, and finally by the unique
+hash of the revision.  
+\interaction{tag.tags}
+Notice that \texttt{tip} is listed in the output of \hgcmd{tags}.  The
+\texttt{tip} tag is a special ``floating'' tag, which always
+identifies the newest revision in the repository.
+
+In the output of the \hgcmd{tags} command, tags are listed in reverse
+order, by revision number.  This usually means that recent tags are
+listed before older tags.  It also means that \texttt{tip} is always
+going to be the first tag listed in the output of \hgcmd{tags}.
+
+When you run \hgcmd{log}, if it displays a revision that has tags
+associated with it, it will print those tags.
+\interaction{tag.log}
+
+Any time you need to provide a revision~ID to a Mercurial command, the
+command will accept a tag name in its place.  Internally, Mercurial
+will translate your tag name into the corresponding revision~ID, then
+use that.
+\interaction{tag.log.v1.0}
+
+There's no limit on the number of tags you can have in a repository,
+or on the number of tags that a single revision can have.  As a
+practical matter, it's not a great idea to have ``too many'' (a number
+which will vary from project to project), simply because tags are
+supposed to help you to find revisions.  If you have lots of tags, the
+ease of using them to identify revisions diminishes rapidly.
+
+For example, if your project has milestones as frequent as every few
+days, it's perfectly reasonable to tag each one of those.  But if you
+have a continuous build system that makes sure every revision can be
+built cleanly, you'd be introducing a lot of noise if you were to tag
+every clean build.  Instead, you could tag failed builds (on the
+assumption that they're rare!), or simply not use tags to track
+buildability.
+
+If you want to remove a tag that you no longer want, use
+\hgcmdargs{tag}{--remove}.  
+\interaction{tag.remove}
+You can also modify a tag at any time, so that it identifies a
+different revision, by simply issuing a new \hgcmd{tag} command.
+You'll have to use the \hgopt{tag}{-f} option to tell Mercurial that
+you \emph{really} want to update the tag.
+\interaction{tag.replace}
+There will still be a permanent record of the previous identity of the
+tag, but Mercurial will no longer use it.  There's thus no penalty to
+tagging the wrong revision; all you have to do is turn around and tag
+the correct revision once you discover your error.
+
+Mercurial stores tags in a normal revision-controlled file in your
+repository.  If you've created any tags, you'll find them in a file
+named \sfilename{.hgtags}.  When you run the \hgcmd{tag} command,
+Mercurial modifies this file, then automatically commits the change to
+it.  This means that every time you run \hgcmd{tag}, you'll see a
+corresponding changeset in the output of \hgcmd{log}.
+\interaction{tag.tip}
+
+\subsection{Handling tag conflicts during a merge}
+
+You won't often need to care about the \sfilename{.hgtags} file, but
+it sometimes makes its presence known during a merge.  The format of
+the file is simple: it consists of a series of lines.  Each line
+starts with a changeset hash, followed by a space, followed by the
+name of a tag.
+
+If you're resolving a conflict in the \sfilename{.hgtags} file during
+a merge, there's one twist to modifying the \sfilename{.hgtags} file:
+when Mercurial is parsing the tags in a repository, it \emph{never}
+reads the working copy of the \sfilename{.hgtags} file.  Instead, it
+reads the \emph{most recently committed} revision of the file.
+
+An unfortunate consequence of this design is that you can't actually
+verify that your merged \sfilename{.hgtags} file is correct until
+\emph{after} you've committed a change.  So if you find yourself
+resolving a conflict on \sfilename{.hgtags} during a merge, be sure to
+run \hgcmd{tags} after you commit.  If it finds an error in the
+\sfilename{.hgtags} file, it will report the location of the error,
+which you can then fix and commit.  You should then run \hgcmd{tags}
+again, just to be sure that your fix is correct.
+
+\subsection{Tags and cloning}
+
+You may have noticed that the \hgcmd{clone} command has a
+\hgopt{clone}{-r} option that lets you clone an exact copy of the
+repository as of a particular changeset.  The new clone will not
+contain any project history that comes after the revision you
+specified.  This has an interaction with tags that can surprise the
+unwary.
+
+Recall that a tag is stored as a revision to the \sfilename{.hgtags}
+file, so that when you create a tag, the changeset in which it's
+recorded necessarily refers to an older changeset.  When you run
+\hgcmdargs{clone}{-r foo} to clone a repository as of tag
+\texttt{foo}, the new clone \emph{will not contain the history that created the tag} that you used to clone the repository.  The result
+is that you'll get exactly the right subset of the project's history
+in the new repository, but \emph{not} the tag you might have expected.
+
+\subsection{When permanent tags are too much}
+
+Since Mercurial's tags are revision controlled and carried around with
+a project's history, everyone you work with will see the tags you
+create.  But giving names to revisions has uses beyond simply noting
+that revision \texttt{4237e45506ee} is really \texttt{v2.0.2}.  If
+you're trying to track down a subtle bug, you might want a tag to
+remind you of something like ``Anne saw the symptoms with this
+revision''.
+
+For cases like this, what you might want to use are \emph{local} tags.
+You can create a local tag with the \hgopt{tag}{-l} option to the
+\hgcmd{tag} command.  This will store the tag in a file called
+\sfilename{.hg/localtags}.  Unlike \sfilename{.hgtags},
+\sfilename{.hg/localtags} is not revision controlled.  Any tags you
+create using \hgopt{tag}{-l} remain strictly local to the repository
+you're currently working in.
+
+\section{The flow of changes---big picture vs. little}
+
+To return to the outline I sketched at the beginning of a chapter,
+let's think about a project that has multiple concurrent pieces of
+work under development at once.
+
+There might be a push for a new ``main'' release; a new minor bugfix
+release to the last main release; and an unexpected ``hot fix'' to an
+old release that is now in maintenance mode.
+
+The usual way people refer to these different concurrent directions of
+development is as ``branches''.  However, we've already seen numerous
+times that Mercurial treats \emph{all of history} as a series of
+branches and merges.  Really, what we have here is two ideas that are
+peripherally related, but which happen to share a name.
+\begin{itemize}
+\item ``Big picture'' branches represent the sweep of a project's
+  evolution; people give them names, and talk about them in
+  conversation.
+\item ``Little picture'' branches are artefacts of the day-to-day
+  activity of developing and merging changes.  They expose the
+  narrative of how the code was developed.
+\end{itemize}
+
+\section{Managing big-picture branches in repositories}
+
+The easiest way to isolate a ``big picture'' branch in Mercurial is in
+a dedicated repository.  If you have an existing shared
+repository---let's call it \texttt{myproject}---that reaches a ``1.0''
+milestone, you can start to prepare for future maintenance releases on
+top of version~1.0 by tagging the revision from which you prepared
+the~1.0 release.
+\interaction{branch-repo.tag}
+You can then clone a new shared \texttt{myproject-1.0.1} repository as
+of that tag.
+\interaction{branch-repo.clone}
+
+Afterwards, if someone needs to work on a bug fix that ought to go
+into an upcoming~1.0.1 minor release, they clone the
+\texttt{myproject-1.0.1} repository, make their changes, and push them
+back.
+\interaction{branch-repo.bugfix}
+Meanwhile, development for the next major release can continue,
+isolated and unabated, in the \texttt{myproject} repository.
+\interaction{branch-repo.new}
+
+\section{Don't repeat yourself: merging across branches}
+
+In many cases, if you have a bug to fix on a maintenance branch, the
+chances are good that the bug exists on your project's main branch
+(and possibly other maintenance branches, too).  It's a rare developer
+who wants to fix the same bug multiple times, so let's look at a few
+ways that Mercurial can help you to manage these bugfixes without
+duplicating your work.
+
+In the simplest instance, all you need to do is pull changes from your
+maintenance branch into your local clone of the target branch.
+\interaction{branch-repo.pull}
+You'll then need to merge the heads of the two branches, and push back
+to the main branch.
+\interaction{branch-repo.merge}
+
+\section{Naming branches within one repository}
+
+In most instances, isolating branches in repositories is the right
+approach.  Its simplicity makes it easy to understand; and so it's
+hard to make mistakes.  There's a one-to-one relationship between
+branches you're working in and directories on your system.  This lets
+you use normal (non-Mercurial-aware) tools to work on files within a
+branch/repository.
+
+If you're more in the ``power user'' category (\emph{and} your
+collaborators are too), there is an alternative way of handling
+branches that you can consider.  I've already mentioned the
+human-level distinction between ``small picture'' and ``big picture''
+branches.  While Mercurial works with multiple ``small picture''
+branches in a repository all the time (for example after you pull
+changes in, but before you merge them), it can \emph{also} work with
+multiple ``big picture'' branches.
+
+The key to working this way is that Mercurial lets you assign a
+persistent \emph{name} to a branch.  There always exists a branch
+named \texttt{default}.  Even before you start naming branches
+yourself, you can find traces of the \texttt{default} branch if you
+look for them.
+
+As an example, when you run the \hgcmd{commit} command, and it pops up
+your editor so that you can enter a commit message, look for a line
+that contains the text ``\texttt{HG: branch default}'' at the bottom.
+This is telling you that your commit will occur on the branch named
+\texttt{default}.
+
+To start working with named branches, use the \hgcmd{branches}
+command.  This command lists the named branches already present in
+your repository, telling you which changeset is the tip of each.
+\interaction{branch-named.branches}
+Since you haven't created any named branches yet, the only one that
+exists is \texttt{default}.
+
+To find out what the ``current'' branch is, run the \hgcmd{branch}
+command, giving it no arguments.  This tells you what branch the
+parent of the current changeset is on.
+\interaction{branch-named.branch}
+
+To create a new branch, run the \hgcmd{branch} command again.  This
+time, give it one argument: the name of the branch you want to create.
+\interaction{branch-named.create}
+
+After you've created a branch, you might wonder what effect the
+\hgcmd{branch} command has had.  What do the \hgcmd{status} and
+\hgcmd{tip} commands report?
+\interaction{branch-named.status}
+Nothing has changed in the working directory, and there's been no new
+history created.  As this suggests, running the \hgcmd{branch} command
+has no permanent effect; it only tells Mercurial what branch name to
+use the \emph{next} time you commit a changeset.
+
+When you commit a change, Mercurial records the name of the branch on
+which you committed.  Once you've switched from the \texttt{default}
+branch to another and committed, you'll see the name of the new branch
+show up in the output of \hgcmd{log}, \hgcmd{tip}, and other commands
+that display the same kind of output.
+\interaction{branch-named.commit}
+The \hgcmd{log}-like commands will print the branch name of every
+changeset that's not on the \texttt{default} branch.  As a result, if
+you never use named branches, you'll never see this information.
+
+Once you've named a branch and committed a change with that name,
+every subsequent commit that descends from that change will inherit
+the same branch name.  You can change the name of a branch at any
+time, using the \hgcmd{branch} command.  
+\interaction{branch-named.rebranch}
+In practice, this is something you won't do very often, as branch
+names tend to have fairly long lifetimes.  (This isn't a rule, just an
+observation.)
+
+\section{Dealing with multiple named branches in a repository}
+
+If you have more than one named branch in a repository, Mercurial will
+remember the branch that your working directory on when you start a
+command like \hgcmd{update} or \hgcmdargs{pull}{-u}.  It will update
+the working directory to the tip of this branch, no matter what the
+``repo-wide'' tip is.  To update to a revision that's on a different
+named branch, you may need to use the \hgopt{update}{-C} option to
+\hgcmd{update}.
+
+This behaviour is a little subtle, so let's see it in action.  First,
+let's remind ourselves what branch we're currently on, and what
+branches are in our repository.
+\interaction{branch-named.parents}
+We're on the \texttt{bar} branch, but there also exists an older
+\hgcmd{foo} branch.
+
+We can \hgcmd{update} back and forth between the tips of the
+\texttt{foo} and \texttt{bar} branches without needing to use the
+\hgopt{update}{-C} option, because this only involves going backwards
+and forwards linearly through our change history.
+\interaction{branch-named.update-switchy}
+
+If we go back to the \texttt{foo} branch and then run \hgcmd{update},
+it will keep us on \texttt{foo}, not move us to the tip of
+\texttt{bar}.
+\interaction{branch-named.update-nothing}
+
+Committing a new change on the \texttt{foo} branch introduces a new
+head.
+\interaction{branch-named.foo-commit}
+
+\section{Branch names and merging}
+
+As you've probably noticed, merges in Mercurial are not symmetrical.
+Let's say our repository has two heads, 17 and 23.  If I
+\hgcmd{update} to 17 and then \hgcmd{merge} with 23, Mercurial records
+17 as the first parent of the merge, and 23 as the second.  Whereas if
+I \hgcmd{update} to 23 and then \hgcmd{merge} with 17, it records 23
+as the first parent, and 17 as the second.
+
+This affects Mercurial's choice of branch name when you merge.  After
+a merge, Mercurial will retain the branch name of the first parent
+when you commit the result of the merge.  If your first parent's
+branch name is \texttt{foo}, and you merge with \texttt{bar}, the
+branch name will still be \texttt{foo} after you merge.
+
+It's not unusual for a repository to contain multiple heads, each with
+the same branch name.  Let's say I'm working on the \texttt{foo}
+branch, and so are you.  We commit different changes; I pull your
+changes; I now have two heads, each claiming to be on the \texttt{foo}
+branch.  The result of a merge will be a single head on the
+\texttt{foo} branch, as you might hope.
+
+But if I'm working on the \texttt{bar} branch, and I merge work from
+the \texttt{foo} branch, the result will remain on the \texttt{bar}
+branch.
+\interaction{branch-named.merge}
+
+To give a more concrete example, if I'm working on the
+\texttt{bleeding-edge} branch, and I want to bring in the latest fixes
+from the \texttt{stable} branch, Mercurial will choose the ``right''
+(\texttt{bleeding-edge}) branch name when I pull and merge from
+\texttt{stable}.
+
+\section{Branch naming is generally useful}
+
+You shouldn't think of named branches as applicable only to situations
+where you have multiple long-lived branches cohabiting in a single
+repository.  They're very useful even in the one-branch-per-repository
+case.  
+
+In the simplest case, giving a name to each branch gives you a
+permanent record of which branch a changeset originated on.  This
+gives you more context when you're trying to follow the history of a
+long-lived branchy project.
+
+If you're working with shared repositories, you can set up a
+\hook{pretxnchangegroup} hook on each that will block incoming changes
+that have the ``wrong'' branch name.  This provides a simple, but
+effective, defence against people accidentally pushing changes from a
+``bleeding edge'' branch to a ``stable'' branch.  Such a hook might
+look like this inside the shared repo's \hgrc.
+\begin{codesample2}
+  [hooks]
+  pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch
+\end{codesample2}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch09-undo.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,767 @@
+\chapter{Finding and fixing your mistakes}
+\label{chap:undo}
+
+To err might be human, but to really handle the consequences well
+takes a top-notch revision control system.  In this chapter, we'll
+discuss some of the techniques you can use when you find that a
+problem has crept into your project.  Mercurial has some highly
+capable features that will help you to isolate the sources of
+problems, and to handle them appropriately.
+
+\section{Erasing local history}
+
+\subsection{The accidental commit}
+
+I have the occasional but persistent problem of typing rather more
+quickly than I can think, which sometimes results in me committing a
+changeset that is either incomplete or plain wrong.  In my case, the
+usual kind of incomplete changeset is one in which I've created a new
+source file, but forgotten to \hgcmd{add} it.  A ``plain wrong''
+changeset is not as common, but no less annoying.
+
+\subsection{Rolling back a transaction}
+\label{sec:undo:rollback}
+
+In section~\ref{sec:concepts:txn}, I mentioned that Mercurial treats
+each modification of a repository as a \emph{transaction}.  Every time
+you commit a changeset or pull changes from another repository,
+Mercurial remembers what you did.  You can undo, or \emph{roll back},
+exactly one of these actions using the \hgcmd{rollback} command.  (See
+section~\ref{sec:undo:rollback-after-push} for an important caveat
+about the use of this command.)
+
+Here's a mistake that I often find myself making: committing a change
+in which I've created a new file, but forgotten to \hgcmd{add} it.
+\interaction{rollback.commit}
+Looking at the output of \hgcmd{status} after the commit immediately
+confirms the error.
+\interaction{rollback.status}
+The commit captured the changes to the file \filename{a}, but not the
+new file \filename{b}.  If I were to push this changeset to a
+repository that I shared with a colleague, the chances are high that
+something in \filename{a} would refer to \filename{b}, which would not
+be present in their repository when they pulled my changes.  I would
+thus become the object of some indignation.
+
+However, luck is with me---I've caught my error before I pushed the
+changeset.  I use the \hgcmd{rollback} command, and Mercurial makes
+that last changeset vanish.
+\interaction{rollback.rollback}
+Notice that the changeset is no longer present in the repository's
+history, and the working directory once again thinks that the file
+\filename{a} is modified.  The commit and rollback have left the
+working directory exactly as it was prior to the commit; the changeset
+has been completely erased.  I can now safely \hgcmd{add} the file
+\filename{b}, and rerun my commit.
+\interaction{rollback.add}
+
+\subsection{The erroneous pull}
+
+It's common practice with Mercurial to maintain separate development
+branches of a project in different repositories.  Your development
+team might have one shared repository for your project's ``0.9''
+release, and another, containing different changes, for the ``1.0''
+release.
+
+Given this, you can imagine that the consequences could be messy if
+you had a local ``0.9'' repository, and accidentally pulled changes
+from the shared ``1.0'' repository into it.  At worst, you could be
+paying insufficient attention, and push those changes into the shared
+``0.9'' tree, confusing your entire team (but don't worry, we'll
+return to this horror scenario later).  However, it's more likely that
+you'll notice immediately, because Mercurial will display the URL it's
+pulling from, or you will see it pull a suspiciously large number of
+changes into the repository.
+
+The \hgcmd{rollback} command will work nicely to expunge all of the
+changesets that you just pulled.  Mercurial groups all changes from
+one \hgcmd{pull} into a single transaction, so one \hgcmd{rollback} is
+all you need to undo this mistake.
+
+\subsection{Rolling back is useless once you've pushed}
+\label{sec:undo:rollback-after-push}
+
+The value of the \hgcmd{rollback} command drops to zero once you've
+pushed your changes to another repository.  Rolling back a change
+makes it disappear entirely, but \emph{only} in the repository in
+which you perform the \hgcmd{rollback}.  Because a rollback eliminates
+history, there's no way for the disappearance of a change to propagate
+between repositories.
+
+If you've pushed a change to another repository---particularly if it's
+a shared repository---it has essentially ``escaped into the wild,''
+and you'll have to recover from your mistake in a different way.  What
+will happen if you push a changeset somewhere, then roll it back, then
+pull from the repository you pushed to, is that the changeset will
+reappear in your repository.
+
+(If you absolutely know for sure that the change you want to roll back
+is the most recent change in the repository that you pushed to,
+\emph{and} you know that nobody else could have pulled it from that
+repository, you can roll back the changeset there, too, but you really
+should really not rely on this working reliably.  If you do this,
+sooner or later a change really will make it into a repository that
+you don't directly control (or have forgotten about), and come back to
+bite you.)
+
+\subsection{You can only roll back once}
+
+Mercurial stores exactly one transaction in its transaction log; that
+transaction is the most recent one that occurred in the repository.
+This means that you can only roll back one transaction.  If you expect
+to be able to roll back one transaction, then its predecessor, this is
+not the behaviour you will get.
+\interaction{rollback.twice}
+Once you've rolled back one transaction in a repository, you can't
+roll back again in that repository until you perform another commit or
+pull.
+
+\section{Reverting the mistaken change}
+
+If you make a modification to a file, and decide that you really
+didn't want to change the file at all, and you haven't yet committed
+your changes, the \hgcmd{revert} command is the one you'll need.  It
+looks at the changeset that's the parent of the working directory, and
+restores the contents of the file to their state as of that changeset.
+(That's a long-winded way of saying that, in the normal case, it
+undoes your modifications.)
+
+Let's illustrate how the \hgcmd{revert} command works with yet another
+small example.  We'll begin by modifying a file that Mercurial is
+already tracking.
+\interaction{daily.revert.modify}
+If we don't want that change, we can simply \hgcmd{revert} the file.
+\interaction{daily.revert.unmodify}
+The \hgcmd{revert} command provides us with an extra degree of safety
+by saving our modified file with a \filename{.orig} extension.
+\interaction{daily.revert.status}
+
+Here is a summary of the cases that the \hgcmd{revert} command can
+deal with.  We will describe each of these in more detail in the
+section that follows.
+\begin{itemize}
+\item If you modify a file, it will restore the file to its unmodified
+  state.
+\item If you \hgcmd{add} a file, it will undo the ``added'' state of
+  the file, but leave the file itself untouched.
+\item If you delete a file without telling Mercurial, it will restore
+  the file to its unmodified contents.
+\item If you use the \hgcmd{remove} command to remove a file, it will
+  undo the ``removed'' state of the file, and restore the file to its
+  unmodified contents.
+\end{itemize}
+
+\subsection{File management errors}
+\label{sec:undo:mgmt}
+
+The \hgcmd{revert} command is useful for more than just modified
+files.  It lets you reverse the results of all of Mercurial's file
+management commands---\hgcmd{add}, \hgcmd{remove}, and so on.
+
+If you \hgcmd{add} a file, then decide that in fact you don't want
+Mercurial to track it, use \hgcmd{revert} to undo the add.  Don't
+worry; Mercurial will not modify the file in any way.  It will just
+``unmark'' the file.
+\interaction{daily.revert.add}
+
+Similarly, if you ask Mercurial to \hgcmd{remove} a file, you can use
+\hgcmd{revert} to restore it to the contents it had as of the parent
+of the working directory.
+\interaction{daily.revert.remove}
+This works just as well for a file that you deleted by hand, without
+telling Mercurial (recall that in Mercurial terminology, this kind of
+file is called ``missing'').
+\interaction{daily.revert.missing}
+
+If you revert a \hgcmd{copy}, the copied-to file remains in your
+working directory afterwards, untracked.  Since a copy doesn't affect
+the copied-from file in any way, Mercurial doesn't do anything with
+the copied-from file.
+\interaction{daily.revert.copy}
+
+\subsubsection{A slightly special case: reverting a rename}
+
+If you \hgcmd{rename} a file, there is one small detail that
+you should remember.  When you \hgcmd{revert} a rename, it's not
+enough to provide the name of the renamed-to file, as you can see
+here.
+\interaction{daily.revert.rename}
+As you can see from the output of \hgcmd{status}, the renamed-to file
+is no longer identified as added, but the renamed-\emph{from} file is
+still removed!  This is counter-intuitive (at least to me), but at
+least it's easy to deal with.
+\interaction{daily.revert.rename-orig}
+So remember, to revert a \hgcmd{rename}, you must provide \emph{both}
+the source and destination names.  
+
+% TODO: the output doesn't look like it will be removed!
+
+(By the way, if you rename a file, then modify the renamed-to file,
+then revert both components of the rename, when Mercurial restores the
+file that was removed as part of the rename, it will be unmodified.
+If you need the modifications in the renamed-to file to show up in the
+renamed-from file, don't forget to copy them over.)
+
+These fiddly aspects of reverting a rename arguably constitute a small
+bug in Mercurial.
+
+\section{Dealing with committed changes}
+
+Consider a case where you have committed a change $a$, and another
+change $b$ on top of it; you then realise that change $a$ was
+incorrect.  Mercurial lets you ``back out'' an entire changeset
+automatically, and building blocks that let you reverse part of a
+changeset by hand.
+
+Before you read this section, here's something to keep in mind: the
+\hgcmd{backout} command undoes changes by \emph{adding} history, not
+by modifying or erasing it.  It's the right tool to use if you're
+fixing bugs, but not if you're trying to undo some change that has
+catastrophic consequences.  To deal with those, see
+section~\ref{sec:undo:aaaiiieee}.
+
+\subsection{Backing out a changeset}
+
+The \hgcmd{backout} command lets you ``undo'' the effects of an entire
+changeset in an automated fashion.  Because Mercurial's history is
+immutable, this command \emph{does not} get rid of the changeset you
+want to undo.  Instead, it creates a new changeset that
+\emph{reverses} the effect of the to-be-undone changeset.
+
+The operation of the \hgcmd{backout} command is a little intricate, so
+let's illustrate it with some examples.  First, we'll create a
+repository with some simple changes.
+\interaction{backout.init}
+
+The \hgcmd{backout} command takes a single changeset ID as its
+argument; this is the changeset to back out.  Normally,
+\hgcmd{backout} will drop you into a text editor to write a commit
+message, so you can record why you're backing the change out.  In this
+example, we provide a commit message on the command line using the
+\hgopt{backout}{-m} option.
+
+\subsection{Backing out the tip changeset}
+
+We're going to start by backing out the last changeset we committed.
+\interaction{backout.simple}
+You can see that the second line from \filename{myfile} is no longer
+present.  Taking a look at the output of \hgcmd{log} gives us an idea
+of what the \hgcmd{backout} command has done.
+\interaction{backout.simple.log}
+Notice that the new changeset that \hgcmd{backout} has created is a
+child of the changeset we backed out.  It's easier to see this in
+figure~\ref{fig:undo:backout}, which presents a graphical view of the
+change history.  As you can see, the history is nice and linear.
+
+\begin{figure}[htb]
+  \centering
+  \grafix{undo-simple}
+  \caption{Backing out a change using the \hgcmd{backout} command}
+  \label{fig:undo:backout}
+\end{figure}
+
+\subsection{Backing out a non-tip change}
+
+If you want to back out a change other than the last one you
+committed, pass the \hgopt{backout}{--merge} option to the
+\hgcmd{backout} command.
+\interaction{backout.non-tip.clone}
+This makes backing out any changeset a ``one-shot'' operation that's
+usually simple and fast.
+\interaction{backout.non-tip.backout}
+
+If you take a look at the contents of \filename{myfile} after the
+backout finishes, you'll see that the first and third changes are
+present, but not the second.
+\interaction{backout.non-tip.cat}
+
+As the graphical history in figure~\ref{fig:undo:backout-non-tip}
+illustrates, Mercurial actually commits \emph{two} changes in this
+kind of situation (the box-shaped nodes are the ones that Mercurial
+commits automatically).  Before Mercurial begins the backout process,
+it first remembers what the current parent of the working directory
+is.  It then backs out the target changeset, and commits that as a
+changeset.  Finally, it merges back to the previous parent of the
+working directory, and commits the result of the merge.
+
+% TODO: to me it looks like mercurial doesn't commit the second merge automatically!
+
+\begin{figure}[htb]
+  \centering
+  \grafix{undo-non-tip}
+  \caption{Automated backout of a non-tip change using the \hgcmd{backout} command}
+  \label{fig:undo:backout-non-tip}
+\end{figure}
+
+The result is that you end up ``back where you were'', only with some
+extra history that undoes the effect of the changeset you wanted to
+back out.
+
+\subsubsection{Always use the \hgopt{backout}{--merge} option}
+
+In fact, since the \hgopt{backout}{--merge} option will do the ``right
+thing'' whether or not the changeset you're backing out is the tip
+(i.e.~it won't try to merge if it's backing out the tip, since there's
+no need), you should \emph{always} use this option when you run the
+\hgcmd{backout} command.
+
+\subsection{Gaining more control of the backout process}
+
+While I've recommended that you always use the
+\hgopt{backout}{--merge} option when backing out a change, the
+\hgcmd{backout} command lets you decide how to merge a backout
+changeset.  Taking control of the backout process by hand is something
+you will rarely need to do, but it can be useful to understand what
+the \hgcmd{backout} command is doing for you automatically.  To
+illustrate this, let's clone our first repository, but omit the
+backout change that it contains.
+
+\interaction{backout.manual.clone}
+As with our earlier example, We'll commit a third changeset, then back
+out its parent, and see what happens.
+\interaction{backout.manual.backout} 
+Our new changeset is again a descendant of the changeset we backout
+out; it's thus a new head, \emph{not} a descendant of the changeset
+that was the tip.  The \hgcmd{backout} command was quite explicit in
+telling us this.
+\interaction{backout.manual.log}
+
+Again, it's easier to see what has happened by looking at a graph of
+the revision history, in figure~\ref{fig:undo:backout-manual}.  This
+makes it clear that when we use \hgcmd{backout} to back out a change
+other than the tip, Mercurial adds a new head to the repository (the
+change it committed is box-shaped).
+
+\begin{figure}[htb]
+  \centering
+  \grafix{undo-manual}
+  \caption{Backing out a change using the \hgcmd{backout} command}
+  \label{fig:undo:backout-manual}
+\end{figure}
+
+After the \hgcmd{backout} command has completed, it leaves the new
+``backout'' changeset as the parent of the working directory.
+\interaction{backout.manual.parents}
+Now we have two isolated sets of changes.
+\interaction{backout.manual.heads}
+
+Let's think about what we expect to see as the contents of
+\filename{myfile} now.  The first change should be present, because
+we've never backed it out.  The second change should be missing, as
+that's the change we backed out.  Since the history graph shows the
+third change as a separate head, we \emph{don't} expect to see the
+third change present in \filename{myfile}.
+\interaction{backout.manual.cat}
+To get the third change back into the file, we just do a normal merge
+of our two heads.
+\interaction{backout.manual.merge}
+Afterwards, the graphical history of our repository looks like
+figure~\ref{fig:undo:backout-manual-merge}.
+
+\begin{figure}[htb]
+  \centering
+  \grafix{undo-manual-merge}
+  \caption{Manually merging a backout change}
+  \label{fig:undo:backout-manual-merge}
+\end{figure}
+
+\subsection{Why \hgcmd{backout} works as it does}
+
+Here's a brief description of how the \hgcmd{backout} command works.
+\begin{enumerate}
+\item It ensures that the working directory is ``clean'', i.e.~that
+  the output of \hgcmd{status} would be empty.
+\item It remembers the current parent of the working directory.  Let's
+  call this changeset \texttt{orig}
+\item It does the equivalent of a \hgcmd{update} to sync the working
+  directory to the changeset you want to back out.  Let's call this
+  changeset \texttt{backout}
+\item It finds the parent of that changeset.  Let's call that
+  changeset \texttt{parent}.
+\item For each file that the \texttt{backout} changeset affected, it
+  does the equivalent of a \hgcmdargs{revert}{-r parent} on that file,
+  to restore it to the contents it had before that changeset was
+  committed.
+\item It commits the result as a new changeset.  This changeset has
+  \texttt{backout} as its parent.
+\item If you specify \hgopt{backout}{--merge} on the command line, it
+  merges with \texttt{orig}, and commits the result of the merge.
+\end{enumerate}
+
+An alternative way to implement the \hgcmd{backout} command would be
+to \hgcmd{export} the to-be-backed-out changeset as a diff, then use
+the \cmdopt{patch}{--reverse} option to the \command{patch} command to
+reverse the effect of the change without fiddling with the working
+directory.  This sounds much simpler, but it would not work nearly as
+well.
+
+The reason that \hgcmd{backout} does an update, a commit, a merge, and
+another commit is to give the merge machinery the best chance to do a
+good job when dealing with all the changes \emph{between} the change
+you're backing out and the current tip.  
+
+If you're backing out a changeset that's~100 revisions back in your
+project's history, the chances that the \command{patch} command will
+be able to apply a reverse diff cleanly are not good, because
+intervening changes are likely to have ``broken the context'' that
+\command{patch} uses to determine whether it can apply a patch (if
+this sounds like gibberish, see \ref{sec:mq:patch} for a
+discussion of the \command{patch} command).  Also, Mercurial's merge
+machinery will handle files and directories being renamed, permission
+changes, and modifications to binary files, none of which
+\command{patch} can deal with.
+
+\section{Changes that should never have been}
+\label{sec:undo:aaaiiieee}
+
+Most of the time, the \hgcmd{backout} command is exactly what you need
+if you want to undo the effects of a change.  It leaves a permanent
+record of exactly what you did, both when committing the original
+changeset and when you cleaned up after it.
+
+On rare occasions, though, you may find that you've committed a change
+that really should not be present in the repository at all.  For
+example, it would be very unusual, and usually considered a mistake,
+to commit a software project's object files as well as its source
+files.  Object files have almost no intrinsic value, and they're
+\emph{big}, so they increase the size of the repository and the amount
+of time it takes to clone or pull changes.
+
+Before I discuss the options that you have if you commit a ``brown
+paper bag'' change (the kind that's so bad that you want to pull a
+brown paper bag over your head), let me first discuss some approaches
+that probably won't work.
+
+Since Mercurial treats history as accumulative---every change builds
+on top of all changes that preceded it---you generally can't just make
+disastrous changes disappear.  The one exception is when you've just
+committed a change, and it hasn't been pushed or pulled into another
+repository.  That's when you can safely use the \hgcmd{rollback}
+command, as I detailed in section~\ref{sec:undo:rollback}.
+
+After you've pushed a bad change to another repository, you
+\emph{could} still use \hgcmd{rollback} to make your local copy of the
+change disappear, but it won't have the consequences you want.  The
+change will still be present in the remote repository, so it will
+reappear in your local repository the next time you pull.
+
+If a situation like this arises, and you know which repositories your
+bad change has propagated into, you can \emph{try} to get rid of the
+changeefrom \emph{every} one of those repositories.  This is, of
+course, not a satisfactory solution: if you miss even a single
+repository while you're expunging, the change is still ``in the
+wild'', and could propagate further.
+
+If you've committed one or more changes \emph{after} the change that
+you'd like to see disappear, your options are further reduced.
+Mercurial doesn't provide a way to ``punch a hole'' in history,
+leaving changesets intact.
+
+XXX This needs filling out.  The \texttt{hg-replay} script in the
+\texttt{examples} directory works, but doesn't handle merge
+changesets.  Kind of an important omission.
+
+\subsection{Protect yourself from ``escaped'' changes}
+
+If you've committed some changes to your local repository and they've
+been pushed or pulled somewhere else, this isn't necessarily a
+disaster.  You can protect yourself ahead of time against some classes
+of bad changeset.  This is particularly easy if your team usually
+pulls changes from a central repository.
+
+By configuring some hooks on that repository to validate incoming
+changesets (see chapter~\ref{chap:hook}), you can automatically
+prevent some kinds of bad changeset from being pushed to the central
+repository at all.  With such a configuration in place, some kinds of
+bad changeset will naturally tend to ``die out'' because they can't
+propagate into the central repository.  Better yet, this happens
+without any need for explicit intervention.
+
+For instance, an incoming change hook that verifies that a changeset
+will actually compile can prevent people from inadvertantly ``breaking
+the build''.
+
+\section{Finding the source of a bug}
+\label{sec:undo:bisect}
+
+While it's all very well to be able to back out a changeset that
+introduced a bug, this requires that you know which changeset to back
+out.  Mercurial provides an invaluable command, called
+\hgcmd{bisect}, that helps you to automate this process and accomplish
+it very efficiently.
+
+The idea behind the \hgcmd{bisect} command is that a changeset has
+introduced some change of behaviour that you can identify with a
+simple binary test.  You don't know which piece of code introduced the
+change, but you know how to test for the presence of the bug.  The
+\hgcmd{bisect} command uses your test to direct its search for the
+changeset that introduced the code that caused the bug.
+
+Here are a few scenarios to help you understand how you might apply
+this command.
+\begin{itemize}
+\item The most recent version of your software has a bug that you
+  remember wasn't present a few weeks ago, but you don't know when it
+  was introduced.  Here, your binary test checks for the presence of
+  that bug.
+\item You fixed a bug in a rush, and now it's time to close the entry
+  in your team's bug database.  The bug database requires a changeset
+  ID when you close an entry, but you don't remember which changeset
+  you fixed the bug in.  Once again, your binary test checks for the
+  presence of the bug.
+\item Your software works correctly, but runs~15\% slower than the
+  last time you measured it.  You want to know which changeset
+  introduced the performance regression.  In this case, your binary
+  test measures the performance of your software, to see whether it's
+  ``fast'' or ``slow''.
+\item The sizes of the components of your project that you ship
+  exploded recently, and you suspect that something changed in the way
+  you build your project.
+\end{itemize}
+
+From these examples, it should be clear that the \hgcmd{bisect}
+command is not useful only for finding the sources of bugs.  You can
+use it to find any ``emergent property'' of a repository (anything
+that you can't find from a simple text search of the files in the
+tree) for which you can write a binary test.
+
+We'll introduce a little bit of terminology here, just to make it
+clear which parts of the search process are your responsibility, and
+which are Mercurial's.  A \emph{test} is something that \emph{you} run
+when \hgcmd{bisect} chooses a changeset.  A \emph{probe} is what
+\hgcmd{bisect} runs to tell whether a revision is good.  Finally,
+we'll use the word ``bisect'', as both a noun and a verb, to stand in
+for the phrase ``search using the \hgcmd{bisect} command.
+
+One simple way to automate the searching process would be simply to
+probe every changeset.  However, this scales poorly.  If it took ten
+minutes to test a single changeset, and you had 10,000 changesets in
+your repository, the exhaustive approach would take on average~35
+\emph{days} to find the changeset that introduced a bug.  Even if you
+knew that the bug was introduced by one of the last 500 changesets,
+and limited your search to those, you'd still be looking at over 40
+hours to find the changeset that introduced your bug.
+
+What the \hgcmd{bisect} command does is use its knowledge of the
+``shape'' of your project's revision history to perform a search in
+time proportional to the \emph{logarithm} of the number of changesets
+to check (the kind of search it performs is called a dichotomic
+search).  With this approach, searching through 10,000 changesets will
+take less than three hours, even at ten minutes per test (the search
+will require about 14 tests).  Limit your search to the last hundred
+changesets, and it will take only about an hour (roughly seven tests).
+
+The \hgcmd{bisect} command is aware of the ``branchy'' nature of a
+Mercurial project's revision history, so it has no problems dealing
+with branches, merges, or multiple heads in a repository.  It can
+prune entire branches of history with a single probe, which is how it
+operates so efficiently.
+
+\subsection{Using the \hgcmd{bisect} command}
+
+Here's an example of \hgcmd{bisect} in action.
+
+\begin{note}
+  In versions 0.9.5 and earlier of Mercurial, \hgcmd{bisect} was not a
+  core command: it was distributed with Mercurial as an extension.
+  This section describes the built-in command, not the old extension.
+\end{note}
+
+Now let's create a repository, so that we can try out the
+\hgcmd{bisect} command in isolation.
+\interaction{bisect.init}
+We'll simulate a project that has a bug in it in a simple-minded way:
+create trivial changes in a loop, and nominate one specific change
+that will have the ``bug''.  This loop creates 35 changesets, each
+adding a single file to the repository.  We'll represent our ``bug''
+with a file that contains the text ``i have a gub''.
+\interaction{bisect.commits}
+
+The next thing that we'd like to do is figure out how to use the
+\hgcmd{bisect} command.  We can use Mercurial's normal built-in help
+mechanism for this.
+\interaction{bisect.help}
+
+The \hgcmd{bisect} command works in steps.  Each step proceeds as follows.
+\begin{enumerate}
+\item You run your binary test.
+  \begin{itemize}
+  \item If the test succeeded, you tell \hgcmd{bisect} by running the
+    \hgcmdargs{bisect}{good} command.
+  \item If it failed, run the \hgcmdargs{bisect}{--bad} command.
+  \end{itemize}
+\item The command uses your information to decide which changeset to
+  test next.
+\item It updates the working directory to that changeset, and the
+  process begins again.
+\end{enumerate}
+The process ends when \hgcmd{bisect} identifies a unique changeset
+that marks the point where your test transitioned from ``succeeding''
+to ``failing''.
+
+To start the search, we must run the \hgcmdargs{bisect}{--reset} command.
+\interaction{bisect.search.init}
+
+In our case, the binary test we use is simple: we check to see if any
+file in the repository contains the string ``i have a gub''.  If it
+does, this changeset contains the change that ``caused the bug''.  By
+convention, a changeset that has the property we're searching for is
+``bad'', while one that doesn't is ``good''.
+
+Most of the time, the revision to which the working directory is
+synced (usually the tip) already exhibits the problem introduced by
+the buggy change, so we'll mark it as ``bad''.
+\interaction{bisect.search.bad-init}
+
+Our next task is to nominate a changeset that we know \emph{doesn't}
+have the bug; the \hgcmd{bisect} command will ``bracket'' its search
+between the first pair of good and bad changesets.  In our case, we
+know that revision~10 didn't have the bug.  (I'll have more words
+about choosing the first ``good'' changeset later.)
+\interaction{bisect.search.good-init}
+
+Notice that this command printed some output.
+\begin{itemize}
+\item It told us how many changesets it must consider before it can
+  identify the one that introduced the bug, and how many tests that
+  will require.
+\item It updated the working directory to the next changeset to test,
+  and told us which changeset it's testing.
+\end{itemize}
+
+We now run our test in the working directory.  We use the
+\command{grep} command to see if our ``bad'' file is present in the
+working directory.  If it is, this revision is bad; if not, this
+revision is good.
+\interaction{bisect.search.step1}
+
+This test looks like a perfect candidate for automation, so let's turn
+it into a shell function.
+\interaction{bisect.search.mytest}
+We can now run an entire test step with a single command,
+\texttt{mytest}.
+\interaction{bisect.search.step2}
+A few more invocations of our canned test step command, and we're
+done.
+\interaction{bisect.search.rest}
+
+Even though we had~40 changesets to search through, the \hgcmd{bisect}
+command let us find the changeset that introduced our ``bug'' with
+only five tests.  Because the number of tests that the \hgcmd{bisect}
+command performs grows logarithmically with the number of changesets to
+search, the advantage that it has over the ``brute force'' search
+approach increases with every changeset you add.
+
+\subsection{Cleaning up after your search}
+
+When you're finished using the \hgcmd{bisect} command in a
+repository, you can use the \hgcmdargs{bisect}{reset} command to drop
+the information it was using to drive your search.  The command
+doesn't use much space, so it doesn't matter if you forget to run this
+command.  However, \hgcmd{bisect} won't let you start a new search in
+that repository until you do a \hgcmdargs{bisect}{reset}.
+\interaction{bisect.search.reset}
+
+\section{Tips for finding bugs effectively}
+
+\subsection{Give consistent input}
+
+The \hgcmd{bisect} command requires that you correctly report the
+result of every test you perform.  If you tell it that a test failed
+when it really succeeded, it \emph{might} be able to detect the
+inconsistency.  If it can identify an inconsistency in your reports,
+it will tell you that a particular changeset is both good and bad.
+However, it can't do this perfectly; it's about as likely to report
+the wrong changeset as the source of the bug.
+
+\subsection{Automate as much as possible}
+
+When I started using the \hgcmd{bisect} command, I tried a few times
+to run my tests by hand, on the command line.  This is an approach
+that I, at least, am not suited to.  After a few tries, I found that I
+was making enough mistakes that I was having to restart my searches
+several times before finally getting correct results.
+
+My initial problems with driving the \hgcmd{bisect} command by hand
+occurred even with simple searches on small repositories; if the
+problem you're looking for is more subtle, or the number of tests that
+\hgcmd{bisect} must perform increases, the likelihood of operator
+error ruining the search is much higher.  Once I started automating my
+tests, I had much better results.
+
+The key to automated testing is twofold:
+\begin{itemize}
+\item always test for the same symptom, and
+\item always feed consistent input to the \hgcmd{bisect} command.
+\end{itemize}
+In my tutorial example above, the \command{grep} command tests for the
+symptom, and the \texttt{if} statement takes the result of this check
+and ensures that we always feed the same input to the \hgcmd{bisect}
+command.  The \texttt{mytest} function marries these together in a
+reproducible way, so that every test is uniform and consistent.
+
+\subsection{Check your results}
+
+Because the output of a \hgcmd{bisect} search is only as good as the
+input you give it, don't take the changeset it reports as the
+absolute truth.  A simple way to cross-check its report is to manually
+run your test at each of the following changesets:
+\begin{itemize}
+\item The changeset that it reports as the first bad revision.  Your
+  test should still report this as bad.
+\item The parent of that changeset (either parent, if it's a merge).
+  Your test should report this changeset as good.
+\item A child of that changeset.  Your test should report this
+  changeset as bad.
+\end{itemize}
+
+\subsection{Beware interference between bugs}
+
+It's possible that your search for one bug could be disrupted by the
+presence of another.  For example, let's say your software crashes at
+revision 100, and worked correctly at revision 50.  Unknown to you,
+someone else introduced a different crashing bug at revision 60, and
+fixed it at revision 80.  This could distort your results in one of
+several ways.
+
+It is possible that this other bug completely ``masks'' yours, which
+is to say that it occurs before your bug has a chance to manifest
+itself.  If you can't avoid that other bug (for example, it prevents
+your project from building), and so can't tell whether your bug is
+present in a particular changeset, the \hgcmd{bisect} command cannot
+help you directly.  Instead, you can mark a changeset as untested by
+running \hgcmdargs{bisect}{--skip}.
+
+A different problem could arise if your test for a bug's presence is
+not specific enough.  If you check for ``my program crashes'', then
+both your crashing bug and an unrelated crashing bug that masks it
+will look like the same thing, and mislead \hgcmd{bisect}.
+
+Another useful situation in which to use \hgcmdargs{bisect}{--skip} is
+if you can't test a revision because your project was in a broken and
+hence untestable state at that revision, perhaps because someone
+checked in a change that prevented the project from building.
+
+\subsection{Bracket your search lazily}
+
+Choosing the first ``good'' and ``bad'' changesets that will mark the
+end points of your search is often easy, but it bears a little
+discussion nevertheless.  From the perspective of \hgcmd{bisect}, the
+``newest'' changeset is conventionally ``bad'', and the older
+changeset is ``good''.
+
+If you're having trouble remembering when a suitable ``good'' change
+was, so that you can tell \hgcmd{bisect}, you could do worse than
+testing changesets at random.  Just remember to eliminate contenders
+that can't possibly exhibit the bug (perhaps because the feature with
+the bug isn't present yet) and those where another problem masks the
+bug (as I discussed above).
+
+Even if you end up ``early'' by thousands of changesets or months of
+history, you will only add a handful of tests to the total number that
+\hgcmd{bisect} must perform, thanks to its logarithmic behaviour.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch10-hook.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1413 @@
+\chapter{Handling repository events with hooks}
+\label{chap:hook}
+
+Mercurial offers a powerful mechanism to let you perform automated
+actions in response to events that occur in a repository.  In some
+cases, you can even control Mercurial's response to those events.
+
+The name Mercurial uses for one of these actions is a \emph{hook}.
+Hooks are called ``triggers'' in some revision control systems, but
+the two names refer to the same idea.
+
+\section{An overview of hooks in Mercurial}
+
+Here is a brief list of the hooks that Mercurial supports.  We will
+revisit each of these hooks in more detail later, in
+section~\ref{sec:hook:ref}.
+
+\begin{itemize}
+\item[\small\hook{changegroup}] This is run after a group of
+  changesets has been brought into the repository from elsewhere.
+\item[\small\hook{commit}] This is run after a new changeset has been
+  created in the local repository.
+\item[\small\hook{incoming}] This is run once for each new changeset
+  that is brought into the repository from elsewhere.  Notice the
+  difference from \hook{changegroup}, which is run once per
+  \emph{group} of changesets brought in.
+\item[\small\hook{outgoing}] This is run after a group of changesets
+  has been transmitted from this repository.
+\item[\small\hook{prechangegroup}] This is run before starting to
+  bring a group of changesets into the repository.
+\item[\small\hook{precommit}] Controlling. This is run before starting
+  a commit.
+\item[\small\hook{preoutgoing}] Controlling. This is run before
+  starting to transmit a group of changesets from this repository.
+\item[\small\hook{pretag}] Controlling. This is run before creating a tag.
+\item[\small\hook{pretxnchangegroup}] Controlling. This is run after a
+  group of changesets has been brought into the local repository from
+  another, but before the transaction completes that will make the
+  changes permanent in the repository.
+\item[\small\hook{pretxncommit}] Controlling. This is run after a new
+  changeset has been created in the local repository, but before the
+  transaction completes that will make it permanent.
+\item[\small\hook{preupdate}] Controlling. This is run before starting
+  an update or merge of the working directory.
+\item[\small\hook{tag}] This is run after a tag is created.
+\item[\small\hook{update}] This is run after an update or merge of the
+  working directory has finished.
+\end{itemize}
+Each of the hooks whose description begins with the word
+``Controlling'' has the ability to determine whether an activity can
+proceed.  If the hook succeeds, the activity may proceed; if it fails,
+the activity is either not permitted or undone, depending on the hook.
+
+\section{Hooks and security}
+
+\subsection{Hooks are run with your privileges}
+
+When you run a Mercurial command in a repository, and the command
+causes a hook to run, that hook runs on \emph{your} system, under
+\emph{your} user account, with \emph{your} privilege level.  Since
+hooks are arbitrary pieces of executable code, you should treat them
+with an appropriate level of suspicion.  Do not install a hook unless
+you are confident that you know who created it and what it does.
+
+In some cases, you may be exposed to hooks that you did not install
+yourself.  If you work with Mercurial on an unfamiliar system,
+Mercurial will run hooks defined in that system's global \hgrc\ file.
+
+If you are working with a repository owned by another user, Mercurial
+can run hooks defined in that user's repository, but it will still run
+them as ``you''.  For example, if you \hgcmd{pull} from that
+repository, and its \sfilename{.hg/hgrc} defines a local
+\hook{outgoing} hook, that hook will run under your user account, even
+though you don't own that repository.
+
+\begin{note}
+  This only applies if you are pulling from a repository on a local or
+  network filesystem.  If you're pulling over http or ssh, any
+  \hook{outgoing} hook will run under whatever account is executing
+  the server process, on the server.
+\end{note}
+
+XXX To see what hooks are defined in a repository, use the
+\hgcmdargs{config}{hooks} command.  If you are working in one
+repository, but talking to another that you do not own (e.g.~using
+\hgcmd{pull} or \hgcmd{incoming}), remember that it is the other
+repository's hooks you should be checking, not your own.
+
+\subsection{Hooks do not propagate}
+
+In Mercurial, hooks are not revision controlled, and do not propagate
+when you clone, or pull from, a repository.  The reason for this is
+simple: a hook is a completely arbitrary piece of executable code.  It
+runs under your user identity, with your privilege level, on your
+machine.
+
+It would be extremely reckless for any distributed revision control
+system to implement revision-controlled hooks, as this would offer an
+easily exploitable way to subvert the accounts of users of the
+revision control system.
+
+Since Mercurial does not propagate hooks, if you are collaborating
+with other people on a common project, you should not assume that they
+are using the same Mercurial hooks as you are, or that theirs are
+correctly configured.  You should document the hooks you expect people
+to use.
+
+In a corporate intranet, this is somewhat easier to control, as you
+can for example provide a ``standard'' installation of Mercurial on an
+NFS filesystem, and use a site-wide \hgrc\ file to define hooks that
+all users will see.  However, this too has its limits; see below.
+
+\subsection{Hooks can be overridden}
+
+Mercurial allows you to override a hook definition by redefining the
+hook.  You can disable it by setting its value to the empty string, or
+change its behaviour as you wish.
+
+If you deploy a system-~or site-wide \hgrc\ file that defines some
+hooks, you should thus understand that your users can disable or
+override those hooks.
+
+\subsection{Ensuring that critical hooks are run}
+
+Sometimes you may want to enforce a policy that you do not want others
+to be able to work around.  For example, you may have a requirement
+that every changeset must pass a rigorous set of tests.  Defining this
+requirement via a hook in a site-wide \hgrc\ won't work for remote
+users on laptops, and of course local users can subvert it at will by
+overriding the hook.
+
+Instead, you can set up your policies for use of Mercurial so that
+people are expected to propagate changes through a well-known
+``canonical'' server that you have locked down and configured
+appropriately.
+
+One way to do this is via a combination of social engineering and
+technology.  Set up a restricted-access account; users can push
+changes over the network to repositories managed by this account, but
+they cannot log into the account and run normal shell commands.  In
+this scenario, a user can commit a changeset that contains any old
+garbage they want.
+
+When someone pushes a changeset to the server that everyone pulls
+from, the server will test the changeset before it accepts it as
+permanent, and reject it if it fails to pass the test suite.  If
+people only pull changes from this filtering server, it will serve to
+ensure that all changes that people pull have been automatically
+vetted.
+
+\section{Care with \texttt{pretxn} hooks in a shared-access repository}
+
+If you want to use hooks to do some automated work in a repository
+that a number of people have shared access to, you need to be careful
+in how you do this.
+
+Mercurial only locks a repository when it is writing to the
+repository, and only the parts of Mercurial that write to the
+repository pay attention to locks.  Write locks are necessary to
+prevent multiple simultaneous writers from scribbling on each other's
+work, corrupting the repository.
+
+Because Mercurial is careful with the order in which it reads and
+writes data, it does not need to acquire a lock when it wants to read
+data from the repository.  The parts of Mercurial that read from the
+repository never pay attention to locks.  This lockless reading scheme
+greatly increases performance and concurrency.
+
+With great performance comes a trade-off, though, one which has the
+potential to cause you trouble unless you're aware of it.  To describe
+this requires a little detail about how Mercurial adds changesets to a
+repository and reads those changes.
+
+When Mercurial \emph{writes} metadata, it writes it straight into the
+destination file.  It writes file data first, then manifest data
+(which contains pointers to the new file data), then changelog data
+(which contains pointers to the new manifest data).  Before the first
+write to each file, it stores a record of where the end of the file
+was in its transaction log.  If the transaction must be rolled back,
+Mercurial simply truncates each file back to the size it was before the
+transaction began.
+
+When Mercurial \emph{reads} metadata, it reads the changelog first,
+then everything else.  Since a reader will only access parts of the
+manifest or file metadata that it can see in the changelog, it can
+never see partially written data.
+
+Some controlling hooks (\hook{pretxncommit} and
+\hook{pretxnchangegroup}) run when a transaction is almost complete.
+All of the metadata has been written, but Mercurial can still roll the
+transaction back and cause the newly-written data to disappear.
+
+If one of these hooks runs for long, it opens a window of time during
+which a reader can see the metadata for changesets that are not yet
+permanent, and should not be thought of as ``really there''.  The
+longer the hook runs, the longer that window is open.
+
+\subsection{The problem illustrated}
+
+In principle, a good use for the \hook{pretxnchangegroup} hook would
+be to automatically build and test incoming changes before they are
+accepted into a central repository.  This could let you guarantee that
+nobody can push changes to this repository that ``break the build''.
+But if a client can pull changes while they're being tested, the
+usefulness of the test is zero; an unsuspecting someone can pull
+untested changes, potentially breaking their build.
+
+The safest technological answer to this challenge is to set up such a
+``gatekeeper'' repository as \emph{unidirectional}.  Let it take
+changes pushed in from the outside, but do not allow anyone to pull
+changes from it (use the \hook{preoutgoing} hook to lock it down).
+Configure a \hook{changegroup} hook so that if a build or test
+succeeds, the hook will push the new changes out to another repository
+that people \emph{can} pull from.
+
+In practice, putting a centralised bottleneck like this in place is
+not often a good idea, and transaction visibility has nothing to do
+with the problem.  As the size of a project---and the time it takes to
+build and test---grows, you rapidly run into a wall with this ``try
+before you buy'' approach, where you have more changesets to test than
+time in which to deal with them.  The inevitable result is frustration
+on the part of all involved.
+
+An approach that scales better is to get people to build and test
+before they push, then run automated builds and tests centrally
+\emph{after} a push, to be sure all is well.  The advantage of this
+approach is that it does not impose a limit on the rate at which the
+repository can accept changes.
+
+\section{A short tutorial on using hooks}
+\label{sec:hook:simple}
+
+It is easy to write a Mercurial hook.  Let's start with a hook that
+runs when you finish a \hgcmd{commit}, and simply prints the hash of
+the changeset you just created.  The hook is called \hook{commit}.
+
+\begin{figure}[ht]
+  \interaction{hook.simple.init}
+  \caption{A simple hook that runs when a changeset is committed}
+  \label{ex:hook:init}
+\end{figure}
+
+All hooks follow the pattern in example~\ref{ex:hook:init}.  You add
+an entry to the \rcsection{hooks} section of your \hgrc.  On the left
+is the name of the event to trigger on; on the right is the action to
+take.  As you can see, you can run an arbitrary shell command in a
+hook.  Mercurial passes extra information to the hook using
+environment variables (look for \envar{HG\_NODE} in the example).
+
+\subsection{Performing multiple actions per event}
+
+Quite often, you will want to define more than one hook for a
+particular kind of event, as shown in example~\ref{ex:hook:ext}.
+Mercurial lets you do this by adding an \emph{extension} to the end of
+a hook's name.  You extend a hook's name by giving the name of the
+hook, followed by a full stop (the ``\texttt{.}'' character), followed
+by some more text of your choosing.  For example, Mercurial will run
+both \texttt{commit.foo} and \texttt{commit.bar} when the
+\texttt{commit} event occurs.
+
+\begin{figure}[ht]
+  \interaction{hook.simple.ext}
+  \caption{Defining a second \hook{commit} hook}
+  \label{ex:hook:ext}
+\end{figure}
+
+To give a well-defined order of execution when there are multiple
+hooks defined for an event, Mercurial sorts hooks by extension, and
+executes the hook commands in this sorted order.  In the above
+example, it will execute \texttt{commit.bar} before
+\texttt{commit.foo}, and \texttt{commit} before both.
+
+It is a good idea to use a somewhat descriptive extension when you
+define a new hook.  This will help you to remember what the hook was
+for.  If the hook fails, you'll get an error message that contains the
+hook name and extension, so using a descriptive extension could give
+you an immediate hint as to why the hook failed (see
+section~\ref{sec:hook:perm} for an example).
+
+\subsection{Controlling whether an activity can proceed}
+\label{sec:hook:perm}
+
+In our earlier examples, we used the \hook{commit} hook, which is
+run after a commit has completed.  This is one of several Mercurial
+hooks that run after an activity finishes.  Such hooks have no way of
+influencing the activity itself.
+
+Mercurial defines a number of events that occur before an activity
+starts; or after it starts, but before it finishes.  Hooks that
+trigger on these events have the added ability to choose whether the
+activity can continue, or will abort.  
+
+The \hook{pretxncommit} hook runs after a commit has all but
+completed.  In other words, the metadata representing the changeset
+has been written out to disk, but the transaction has not yet been
+allowed to complete.  The \hook{pretxncommit} hook has the ability to
+decide whether the transaction can complete, or must be rolled back.
+
+If the \hook{pretxncommit} hook exits with a status code of zero, the
+transaction is allowed to complete; the commit finishes; and the
+\hook{commit} hook is run.  If the \hook{pretxncommit} hook exits with
+a non-zero status code, the transaction is rolled back; the metadata
+representing the changeset is erased; and the \hook{commit} hook is
+not run.
+
+\begin{figure}[ht]
+  \interaction{hook.simple.pretxncommit}
+  \caption{Using the \hook{pretxncommit} hook to control commits}
+  \label{ex:hook:pretxncommit}
+\end{figure}
+
+The hook in example~\ref{ex:hook:pretxncommit} checks that a commit
+comment contains a bug ID.  If it does, the commit can complete.  If
+not, the commit is rolled back.
+
+\section{Writing your own hooks}
+
+When you are writing a hook, you might find it useful to run Mercurial
+either with the \hggopt{-v} option, or the \rcitem{ui}{verbose} config
+item set to ``true''.  When you do so, Mercurial will print a message
+before it calls each hook.
+
+\subsection{Choosing how your hook should run}
+\label{sec:hook:lang}
+
+You can write a hook either as a normal program---typically a shell
+script---or as a Python function that is executed within the Mercurial
+process.
+
+Writing a hook as an external program has the advantage that it
+requires no knowledge of Mercurial's internals.  You can call normal
+Mercurial commands to get any added information you need.  The
+trade-off is that external hooks are slower than in-process hooks.
+
+An in-process Python hook has complete access to the Mercurial API,
+and does not ``shell out'' to another process, so it is inherently
+faster than an external hook.  It is also easier to obtain much of the
+information that a hook requires by using the Mercurial API than by
+running Mercurial commands.
+
+If you are comfortable with Python, or require high performance,
+writing your hooks in Python may be a good choice.  However, when you
+have a straightforward hook to write and you don't need to care about
+performance (probably the majority of hooks), a shell script is
+perfectly fine.
+
+\subsection{Hook parameters}
+\label{sec:hook:param}
+
+Mercurial calls each hook with a set of well-defined parameters.  In
+Python, a parameter is passed as a keyword argument to your hook
+function.  For an external program, a parameter is passed as an
+environment variable.
+
+Whether your hook is written in Python or as a shell script, the
+hook-specific parameter names and values will be the same.  A boolean
+parameter will be represented as a boolean value in Python, but as the
+number 1 (for ``true'') or 0 (for ``false'') as an environment
+variable for an external hook.  If a hook parameter is named
+\texttt{foo}, the keyword argument for a Python hook will also be
+named \texttt{foo}, while the environment variable for an external
+hook will be named \texttt{HG\_FOO}.
+
+\subsection{Hook return values and activity control}
+
+A hook that executes successfully must exit with a status of zero if
+external, or return boolean ``false'' if in-process.  Failure is
+indicated with a non-zero exit status from an external hook, or an
+in-process hook returning boolean ``true''.  If an in-process hook
+raises an exception, the hook is considered to have failed.
+
+For a hook that controls whether an activity can proceed, zero/false
+means ``allow'', while non-zero/true/exception means ``deny''.
+
+\subsection{Writing an external hook}
+
+When you define an external hook in your \hgrc\ and the hook is run,
+its value is passed to your shell, which interprets it.  This means
+that you can use normal shell constructs in the body of the hook.
+
+An executable hook is always run with its current directory set to a
+repository's root directory.
+
+Each hook parameter is passed in as an environment variable; the name
+is upper-cased, and prefixed with the string ``\texttt{HG\_}''.
+
+With the exception of hook parameters, Mercurial does not set or
+modify any environment variables when running a hook.  This is useful
+to remember if you are writing a site-wide hook that may be run by a
+number of different users with differing environment variables set.
+In multi-user situations, you should not rely on environment variables
+being set to the values you have in your environment when testing the
+hook.
+
+\subsection{Telling Mercurial to use an in-process hook}
+
+The \hgrc\ syntax for defining an in-process hook is slightly
+different than for an executable hook.  The value of the hook must
+start with the text ``\texttt{python:}'', and continue with the
+fully-qualified name of a callable object to use as the hook's value.
+
+The module in which a hook lives is automatically imported when a hook
+is run.  So long as you have the module name and \envar{PYTHONPATH}
+right, it should ``just work''.
+
+The following \hgrc\ example snippet illustrates the syntax and
+meaning of the notions we just described.
+\begin{codesample2}
+  [hooks]
+  commit.example = python:mymodule.submodule.myhook
+\end{codesample2}
+When Mercurial runs the \texttt{commit.example} hook, it imports
+\texttt{mymodule.submodule}, looks for the callable object named
+\texttt{myhook}, and calls it.
+
+\subsection{Writing an in-process hook}
+
+The simplest in-process hook does nothing, but illustrates the basic
+shape of the hook API:
+\begin{codesample2}
+  def myhook(ui, repo, **kwargs):
+      pass
+\end{codesample2}
+The first argument to a Python hook is always a
+\pymodclass{mercurial.ui}{ui} object.  The second is a repository object;
+at the moment, it is always an instance of
+\pymodclass{mercurial.localrepo}{localrepository}.  Following these two
+arguments are other keyword arguments.  Which ones are passed in
+depends on the hook being called, but a hook can ignore arguments it
+doesn't care about by dropping them into a keyword argument dict, as
+with \texttt{**kwargs} above.
+
+\section{Some hook examples}
+
+\subsection{Writing meaningful commit messages}
+
+It's hard to imagine a useful commit message being very short.  The
+simple \hook{pretxncommit} hook of figure~\ref{ex:hook:msglen.go}
+will prevent you from committing a changeset with a message that is
+less than ten bytes long.
+
+\begin{figure}[ht]
+  \interaction{hook.msglen.go}
+  \caption{A hook that forbids overly short commit messages}
+  \label{ex:hook:msglen.go}
+\end{figure}
+
+\subsection{Checking for trailing whitespace}
+
+An interesting use of a commit-related hook is to help you to write
+cleaner code.  A simple example of ``cleaner code'' is the dictum that
+a change should not add any new lines of text that contain ``trailing
+whitespace''.  Trailing whitespace is a series of space and tab
+characters at the end of a line of text.  In most cases, trailing
+whitespace is unnecessary, invisible noise, but it is occasionally
+problematic, and people often prefer to get rid of it.
+
+You can use either the \hook{precommit} or \hook{pretxncommit} hook to
+tell whether you have a trailing whitespace problem.  If you use the
+\hook{precommit} hook, the hook will not know which files you are
+committing, so it will have to check every modified file in the
+repository for trailing white space.  If you want to commit a change
+to just the file \filename{foo}, but the file \filename{bar} contains
+trailing whitespace, doing a check in the \hook{precommit} hook will
+prevent you from committing \filename{foo} due to the problem with
+\filename{bar}.  This doesn't seem right.
+
+Should you choose the \hook{pretxncommit} hook, the check won't occur
+until just before the transaction for the commit completes.  This will
+allow you to check for problems only the exact files that are being
+committed.  However, if you entered the commit message interactively
+and the hook fails, the transaction will roll back; you'll have to
+re-enter the commit message after you fix the trailing whitespace and
+run \hgcmd{commit} again.
+
+\begin{figure}[ht]
+  \interaction{hook.ws.simple}
+  \caption{A simple hook that checks for trailing whitespace}
+  \label{ex:hook:ws.simple}
+\end{figure}
+
+Figure~\ref{ex:hook:ws.simple} introduces a simple \hook{pretxncommit}
+hook that checks for trailing whitespace.  This hook is short, but not
+very helpful.  It exits with an error status if a change adds a line
+with trailing whitespace to any file, but does not print any
+information that might help us to identify the offending file or
+line.  It also has the nice property of not paying attention to
+unmodified lines; only lines that introduce new trailing whitespace
+cause problems.
+
+\begin{figure}[ht]
+  \interaction{hook.ws.better}
+  \caption{A better trailing whitespace hook}
+  \label{ex:hook:ws.better}
+\end{figure}
+
+The example of figure~\ref{ex:hook:ws.better} is much more complex,
+but also more useful.  It parses a unified diff to see if any lines
+add trailing whitespace, and prints the name of the file and the line
+number of each such occurrence.  Even better, if the change adds
+trailing whitespace, this hook saves the commit comment and prints the
+name of the save file before exiting and telling Mercurial to roll the
+transaction back, so you can use
+\hgcmdargs{commit}{\hgopt{commit}{-l}~\emph{filename}} to reuse the
+saved commit message once you've corrected the problem.
+
+As a final aside, note in figure~\ref{ex:hook:ws.better} the use of
+\command{perl}'s in-place editing feature to get rid of trailing
+whitespace from a file.  This is concise and useful enough that I will
+reproduce it here.
+\begin{codesample2}
+  perl -pi -e 's,\textbackslash{}s+\$,,' filename
+\end{codesample2}
+
+\section{Bundled hooks}
+
+Mercurial ships with several bundled hooks.  You can find them in the
+\dirname{hgext} directory of a Mercurial source tree.  If you are
+using a Mercurial binary package, the hooks will be located in the
+\dirname{hgext} directory of wherever your package installer put
+Mercurial.
+
+\subsection{\hgext{acl}---access control for parts of a repository}
+
+The \hgext{acl} extension lets you control which remote users are
+allowed to push changesets to a networked server.  You can protect any
+portion of a repository (including the entire repo), so that a
+specific remote user can push changes that do not affect the protected
+portion.
+
+This extension implements access control based on the identity of the
+user performing a push, \emph{not} on who committed the changesets
+they're pushing.  It makes sense to use this hook only if you have a
+locked-down server environment that authenticates remote users, and
+you want to be sure that only specific users are allowed to push
+changes to that server.
+
+\subsubsection{Configuring the \hook{acl} hook}
+
+In order to manage incoming changesets, the \hgext{acl} hook must be
+used as a \hook{pretxnchangegroup} hook.  This lets it see which files
+are modified by each incoming changeset, and roll back a group of
+changesets if they modify ``forbidden'' files.  Example:
+\begin{codesample2}
+  [hooks]
+  pretxnchangegroup.acl = python:hgext.acl.hook
+\end{codesample2}
+
+The \hgext{acl} extension is configured using three sections.  
+
+The \rcsection{acl} section has only one entry, \rcitem{acl}{sources},
+which lists the sources of incoming changesets that the hook should
+pay attention to.  You don't normally need to configure this section.
+\begin{itemize}
+\item[\rcitem{acl}{serve}] Control incoming changesets that are arriving
+  from a remote repository over http or ssh.  This is the default
+  value of \rcitem{acl}{sources}, and usually the only setting you'll
+  need for this configuration item.
+\item[\rcitem{acl}{pull}] Control incoming changesets that are
+  arriving via a pull from a local repository.
+\item[\rcitem{acl}{push}] Control incoming changesets that are
+  arriving via a push from a local repository.
+\item[\rcitem{acl}{bundle}] Control incoming changesets that are
+  arriving from another repository via a bundle.
+\end{itemize}
+
+The \rcsection{acl.allow} section controls the users that are allowed to
+add changesets to the repository.  If this section is not present, all
+users that are not explicitly denied are allowed.  If this section is
+present, all users that are not explicitly allowed are denied (so an
+empty section means that all users are denied).
+
+The \rcsection{acl.deny} section determines which users are denied
+from adding changesets to the repository.  If this section is not
+present or is empty, no users are denied.
+
+The syntaxes for the \rcsection{acl.allow} and \rcsection{acl.deny}
+sections are identical.  On the left of each entry is a glob pattern
+that matches files or directories, relative to the root of the
+repository; on the right, a user name.
+
+In the following example, the user \texttt{docwriter} can only push
+changes to the \dirname{docs} subtree of the repository, while
+\texttt{intern} can push changes to any file or directory except
+\dirname{source/sensitive}.
+\begin{codesample2}
+  [acl.allow]
+  docs/** = docwriter
+
+  [acl.deny]
+  source/sensitive/** = intern
+\end{codesample2}
+
+\subsubsection{Testing and troubleshooting}
+
+If you want to test the \hgext{acl} hook, run it with Mercurial's
+debugging output enabled.  Since you'll probably be running it on a
+server where it's not convenient (or sometimes possible) to pass in
+the \hggopt{--debug} option, don't forget that you can enable
+debugging output in your \hgrc:
+\begin{codesample2}
+  [ui]
+  debug = true
+\end{codesample2}
+With this enabled, the \hgext{acl} hook will print enough information
+to let you figure out why it is allowing or forbidding pushes from
+specific users.
+
+\subsection{\hgext{bugzilla}---integration with Bugzilla}
+
+The \hgext{bugzilla} extension adds a comment to a Bugzilla bug
+whenever it finds a reference to that bug ID in a commit comment.  You
+can install this hook on a shared server, so that any time a remote
+user pushes changes to this server, the hook gets run.  
+
+It adds a comment to the bug that looks like this (you can configure
+the contents of the comment---see below):
+\begin{codesample2}
+  Changeset aad8b264143a, made by Joe User <joe.user@domain.com> in
+  the frobnitz repository, refers to this bug.
+
+  For complete details, see
+  http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a
+
+  Changeset description:
+        Fix bug 10483 by guarding against some NULL pointers
+\end{codesample2}
+The value of this hook is that it automates the process of updating a
+bug any time a changeset refers to it.  If you configure the hook
+properly, it makes it easy for people to browse straight from a
+Bugzilla bug to a changeset that refers to that bug.
+
+You can use the code in this hook as a starting point for some more
+exotic Bugzilla integration recipes.  Here are a few possibilities:
+\begin{itemize}
+\item Require that every changeset pushed to the server have a valid
+  bug~ID in its commit comment.  In this case, you'd want to configure
+  the hook as a \hook{pretxncommit} hook.  This would allow the hook
+  to reject changes that didn't contain bug IDs.
+\item Allow incoming changesets to automatically modify the
+  \emph{state} of a bug, as well as simply adding a comment.  For
+  example, the hook could recognise the string ``fixed bug 31337'' as
+  indicating that it should update the state of bug 31337 to
+  ``requires testing''.
+\end{itemize}
+
+\subsubsection{Configuring the \hook{bugzilla} hook}
+\label{sec:hook:bugzilla:config}
+
+You should configure this hook in your server's \hgrc\ as an
+\hook{incoming} hook, for example as follows:
+\begin{codesample2}
+  [hooks]
+  incoming.bugzilla = python:hgext.bugzilla.hook
+\end{codesample2}
+
+Because of the specialised nature of this hook, and because Bugzilla
+was not written with this kind of integration in mind, configuring
+this hook is a somewhat involved process.
+
+Before you begin, you must install the MySQL bindings for Python on
+the host(s) where you'll be running the hook.  If this is not
+available as a binary package for your system, you can download it
+from~\cite{web:mysql-python}.
+
+Configuration information for this hook lives in the
+\rcsection{bugzilla} section of your \hgrc.
+\begin{itemize}
+\item[\rcitem{bugzilla}{version}] The version of Bugzilla installed on
+  the server.  The database schema that Bugzilla uses changes
+  occasionally, so this hook has to know exactly which schema to use.
+  At the moment, the only version supported is \texttt{2.16}.
+\item[\rcitem{bugzilla}{host}] The hostname of the MySQL server that
+  stores your Bugzilla data.  The database must be configured to allow
+  connections from whatever host you are running the \hook{bugzilla}
+  hook on.
+\item[\rcitem{bugzilla}{user}] The username with which to connect to
+  the MySQL server.  The database must be configured to allow this
+  user to connect from whatever host you are running the
+  \hook{bugzilla} hook on.  This user must be able to access and
+  modify Bugzilla tables.  The default value of this item is
+  \texttt{bugs}, which is the standard name of the Bugzilla user in a
+  MySQL database.
+\item[\rcitem{bugzilla}{password}] The MySQL password for the user you
+  configured above.  This is stored as plain text, so you should make
+  sure that unauthorised users cannot read the \hgrc\ file where you
+  store this information.
+\item[\rcitem{bugzilla}{db}] The name of the Bugzilla database on the
+  MySQL server.  The default value of this item is \texttt{bugs},
+  which is the standard name of the MySQL database where Bugzilla
+  stores its data.
+\item[\rcitem{bugzilla}{notify}] If you want Bugzilla to send out a
+  notification email to subscribers after this hook has added a
+  comment to a bug, you will need this hook to run a command whenever
+  it updates the database.  The command to run depends on where you
+  have installed Bugzilla, but it will typically look something like
+  this, if you have Bugzilla installed in
+  \dirname{/var/www/html/bugzilla}:
+  \begin{codesample4}
+    cd /var/www/html/bugzilla && ./processmail %s nobody@nowhere.com
+  \end{codesample4}
+  The Bugzilla \texttt{processmail} program expects to be given a
+  bug~ID (the hook replaces ``\texttt{\%s}'' with the bug~ID) and an
+  email address.  It also expects to be able to write to some files in
+  the directory that it runs in.  If Bugzilla and this hook are not
+  installed on the same machine, you will need to find a way to run
+  \texttt{processmail} on the server where Bugzilla is installed.
+\end{itemize}
+
+\subsubsection{Mapping committer names to Bugzilla user names}
+
+By default, the \hgext{bugzilla} hook tries to use the email address
+of a changeset's committer as the Bugzilla user name with which to
+update a bug.  If this does not suit your needs, you can map committer
+email addresses to Bugzilla user names using a \rcsection{usermap}
+section.
+
+Each item in the \rcsection{usermap} section contains an email address
+on the left, and a Bugzilla user name on the right.
+\begin{codesample2}
+  [usermap]
+  jane.user@example.com = jane
+\end{codesample2}
+You can either keep the \rcsection{usermap} data in a normal \hgrc, or
+tell the \hgext{bugzilla} hook to read the information from an
+external \filename{usermap} file.  In the latter case, you can store
+\filename{usermap} data by itself in (for example) a user-modifiable
+repository.  This makes it possible to let your users maintain their
+own \rcitem{bugzilla}{usermap} entries.  The main \hgrc\ file might
+look like this:
+\begin{codesample2}
+  # regular hgrc file refers to external usermap file
+  [bugzilla]
+  usermap = /home/hg/repos/userdata/bugzilla-usermap.conf
+\end{codesample2}
+While the \filename{usermap} file that it refers to might look like
+this:
+\begin{codesample2}
+  # bugzilla-usermap.conf - inside a hg repository
+  [usermap]
+  stephanie@example.com = steph
+\end{codesample2}
+
+\subsubsection{Configuring the text that gets added to a bug}
+
+You can configure the text that this hook adds as a comment; you
+specify it in the form of a Mercurial template.  Several \hgrc\
+entries (still in the \rcsection{bugzilla} section) control this
+behaviour.
+\begin{itemize}
+\item[\texttt{strip}] The number of leading path elements to strip
+  from a repository's path name to construct a partial path for a URL.
+  For example, if the repositories on your server live under
+  \dirname{/home/hg/repos}, and you have a repository whose path is
+  \dirname{/home/hg/repos/app/tests}, then setting \texttt{strip} to
+  \texttt{4} will give a partial path of \dirname{app/tests}.  The
+  hook will make this partial path available when expanding a
+  template, as \texttt{webroot}.
+\item[\texttt{template}] The text of the template to use.  In addition
+  to the usual changeset-related variables, this template can use
+  \texttt{hgweb} (the value of the \texttt{hgweb} configuration item
+  above) and \texttt{webroot} (the path constructed using
+  \texttt{strip} above).
+\end{itemize}
+
+In addition, you can add a \rcitem{web}{baseurl} item to the
+\rcsection{web} section of your \hgrc.  The \hgext{bugzilla} hook will
+make this available when expanding a template, as the base string to
+use when constructing a URL that will let users browse from a Bugzilla
+comment to view a changeset.  Example:
+\begin{codesample2}
+  [web]
+  baseurl = http://hg.domain.com/
+\end{codesample2}
+
+Here is an example set of \hgext{bugzilla} hook config information.
+\begin{codesample2}
+  [bugzilla]
+  host = bugzilla.example.com
+  password = mypassword
+  version = 2.16
+  # server-side repos live in /home/hg/repos, so strip 4 leading
+  # separators
+  strip = 4
+  hgweb = http://hg.example.com/
+  usermap = /home/hg/repos/notify/bugzilla.conf
+  template = Changeset \{node|short\}, made by \{author\} in the \{webroot\}
+    repo, refers to this bug.\\nFor complete details, see 
+    \{hgweb\}\{webroot\}?cmd=changeset;node=\{node|short\}\\nChangeset
+    description:\\n\\t\{desc|tabindent\}
+\end{codesample2}
+
+\subsubsection{Testing and troubleshooting}
+
+The most common problems with configuring the \hgext{bugzilla} hook
+relate to running Bugzilla's \filename{processmail} script and mapping
+committer names to user names.
+
+Recall from section~\ref{sec:hook:bugzilla:config} above that the user
+that runs the Mercurial process on the server is also the one that
+will run the \filename{processmail} script.  The
+\filename{processmail} script sometimes causes Bugzilla to write to
+files in its configuration directory, and Bugzilla's configuration
+files are usually owned by the user that your web server runs under.
+
+You can cause \filename{processmail} to be run with the suitable
+user's identity using the \command{sudo} command.  Here is an example
+entry for a \filename{sudoers} file.
+\begin{codesample2}
+  hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s
+\end{codesample2}
+This allows the \texttt{hg\_user} user to run a
+\filename{processmail-wrapper} program under the identity of
+\texttt{httpd\_user}.
+
+This indirection through a wrapper script is necessary, because
+\filename{processmail} expects to be run with its current directory
+set to wherever you installed Bugzilla; you can't specify that kind of
+constraint in a \filename{sudoers} file.  The contents of the wrapper
+script are simple:
+\begin{codesample2}
+  #!/bin/sh
+  cd `dirname $0` && ./processmail "$1" nobody@example.com
+\end{codesample2}
+It doesn't seem to matter what email address you pass to
+\filename{processmail}.
+
+If your \rcsection{usermap} is not set up correctly, users will see an
+error message from the \hgext{bugzilla} hook when they push changes
+to the server.  The error message will look like this:
+\begin{codesample2}
+  cannot find bugzilla user id for john.q.public@example.com
+\end{codesample2}
+What this means is that the committer's address,
+\texttt{john.q.public@example.com}, is not a valid Bugzilla user name,
+nor does it have an entry in your \rcsection{usermap} that maps it to
+a valid Bugzilla user name.
+
+\subsection{\hgext{notify}---send email notifications}
+
+Although Mercurial's built-in web server provides RSS feeds of changes
+in every repository, many people prefer to receive change
+notifications via email.  The \hgext{notify} hook lets you send out
+notifications to a set of email addresses whenever changesets arrive
+that those subscribers are interested in.
+
+As with the \hgext{bugzilla} hook, the \hgext{notify} hook is
+template-driven, so you can customise the contents of the notification
+messages that it sends.
+
+By default, the \hgext{notify} hook includes a diff of every changeset
+that it sends out; you can limit the size of the diff, or turn this
+feature off entirely.  It is useful for letting subscribers review
+changes immediately, rather than clicking to follow a URL.
+
+\subsubsection{Configuring the \hgext{notify} hook}
+
+You can set up the \hgext{notify} hook to send one email message per
+incoming changeset, or one per incoming group of changesets (all those
+that arrived in a single pull or push).
+\begin{codesample2}
+  [hooks]
+  # send one email per group of changes
+  changegroup.notify = python:hgext.notify.hook
+  # send one email per change
+  incoming.notify = python:hgext.notify.hook
+\end{codesample2}
+
+Configuration information for this hook lives in the
+\rcsection{notify} section of a \hgrc\ file.
+\begin{itemize}
+\item[\rcitem{notify}{test}] By default, this hook does not send out
+  email at all; instead, it prints the message that it \emph{would}
+  send.  Set this item to \texttt{false} to allow email to be sent.
+  The reason that sending of email is turned off by default is that it
+  takes several tries to configure this extension exactly as you would
+  like, and it would be bad form to spam subscribers with a number of
+  ``broken'' notifications while you debug your configuration.
+\item[\rcitem{notify}{config}] The path to a configuration file that
+  contains subscription information.  This is kept separate from the
+  main \hgrc\ so that you can maintain it in a repository of its own.
+  People can then clone that repository, update their subscriptions,
+  and push the changes back to your server.
+\item[\rcitem{notify}{strip}] The number of leading path separator
+  characters to strip from a repository's path, when deciding whether
+  a repository has subscribers.  For example, if the repositories on
+  your server live in \dirname{/home/hg/repos}, and \hgext{notify} is
+  considering a repository named \dirname{/home/hg/repos/shared/test},
+  setting \rcitem{notify}{strip} to \texttt{4} will cause
+  \hgext{notify} to trim the path it considers down to
+  \dirname{shared/test}, and it will match subscribers against that.
+\item[\rcitem{notify}{template}] The template text to use when sending
+  messages.  This specifies both the contents of the message header
+  and its body.
+\item[\rcitem{notify}{maxdiff}] The maximum number of lines of diff
+  data to append to the end of a message.  If a diff is longer than
+  this, it is truncated.  By default, this is set to 300.  Set this to
+  \texttt{0} to omit diffs from notification emails.
+\item[\rcitem{notify}{sources}] A list of sources of changesets to
+  consider.  This lets you limit \hgext{notify} to only sending out
+  email about changes that remote users pushed into this repository
+  via a server, for example.  See section~\ref{sec:hook:sources} for
+  the sources you can specify here.
+\end{itemize}
+
+If you set the \rcitem{web}{baseurl} item in the \rcsection{web}
+section, you can use it in a template; it will be available as
+\texttt{webroot}.
+
+Here is an example set of \hgext{notify} configuration information.
+\begin{codesample2}
+  [notify]
+  # really send email
+  test = false
+  # subscriber data lives in the notify repo
+  config = /home/hg/repos/notify/notify.conf
+  # repos live in /home/hg/repos on server, so strip 4 "/" chars
+  strip = 4
+  template = X-Hg-Repo: \{webroot\}
+    Subject: \{webroot\}: \{desc|firstline|strip\}
+    From: \{author\}
+
+    changeset \{node|short\} in \{root\}
+    details: \{baseurl\}\{webroot\}?cmd=changeset;node=\{node|short\}
+    description:
+      \{desc|tabindent|strip\}
+
+  [web]
+  baseurl = http://hg.example.com/
+\end{codesample2}
+
+This will produce a message that looks like the following:
+\begin{codesample2}
+  X-Hg-Repo: tests/slave
+  Subject: tests/slave: Handle error case when slave has no buffers
+  Date: Wed,  2 Aug 2006 15:25:46 -0700 (PDT)
+
+  changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave
+  details: http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5
+  description:
+          Handle error case when slave has no buffers
+  diffs (54 lines):
+
+  diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h
+  --- a/include/tests.h      Wed Aug 02 15:19:52 2006 -0700
+  +++ b/include/tests.h      Wed Aug 02 15:25:26 2006 -0700
+  @@ -212,6 +212,15 @@ static __inline__ void test_headers(void *h)
+  [...snip...]
+\end{codesample2}
+
+\subsubsection{Testing and troubleshooting}
+
+Do not forget that by default, the \hgext{notify} extension \emph{will
+  not send any mail} until you explicitly configure it to do so, by
+setting \rcitem{notify}{test} to \texttt{false}.  Until you do that,
+it simply prints the message it \emph{would} send.
+
+\section{Information for writers of hooks}
+\label{sec:hook:ref}
+
+\subsection{In-process hook execution}
+
+An in-process hook is called with arguments of the following form:
+\begin{codesample2}
+  def myhook(ui, repo, **kwargs):
+      pass
+\end{codesample2}
+The \texttt{ui} parameter is a \pymodclass{mercurial.ui}{ui} object.
+The \texttt{repo} parameter is a
+\pymodclass{mercurial.localrepo}{localrepository} object.  The
+names and values of the \texttt{**kwargs} parameters depend on the
+hook being invoked, with the following common features:
+\begin{itemize}
+\item If a parameter is named \texttt{node} or
+  \texttt{parent\emph{N}}, it will contain a hexadecimal changeset ID.
+  The empty string is used to represent ``null changeset ID'' instead
+  of a string of zeroes.
+\item If a parameter is named \texttt{url}, it will contain the URL of
+  a remote repository, if that can be determined.
+\item Boolean-valued parameters are represented as Python
+  \texttt{bool} objects.
+\end{itemize}
+
+An in-process hook is called without a change to the process's working
+directory (unlike external hooks, which are run in the root of the
+repository).  It must not change the process's working directory, or
+it will cause any calls it makes into the Mercurial API to fail.
+
+If a hook returns a boolean ``false'' value, it is considered to have
+succeeded.  If it returns a boolean ``true'' value or raises an
+exception, it is considered to have failed.  A useful way to think of
+the calling convention is ``tell me if you fail''.
+
+Note that changeset IDs are passed into Python hooks as hexadecimal
+strings, not the binary hashes that Mercurial's APIs normally use.  To
+convert a hash from hex to binary, use the
+\pymodfunc{mercurial.node}{bin} function.
+
+\subsection{External hook execution}
+
+An external hook is passed to the shell of the user running Mercurial.
+Features of that shell, such as variable substitution and command
+redirection, are available.  The hook is run in the root directory of
+the repository (unlike in-process hooks, which are run in the same
+directory that Mercurial was run in).
+
+Hook parameters are passed to the hook as environment variables.  Each
+environment variable's name is converted in upper case and prefixed
+with the string ``\texttt{HG\_}''.  For example, if the name of a
+parameter is ``\texttt{node}'', the name of the environment variable
+representing that parameter will be ``\texttt{HG\_NODE}''.
+
+A boolean parameter is represented as the string ``\texttt{1}'' for
+``true'', ``\texttt{0}'' for ``false''.  If an environment variable is
+named \envar{HG\_NODE}, \envar{HG\_PARENT1} or \envar{HG\_PARENT2}, it
+contains a changeset ID represented as a hexadecimal string.  The
+empty string is used to represent ``null changeset ID'' instead of a
+string of zeroes.  If an environment variable is named
+\envar{HG\_URL}, it will contain the URL of a remote repository, if
+that can be determined.
+
+If a hook exits with a status of zero, it is considered to have
+succeeded.  If it exits with a non-zero status, it is considered to
+have failed.
+
+\subsection{Finding out where changesets come from}
+
+A hook that involves the transfer of changesets between a local
+repository and another may be able to find out information about the
+``far side''.  Mercurial knows \emph{how} changes are being
+transferred, and in many cases \emph{where} they are being transferred
+to or from.
+
+\subsubsection{Sources of changesets}
+\label{sec:hook:sources}
+
+Mercurial will tell a hook what means are, or were, used to transfer
+changesets between repositories.  This is provided by Mercurial in a
+Python parameter named \texttt{source}, or an environment variable named
+\envar{HG\_SOURCE}.
+
+\begin{itemize}
+\item[\texttt{serve}] Changesets are transferred to or from a remote
+  repository over http or ssh.
+\item[\texttt{pull}] Changesets are being transferred via a pull from
+  one repository into another.
+\item[\texttt{push}] Changesets are being transferred via a push from
+  one repository into another.
+\item[\texttt{bundle}] Changesets are being transferred to or from a
+  bundle.
+\end{itemize}
+
+\subsubsection{Where changes are going---remote repository URLs}
+\label{sec:hook:url}
+
+When possible, Mercurial will tell a hook the location of the ``far
+side'' of an activity that transfers changeset data between
+repositories.  This is provided by Mercurial in a Python parameter
+named \texttt{url}, or an environment variable named \envar{HG\_URL}.
+
+This information is not always known.  If a hook is invoked in a
+repository that is being served via http or ssh, Mercurial cannot tell
+where the remote repository is, but it may know where the client is
+connecting from.  In such cases, the URL will take one of the
+following forms:
+\begin{itemize}
+\item \texttt{remote:ssh:\emph{ip-address}}---remote ssh client, at
+  the given IP address.
+\item \texttt{remote:http:\emph{ip-address}}---remote http client, at
+  the given IP address.  If the client is using SSL, this will be of
+  the form \texttt{remote:https:\emph{ip-address}}.
+\item Empty---no information could be discovered about the remote
+  client.
+\end{itemize}
+
+\section{Hook reference}
+
+\subsection{\hook{changegroup}---after remote changesets added}
+\label{sec:hook:changegroup}
+
+This hook is run after a group of pre-existing changesets has been
+added to the repository, for example via a \hgcmd{pull} or
+\hgcmd{unbundle}.  This hook is run once per operation that added one
+or more changesets.  This is in contrast to the \hook{incoming} hook,
+which is run once per changeset, regardless of whether the changesets
+arrive in a group.
+
+Some possible uses for this hook include kicking off an automated
+build or test of the added changesets, updating a bug database, or
+notifying subscribers that a repository contains new changes.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{node}] A changeset ID.  The changeset ID of the first
+  changeset in the group that was added.  All changesets between this
+  and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by
+  a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}.
+\item[\texttt{source}] A string.  The source of these changes.  See
+  section~\ref{sec:hook:sources} for details.
+\item[\texttt{url}] A URL.  The location of the remote repository, if
+  known.  See section~\ref{sec:hook:url} for more information.
+\end{itemize}
+
+See also: \hook{incoming} (section~\ref{sec:hook:incoming}),
+\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}),
+\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup})
+
+\subsection{\hook{commit}---after a new changeset is created}
+\label{sec:hook:commit}
+
+This hook is run after a new changeset has been created.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{node}] A changeset ID.  The changeset ID of the newly
+  committed changeset.
+\item[\texttt{parent1}] A changeset ID.  The changeset ID of the first
+  parent of the newly committed changeset.
+\item[\texttt{parent2}] A changeset ID.  The changeset ID of the second
+  parent of the newly committed changeset.
+\end{itemize}
+
+See also: \hook{precommit} (section~\ref{sec:hook:precommit}),
+\hook{pretxncommit} (section~\ref{sec:hook:pretxncommit})
+
+\subsection{\hook{incoming}---after one remote changeset is added}
+\label{sec:hook:incoming}
+
+This hook is run after a pre-existing changeset has been added to the
+repository, for example via a \hgcmd{push}.  If a group of changesets
+was added in a single operation, this hook is called once for each
+added changeset.
+
+You can use this hook for the same purposes as the \hook{changegroup}
+hook (section~\ref{sec:hook:changegroup}); it's simply more convenient
+sometimes to run a hook once per group of changesets, while other
+times it's handier once per changeset.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{node}] A changeset ID.  The ID of the newly added
+  changeset.
+\item[\texttt{source}] A string.  The source of these changes.  See
+  section~\ref{sec:hook:sources} for details.
+\item[\texttt{url}] A URL.  The location of the remote repository, if
+  known.  See section~\ref{sec:hook:url} for more information.
+\end{itemize}
+
+See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}) \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup})
+
+\subsection{\hook{outgoing}---after changesets are propagated}
+\label{sec:hook:outgoing}
+
+This hook is run after a group of changesets has been propagated out
+of this repository, for example by a \hgcmd{push} or \hgcmd{bundle}
+command.
+
+One possible use for this hook is to notify administrators that
+changes have been pulled.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{node}] A changeset ID.  The changeset ID of the first
+  changeset of the group that was sent.
+\item[\texttt{source}] A string.  The source of the of the operation
+  (see section~\ref{sec:hook:sources}).  If a remote client pulled
+  changes from this repository, \texttt{source} will be
+  \texttt{serve}.  If the client that obtained changes from this
+  repository was local, \texttt{source} will be \texttt{bundle},
+  \texttt{pull}, or \texttt{push}, depending on the operation the
+  client performed.
+\item[\texttt{url}] A URL.  The location of the remote repository, if
+  known.  See section~\ref{sec:hook:url} for more information.
+\end{itemize}
+
+See also: \hook{preoutgoing} (section~\ref{sec:hook:preoutgoing})
+
+\subsection{\hook{prechangegroup}---before starting to add remote changesets}
+\label{sec:hook:prechangegroup}
+
+This controlling hook is run before Mercurial begins to add a group of
+changesets from another repository.
+
+This hook does not have any information about the changesets to be
+added, because it is run before transmission of those changesets is
+allowed to begin.  If this hook fails, the changesets will not be
+transmitted.
+
+One use for this hook is to prevent external changes from being added
+to a repository.  For example, you could use this to ``freeze'' a
+server-hosted branch temporarily or permanently so that users cannot
+push to it, while still allowing a local administrator to modify the
+repository.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{source}] A string.  The source of these changes.  See
+  section~\ref{sec:hook:sources} for details.
+\item[\texttt{url}] A URL.  The location of the remote repository, if
+  known.  See section~\ref{sec:hook:url} for more information.
+\end{itemize}
+
+See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}),
+\hook{incoming} (section~\ref{sec:hook:incoming}), ,
+\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup})
+
+\subsection{\hook{precommit}---before starting to commit a changeset}
+\label{sec:hook:precommit}
+
+This hook is run before Mercurial begins to commit a new changeset.
+It is run before Mercurial has any of the metadata for the commit,
+such as the files to be committed, the commit message, or the commit
+date.
+
+One use for this hook is to disable the ability to commit new
+changesets, while still allowing incoming changesets.  Another is to
+run a build or test, and only allow the commit to begin if the build
+or test succeeds.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{parent1}] A changeset ID.  The changeset ID of the first
+  parent of the working directory.
+\item[\texttt{parent2}] A changeset ID.  The changeset ID of the second
+  parent of the working directory.
+\end{itemize}
+If the commit proceeds, the parents of the working directory will
+become the parents of the new changeset.
+
+See also: \hook{commit} (section~\ref{sec:hook:commit}),
+\hook{pretxncommit} (section~\ref{sec:hook:pretxncommit})
+
+\subsection{\hook{preoutgoing}---before starting to propagate changesets}
+\label{sec:hook:preoutgoing}
+
+This hook is invoked before Mercurial knows the identities of the
+changesets to be transmitted.
+
+One use for this hook is to prevent changes from being transmitted to
+another repository.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{source}] A string.  The source of the operation that is
+  attempting to obtain changes from this repository (see
+  section~\ref{sec:hook:sources}).  See the documentation for the
+  \texttt{source} parameter to the \hook{outgoing} hook, in
+  section~\ref{sec:hook:outgoing}, for possible values of this
+  parameter.
+\item[\texttt{url}] A URL.  The location of the remote repository, if
+  known.  See section~\ref{sec:hook:url} for more information.
+\end{itemize}
+
+See also: \hook{outgoing} (section~\ref{sec:hook:outgoing})
+
+\subsection{\hook{pretag}---before tagging a changeset}
+\label{sec:hook:pretag}
+
+This controlling hook is run before a tag is created.  If the hook
+succeeds, creation of the tag proceeds.  If the hook fails, the tag is
+not created.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{local}] A boolean.  Whether the tag is local to this
+  repository instance (i.e.~stored in \sfilename{.hg/localtags}) or
+  managed by Mercurial (stored in \sfilename{.hgtags}).
+\item[\texttt{node}] A changeset ID.  The ID of the changeset to be tagged.
+\item[\texttt{tag}] A string.  The name of the tag to be created.
+\end{itemize}
+
+If the tag to be created is revision-controlled, the \hook{precommit}
+and \hook{pretxncommit} hooks (sections~\ref{sec:hook:commit}
+and~\ref{sec:hook:pretxncommit}) will also be run.
+
+See also: \hook{tag} (section~\ref{sec:hook:tag})
+
+\subsection{\hook{pretxnchangegroup}---before completing addition of
+  remote changesets}
+\label{sec:hook:pretxnchangegroup}
+
+This controlling hook is run before a transaction---that manages the
+addition of a group of new changesets from outside the
+repository---completes.  If the hook succeeds, the transaction
+completes, and all of the changesets become permanent within this
+repository.  If the hook fails, the transaction is rolled back, and
+the data for the changesets is erased.
+
+This hook can access the metadata associated with the almost-added
+changesets, but it should not do anything permanent with this data.
+It must also not modify the working directory.
+
+While this hook is running, if other Mercurial processes access this
+repository, they will be able to see the almost-added changesets as if
+they are permanent.  This may lead to race conditions if you do not
+take steps to avoid them.
+
+This hook can be used to automatically vet a group of changesets.  If
+the hook fails, all of the changesets are ``rejected'' when the
+transaction rolls back.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{node}] A changeset ID.  The changeset ID of the first
+  changeset in the group that was added.  All changesets between this
+  and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by
+  a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}.
+\item[\texttt{source}] A string.  The source of these changes.  See
+  section~\ref{sec:hook:sources} for details.
+\item[\texttt{url}] A URL.  The location of the remote repository, if
+  known.  See section~\ref{sec:hook:url} for more information.
+\end{itemize}
+
+See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}),
+\hook{incoming} (section~\ref{sec:hook:incoming}),
+\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup})
+
+\subsection{\hook{pretxncommit}---before completing commit of new changeset}
+\label{sec:hook:pretxncommit}
+
+This controlling hook is run before a transaction---that manages a new
+commit---completes.  If the hook succeeds, the transaction completes
+and the changeset becomes permanent within this repository.  If the
+hook fails, the transaction is rolled back, and the commit data is
+erased.
+
+This hook can access the metadata associated with the almost-new
+changeset, but it should not do anything permanent with this data.  It
+must also not modify the working directory.
+
+While this hook is running, if other Mercurial processes access this
+repository, they will be able to see the almost-new changeset as if it
+is permanent.  This may lead to race conditions if you do not take
+steps to avoid them.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{node}] A changeset ID.  The changeset ID of the newly
+  committed changeset.
+\item[\texttt{parent1}] A changeset ID.  The changeset ID of the first
+  parent of the newly committed changeset.
+\item[\texttt{parent2}] A changeset ID.  The changeset ID of the second
+  parent of the newly committed changeset.
+\end{itemize}
+
+See also: \hook{precommit} (section~\ref{sec:hook:precommit})
+
+\subsection{\hook{preupdate}---before updating or merging working directory}
+\label{sec:hook:preupdate}
+
+This controlling hook is run before an update or merge of the working
+directory begins.  It is run only if Mercurial's normal pre-update
+checks determine that the update or merge can proceed.  If the hook
+succeeds, the update or merge may proceed; if it fails, the update or
+merge does not start.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{parent1}] A changeset ID.  The ID of the parent that the
+  working directory is to be updated to.  If the working directory is
+  being merged, it will not change this parent.
+\item[\texttt{parent2}] A changeset ID.  Only set if the working
+  directory is being merged.  The ID of the revision that the working
+  directory is being merged with.
+\end{itemize}
+
+See also: \hook{update} (section~\ref{sec:hook:update})
+
+\subsection{\hook{tag}---after tagging a changeset}
+\label{sec:hook:tag}
+
+This hook is run after a tag has been created.
+
+Parameters to this hook:
+\begin{itemize}
+\item[\texttt{local}] A boolean.  Whether the new tag is local to this
+  repository instance (i.e.~stored in \sfilename{.hg/localtags}) or
+  managed by Mercurial (stored in \sfilename{.hgtags}).
+\item[\texttt{node}] A changeset ID.  The ID of the changeset that was
+  tagged.
+\item[\texttt{tag}] A string.  The name of the tag that was created.
+\end{itemize}
+
+If the created tag is revision-controlled, the \hook{commit} hook
+(section~\ref{sec:hook:commit}) is run before this hook.
+
+See also: \hook{pretag} (section~\ref{sec:hook:pretag})
+
+\subsection{\hook{update}---after updating or merging working directory}
+\label{sec:hook:update}
+
+This hook is run after an update or merge of the working directory
+completes.  Since a merge can fail (if the external \command{hgmerge}
+command fails to resolve conflicts in a file), this hook communicates
+whether the update or merge completed cleanly.
+
+\begin{itemize}
+\item[\texttt{error}] A boolean.  Indicates whether the update or
+  merge completed successfully.
+\item[\texttt{parent1}] A changeset ID.  The ID of the parent that the
+  working directory was updated to.  If the working directory was
+  merged, it will not have changed this parent.
+\item[\texttt{parent2}] A changeset ID.  Only set if the working
+  directory was merged.  The ID of the revision that the working
+  directory was merged with.
+\end{itemize}
+
+See also: \hook{preupdate} (section~\ref{sec:hook:preupdate})
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch11-template.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,475 @@
+\chapter{Customising the output of Mercurial}
+\label{chap:template}
+
+Mercurial provides a powerful mechanism to let you control how it
+displays information.  The mechanism is based on templates.  You can
+use templates to generate specific output for a single command, or to
+customise the entire appearance of the built-in web interface.
+
+\section{Using precanned output styles}
+\label{sec:style}
+
+Packaged with Mercurial are some output styles that you can use
+immediately.  A style is simply a precanned template that someone
+wrote and installed somewhere that Mercurial can find.
+
+Before we take a look at Mercurial's bundled styles, let's review its
+normal output.
+
+\interaction{template.simple.normal}
+
+This is somewhat informative, but it takes up a lot of space---five
+lines of output per changeset.  The \texttt{compact} style reduces
+this to three lines, presented in a sparse manner.
+
+\interaction{template.simple.compact}
+
+The \texttt{changelog} style hints at the expressive power of
+Mercurial's templating engine.  This style attempts to follow the GNU
+Project's changelog guidelines\cite{web:changelog}.
+
+\interaction{template.simple.changelog}
+
+You will not be shocked to learn that Mercurial's default output style
+is named \texttt{default}.
+
+\subsection{Setting a default style}
+
+You can modify the output style that Mercurial will use for every
+command by editing your \hgrc\ file, naming the style you would
+prefer to use.
+
+\begin{codesample2}
+  [ui]
+  style = compact
+\end{codesample2}
+
+If you write a style of your own, you can use it by either providing
+the path to your style file, or copying your style file into a
+location where Mercurial can find it (typically the \texttt{templates}
+subdirectory of your Mercurial install directory).
+
+\section{Commands that support styles and templates}
+
+All of Mercurial's ``\texttt{log}-like'' commands let you use styles
+and templates: \hgcmd{incoming}, \hgcmd{log}, \hgcmd{outgoing}, and
+\hgcmd{tip}.
+
+As I write this manual, these are so far the only commands that
+support styles and templates.  Since these are the most important
+commands that need customisable output, there has been little pressure
+from the Mercurial user community to add style and template support to
+other commands.
+
+\section{The basics of templating}
+
+At its simplest, a Mercurial template is a piece of text.  Some of the
+text never changes, while other parts are \emph{expanded}, or replaced
+with new text, when necessary.
+
+Before we continue, let's look again at a simple example of
+Mercurial's normal output.
+
+\interaction{template.simple.normal}
+
+Now, let's run the same command, but using a template to change its
+output.
+
+\interaction{template.simple.simplest}
+
+The example above illustrates the simplest possible template; it's
+just a piece of static text, printed once for each changeset.  The
+\hgopt{log}{--template} option to the \hgcmd{log} command tells
+Mercurial to use the given text as the template when printing each
+changeset.
+
+Notice that the template string above ends with the text
+``\Verb+\n+''.  This is an \emph{escape sequence}, telling Mercurial
+to print a newline at the end of each template item.  If you omit this
+newline, Mercurial will run each piece of output together.  See
+section~\ref{sec:template:escape} for more details of escape sequences.
+
+A template that prints a fixed string of text all the time isn't very
+useful; let's try something a bit more complex.
+
+\interaction{template.simple.simplesub}
+
+As you can see, the string ``\Verb+{desc}+'' in the template has been
+replaced in the output with the description of each changeset.  Every
+time Mercurial finds text enclosed in curly braces (``\texttt{\{}''
+and ``\texttt{\}}''), it will try to replace the braces and text with
+the expansion of whatever is inside.  To print a literal curly brace,
+you must escape it, as described in section~\ref{sec:template:escape}.
+
+\section{Common template keywords}
+\label{sec:template:keyword}
+
+You can start writing simple templates immediately using the keywords
+below.
+
+\begin{itemize}
+\item[\tplkword{author}] String.  The unmodified author of the changeset.
+\item[\tplkword{branches}] String.  The name of the branch on which
+  the changeset was committed.  Will be empty if the branch name was
+  \texttt{default}.
+\item[\tplkword{date}] Date information.  The date when the changeset
+  was committed.  This is \emph{not} human-readable; you must pass it
+  through a filter that will render it appropriately.  See
+  section~\ref{sec:template:filter} for more information on filters.
+  The date is expressed as a pair of numbers.  The first number is a
+  Unix UTC timestamp (seconds since January 1, 1970); the second is
+  the offset of the committer's timezone from UTC, in seconds.
+\item[\tplkword{desc}] String.  The text of the changeset description.
+\item[\tplkword{files}] List of strings.  All files modified, added, or
+  removed by this changeset.
+\item[\tplkword{file\_adds}] List of strings.  Files added by this
+  changeset.
+\item[\tplkword{file\_dels}] List of strings.  Files removed by this
+  changeset.
+\item[\tplkword{node}] String.  The changeset identification hash, as a
+  40-character hexadecimal string.
+\item[\tplkword{parents}] List of strings.  The parents of the
+  changeset.
+\item[\tplkword{rev}] Integer.  The repository-local changeset revision
+  number.
+\item[\tplkword{tags}] List of strings.  Any tags associated with the
+  changeset.
+\end{itemize}
+
+A few simple experiments will show us what to expect when we use these
+keywords; you can see the results in
+figure~\ref{fig:template:keywords}.
+
+\begin{figure}
+  \interaction{template.simple.keywords}
+  \caption{Template keywords in use}
+  \label{fig:template:keywords}
+\end{figure}
+
+As we noted above, the date keyword does not produce human-readable
+output, so we must treat it specially.  This involves using a
+\emph{filter}, about which more in section~\ref{sec:template:filter}.
+
+\interaction{template.simple.datekeyword}
+
+\section{Escape sequences}
+\label{sec:template:escape}
+
+Mercurial's templating engine recognises the most commonly used escape
+sequences in strings.  When it sees a backslash (``\Verb+\+'')
+character, it looks at the following character and substitutes the two
+characters with a single replacement, as described below.
+
+\begin{itemize}
+\item[\Verb+\textbackslash\textbackslash+] Backslash, ``\Verb+\+'',
+  ASCII~134.
+\item[\Verb+\textbackslash n+] Newline, ASCII~12.
+\item[\Verb+\textbackslash r+] Carriage return, ASCII~15.
+\item[\Verb+\textbackslash t+] Tab, ASCII~11.
+\item[\Verb+\textbackslash v+] Vertical tab, ASCII~13.
+\item[\Verb+\textbackslash \{+] Open curly brace, ``\Verb+{+'', ASCII~173.
+\item[\Verb+\textbackslash \}+] Close curly brace, ``\Verb+}+'', ASCII~175.
+\end{itemize}
+
+As indicated above, if you want the expansion of a template to contain
+a literal ``\Verb+\+'', ``\Verb+{+'', or ``\Verb+{+'' character, you
+must escape it.
+
+\section{Filtering keywords to change their results}
+\label{sec:template:filter}
+
+Some of the results of template expansion are not immediately easy to
+use.  Mercurial lets you specify an optional chain of \emph{filters}
+to modify the result of expanding a keyword.  You have already seen a
+common filter, \tplkwfilt{date}{isodate}, in action above, to make a
+date readable.
+
+Below is a list of the most commonly used filters that Mercurial
+supports.  While some filters can be applied to any text, others can
+only be used in specific circumstances.  The name of each filter is
+followed first by an indication of where it can be used, then a
+description of its effect.
+
+\begin{itemize}
+\item[\tplfilter{addbreaks}] Any text. Add an XHTML ``\Verb+<br/>+''
+  tag before the end of every line except the last.  For example,
+  ``\Verb+foo\nbar+'' becomes ``\Verb+foo<br/>\nbar+''.
+\item[\tplkwfilt{date}{age}] \tplkword{date} keyword.  Render the
+  age of the date, relative to the current time.  Yields a string like
+  ``\Verb+10 minutes+''.
+\item[\tplfilter{basename}] Any text, but most useful for the
+  \tplkword{files} keyword and its relatives.  Treat the text as a
+  path, and return the basename. For example, ``\Verb+foo/bar/baz+''
+  becomes ``\Verb+baz+''.
+\item[\tplkwfilt{date}{date}] \tplkword{date} keyword.  Render a date
+  in a similar format to the Unix \tplkword{date} command, but with
+  timezone included.  Yields a string like
+  ``\Verb+Mon Sep 04 15:13:13 2006 -0700+''.
+\item[\tplkwfilt{author}{domain}] Any text, but most useful for the
+  \tplkword{author} keyword.  Finds the first string that looks like
+  an email address, and extract just the domain component.  For
+  example, ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes
+  ``\Verb+serpentine.com+''.
+\item[\tplkwfilt{author}{email}] Any text, but most useful for the
+  \tplkword{author} keyword.  Extract the first string that looks like
+  an email address.  For example,
+  ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes
+  ``\Verb+bos@serpentine.com+''.
+\item[\tplfilter{escape}] Any text.  Replace the special XML/XHTML
+  characters ``\Verb+&+'', ``\Verb+<+'' and ``\Verb+>+'' with
+  XML entities.
+\item[\tplfilter{fill68}] Any text.  Wrap the text to fit in 68
+  columns.  This is useful before you pass text through the
+  \tplfilter{tabindent} filter, and still want it to fit in an
+  80-column fixed-font window.
+\item[\tplfilter{fill76}] Any text.  Wrap the text to fit in 76
+  columns.
+\item[\tplfilter{firstline}] Any text.  Yield the first line of text,
+  without any trailing newlines.
+\item[\tplkwfilt{date}{hgdate}] \tplkword{date} keyword.  Render the
+  date as a pair of readable numbers.  Yields a string like
+  ``\Verb+1157407993 25200+''.
+\item[\tplkwfilt{date}{isodate}] \tplkword{date} keyword.  Render the
+  date as a text string in ISO~8601 format.  Yields a string like
+  ``\Verb+2006-09-04 15:13:13 -0700+''.
+\item[\tplfilter{obfuscate}] Any text, but most useful for the
+  \tplkword{author} keyword.  Yield the input text rendered as a
+  sequence of XML entities.  This helps to defeat some particularly
+  stupid screen-scraping email harvesting spambots.
+\item[\tplkwfilt{author}{person}] Any text, but most useful for the
+  \tplkword{author} keyword.  Yield the text before an email address.
+  For example, ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+''
+  becomes ``\Verb+Bryan O'Sullivan+''.
+\item[\tplkwfilt{date}{rfc822date}] \tplkword{date} keyword.  Render a
+  date using the same format used in email headers.  Yields a string
+  like ``\Verb+Mon, 04 Sep 2006 15:13:13 -0700+''.
+\item[\tplkwfilt{node}{short}] Changeset hash.  Yield the short form
+  of a changeset hash, i.e.~a 12-character hexadecimal string.
+\item[\tplkwfilt{date}{shortdate}] \tplkword{date} keyword.  Render
+  the year, month, and day of the date.  Yields a string like
+  ``\Verb+2006-09-04+''.
+\item[\tplfilter{strip}] Any text.  Strip all leading and trailing
+  whitespace from the string.
+\item[\tplfilter{tabindent}] Any text.  Yield the text, with every line
+  except the first starting with a tab character.
+\item[\tplfilter{urlescape}] Any text.  Escape all characters that are
+  considered ``special'' by URL parsers.  For example, \Verb+foo bar+
+  becomes \Verb+foo%20bar+.
+\item[\tplkwfilt{author}{user}] Any text, but most useful for the
+  \tplkword{author} keyword.  Return the ``user'' portion of an email
+  address.  For example,
+  ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes
+  ``\Verb+bos+''.
+\end{itemize}
+
+\begin{figure}
+  \interaction{template.simple.manyfilters}
+  \caption{Template filters in action}
+  \label{fig:template:filters}
+\end{figure}
+
+\begin{note}
+  If you try to apply a filter to a piece of data that it cannot
+  process, Mercurial will fail and print a Python exception.  For
+  example, trying to run the output of the \tplkword{desc} keyword
+  into the \tplkwfilt{date}{isodate} filter is not a good idea.
+\end{note}
+
+\subsection{Combining filters}
+
+It is easy to combine filters to yield output in the form you would
+like.  The following chain of filters tidies up a description, then
+makes sure that it fits cleanly into 68 columns, then indents it by a
+further 8~characters (at least on Unix-like systems, where a tab is
+conventionally 8~characters wide).
+
+\interaction{template.simple.combine}
+
+Note the use of ``\Verb+\t+'' (a tab character) in the template to
+force the first line to be indented; this is necessary since
+\tplkword{tabindent} indents all lines \emph{except} the first.
+
+Keep in mind that the order of filters in a chain is significant.  The
+first filter is applied to the result of the keyword; the second to
+the result of the first filter; and so on.  For example, using
+\Verb+fill68|tabindent+ gives very different results from
+\Verb+tabindent|fill68+.
+
+
+\section{From templates to styles}
+
+A command line template provides a quick and simple way to format some
+output.  Templates can become verbose, though, and it's useful to be
+able to give a template a name.  A style file is a template with a
+name, stored in a file.
+
+More than that, using a style file unlocks the power of Mercurial's
+templating engine in ways that are not possible using the command line
+\hgopt{log}{--template} option.
+
+\subsection{The simplest of style files}
+
+Our simple style file contains just one line:
+
+\interaction{template.simple.rev}
+
+This tells Mercurial, ``if you're printing a changeset, use the text
+on the right as the template''.
+
+\subsection{Style file syntax}
+
+The syntax rules for a style file are simple.
+
+\begin{itemize}
+\item The file is processed one line at a time.
+
+\item Leading and trailing white space are ignored.
+
+\item Empty lines are skipped.
+
+\item If a line starts with either of the characters ``\texttt{\#}'' or
+  ``\texttt{;}'', the entire line is treated as a comment, and skipped
+  as if empty.
+
+\item A line starts with a keyword.  This must start with an
+  alphabetic character or underscore, and can subsequently contain any
+  alphanumeric character or underscore.  (In regexp notation, a
+  keyword must match \Verb+[A-Za-z_][A-Za-z0-9_]*+.)
+
+\item The next element must be an ``\texttt{=}'' character, which can
+  be preceded or followed by an arbitrary amount of white space.
+
+\item If the rest of the line starts and ends with matching quote
+  characters (either single or double quote), it is treated as a
+  template body.
+
+\item If the rest of the line \emph{does not} start with a quote
+  character, it is treated as the name of a file; the contents of this
+  file will be read and used as a template body.
+\end{itemize}
+
+\section{Style files by example}
+
+To illustrate how to write a style file, we will construct a few by
+example.  Rather than provide a complete style file and walk through
+it, we'll mirror the usual process of developing a style file by
+starting with something very simple, and walking through a series of
+successively more complete examples.
+
+\subsection{Identifying mistakes in style files}
+
+If Mercurial encounters a problem in a style file you are working on,
+it prints a terse error message that, once you figure out what it
+means, is actually quite useful.
+
+\interaction{template.svnstyle.syntax.input}
+
+Notice that \filename{broken.style} attempts to define a
+\texttt{changeset} keyword, but forgets to give any content for it.
+When instructed to use this style file, Mercurial promptly complains.
+
+\interaction{template.svnstyle.syntax.error}
+
+This error message looks intimidating, but it is not too hard to
+follow.
+
+\begin{itemize}
+\item The first component is simply Mercurial's way of saying ``I am
+  giving up''.
+  \begin{codesample4}
+    \textbf{abort:} broken.style:1: parse error
+  \end{codesample4}
+
+\item Next comes the name of the style file that contains the error.
+  \begin{codesample4}
+    abort: \textbf{broken.style}:1: parse error
+  \end{codesample4}
+
+\item Following the file name is the line number where the error was
+  encountered.
+  \begin{codesample4}
+    abort: broken.style:\textbf{1}: parse error
+  \end{codesample4}
+
+\item Finally, a description of what went wrong.
+  \begin{codesample4}
+    abort: broken.style:1: \textbf{parse error}
+  \end{codesample4}
+  The description of the problem is not always clear (as in this
+  case), but even when it is cryptic, it is almost always trivial to
+  visually inspect the offending line in the style file and see what
+  is wrong.
+\end{itemize}
+
+\subsection{Uniquely identifying a repository}
+
+If you would like to be able to identify a Mercurial repository
+``fairly uniquely'' using a short string as an identifier, you can
+use the first revision in the repository.
+\interaction{template.svnstyle.id} 
+This is not guaranteed to be unique, but it is nevertheless useful in
+many cases.
+\begin{itemize}
+\item It will not work in a completely empty repository, because such
+  a repository does not have a revision~zero.
+\item Neither will it work in the (extremely rare) case where a
+  repository is a merge of two or more formerly independent
+  repositories, and you still have those repositories around.
+\end{itemize}
+Here are some uses to which you could put this identifier:
+\begin{itemize}
+\item As a key into a table for a database that manages repositories
+  on a server.
+\item As half of a \{\emph{repository~ID}, \emph{revision~ID}\} tuple.
+  Save this information away when you run an automated build or other
+  activity, so that you can ``replay'' the build later if necessary.
+\end{itemize}
+
+\subsection{Mimicking Subversion's output}
+
+Let's try to emulate the default output format used by another
+revision control tool, Subversion.
+\interaction{template.svnstyle.short}
+
+Since Subversion's output style is fairly simple, it is easy to
+copy-and-paste a hunk of its output into a file, and replace the text
+produced above by Subversion with the template values we'd like to see
+expanded.
+\interaction{template.svnstyle.template}
+
+There are a few small ways in which this template deviates from the
+output produced by Subversion.
+\begin{itemize}
+\item Subversion prints a ``readable'' date (the ``\texttt{Wed, 27 Sep
+    2006}'' in the example output above) in parentheses.  Mercurial's
+  templating engine does not provide a way to display a date in this
+  format without also printing the time and time zone.
+\item We emulate Subversion's printing of ``separator'' lines full of
+  ``\texttt{-}'' characters by ending the template with such a line.
+  We use the templating engine's \tplkword{header} keyword to print a
+  separator line as the first line of output (see below), thus
+  achieving similar output to Subversion.
+\item Subversion's output includes a count in the header of the number
+  of lines in the commit message.  We cannot replicate this in
+  Mercurial; the templating engine does not currently provide a filter
+  that counts the number of lines the template generates.
+\end{itemize}
+It took me no more than a minute or two of work to replace literal
+text from an example of Subversion's output with some keywords and
+filters to give the template above.  The style file simply refers to
+the template.
+\interaction{template.svnstyle.style}
+
+We could have included the text of the template file directly in the
+style file by enclosing it in quotes and replacing the newlines with
+``\verb!\n!'' sequences, but it would have made the style file too
+difficult to read.  Readability is a good guide when you're trying to
+decide whether some text belongs in a style file, or in a template
+file that the style file points to.  If the style file will look too
+big or cluttered if you insert a literal piece of text, drop it into a
+template instead.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch12-mq.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1043 @@
+\chapter{Managing change with Mercurial Queues}
+\label{chap:mq}
+
+\section{The patch management problem}
+\label{sec:mq:patch-mgmt}
+
+Here is a common scenario: you need to install a software package from
+source, but you find a bug that you must fix in the source before you
+can start using the package.  You make your changes, forget about the
+package for a while, and a few months later you need to upgrade to a
+newer version of the package.  If the newer version of the package
+still has the bug, you must extract your fix from the older source
+tree and apply it against the newer version.  This is a tedious task,
+and it's easy to make mistakes.
+
+This is a simple case of the ``patch management'' problem.  You have
+an ``upstream'' source tree that you can't change; you need to make
+some local changes on top of the upstream tree; and you'd like to be
+able to keep those changes separate, so that you can apply them to
+newer versions of the upstream source.
+
+The patch management problem arises in many situations.  Probably the
+most visible is that a user of an open source software project will
+contribute a bug fix or new feature to the project's maintainers in the
+form of a patch.
+
+Distributors of operating systems that include open source software
+often need to make changes to the packages they distribute so that
+they will build properly in their environments.
+
+When you have few changes to maintain, it is easy to manage a single
+patch using the standard \command{diff} and \command{patch} programs
+(see section~\ref{sec:mq:patch} for a discussion of these tools).
+Once the number of changes grows, it starts to make sense to maintain
+patches as discrete ``chunks of work,'' so that for example a single
+patch will contain only one bug fix (the patch might modify several
+files, but it's doing ``only one thing''), and you may have a number
+of such patches for different bugs you need fixed and local changes
+you require.  In this situation, if you submit a bug fix patch to the
+upstream maintainers of a package and they include your fix in a
+subsequent release, you can simply drop that single patch when you're
+updating to the newer release.
+
+Maintaining a single patch against an upstream tree is a little
+tedious and error-prone, but not difficult.  However, the complexity
+of the problem grows rapidly as the number of patches you have to
+maintain increases.  With more than a tiny number of patches in hand,
+understanding which ones you have applied and maintaining them moves
+from messy to overwhelming.
+
+Fortunately, Mercurial includes a powerful extension, Mercurial Queues
+(or simply ``MQ''), that massively simplifies the patch management
+problem.
+
+\section{The prehistory of Mercurial Queues}
+\label{sec:mq:history}
+
+During the late 1990s, several Linux kernel developers started to
+maintain ``patch series'' that modified the behaviour of the Linux
+kernel.  Some of these series were focused on stability, some on
+feature coverage, and others were more speculative.
+
+The sizes of these patch series grew rapidly.  In 2002, Andrew Morton
+published some shell scripts he had been using to automate the task of
+managing his patch queues.  Andrew was successfully using these
+scripts to manage hundreds (sometimes thousands) of patches on top of
+the Linux kernel.
+
+\subsection{A patchwork quilt}
+\label{sec:mq:quilt}
+
+In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the
+approach of Andrew's scripts and published a tool called ``patchwork
+quilt''~\cite{web:quilt}, or simply ``quilt''
+(see~\cite{gruenbacher:2005} for a paper describing it).  Because
+quilt substantially automated patch management, it rapidly gained a
+large following among open source software developers.
+
+Quilt manages a \emph{stack of patches} on top of a directory tree.
+To begin, you tell quilt to manage a directory tree, and tell it which
+files you want to manage; it stores away the names and contents of
+those files.  To fix a bug, you create a new patch (using a single
+command), edit the files you need to fix, then ``refresh'' the patch.
+
+The refresh step causes quilt to scan the directory tree; it updates
+the patch with all of the changes you have made.  You can create
+another patch on top of the first, which will track the changes
+required to modify the tree from ``tree with one patch applied'' to
+``tree with two patches applied''.
+
+You can \emph{change} which patches are applied to the tree.  If you
+``pop'' a patch, the changes made by that patch will vanish from the
+directory tree.  Quilt remembers which patches you have popped,
+though, so you can ``push'' a popped patch again, and the directory
+tree will be restored to contain the modifications in the patch.  Most
+importantly, you can run the ``refresh'' command at any time, and the
+topmost applied patch will be updated.  This means that you can, at
+any time, change both which patches are applied and what
+modifications those patches make.
+
+Quilt knows nothing about revision control tools, so it works equally
+well on top of an unpacked tarball or a Subversion working copy.
+
+\subsection{From patchwork quilt to Mercurial Queues}
+\label{sec:mq:quilt-mq}
+
+In mid-2005, Chris Mason took the features of quilt and wrote an
+extension that he called Mercurial Queues, which added quilt-like
+behaviour to Mercurial.
+
+The key difference between quilt and MQ is that quilt knows nothing
+about revision control systems, while MQ is \emph{integrated} into
+Mercurial.  Each patch that you push is represented as a Mercurial
+changeset.  Pop a patch, and the changeset goes away.
+
+Because quilt does not care about revision control tools, it is still
+a tremendously useful piece of software to know about for situations
+where you cannot use Mercurial and MQ.
+
+\section{The huge advantage of MQ}
+
+I cannot overstate the value that MQ offers through the unification of
+patches and revision control.
+
+A major reason that patches have persisted in the free software and
+open source world---in spite of the availability of increasingly
+capable revision control tools over the years---is the \emph{agility}
+they offer.  
+
+Traditional revision control tools make a permanent, irreversible
+record of everything that you do.  While this has great value, it's
+also somewhat stifling.  If you want to perform a wild-eyed
+experiment, you have to be careful in how you go about it, or you risk
+leaving unneeded---or worse, misleading or destabilising---traces of
+your missteps and errors in the permanent revision record.
+
+By contrast, MQ's marriage of distributed revision control with
+patches makes it much easier to isolate your work.  Your patches live
+on top of normal revision history, and you can make them disappear or
+reappear at will.  If you don't like a patch, you can drop it.  If a
+patch isn't quite as you want it to be, simply fix it---as many times
+as you need to, until you have refined it into the form you desire.
+
+As an example, the integration of patches with revision control makes
+understanding patches and debugging their effects---and their
+interplay with the code they're based on---\emph{enormously} easier.
+Since every applied patch has an associated changeset, you can use
+\hgcmdargs{log}{\emph{filename}} to see which changesets and patches
+affected a file.  You can use the \hgext{bisect} command to
+binary-search through all changesets and applied patches to see where
+a bug got introduced or fixed.  You can use the \hgcmd{annotate}
+command to see which changeset or patch modified a particular line of
+a source file.  And so on.
+
+\section{Understanding patches}
+\label{sec:mq:patch}
+
+Because MQ doesn't hide its patch-oriented nature, it is helpful to
+understand what patches are, and a little about the tools that work
+with them.
+
+The traditional Unix \command{diff} command compares two files, and
+prints a list of differences between them. The \command{patch} command
+understands these differences as \emph{modifications} to make to a
+file.  Take a look at figure~\ref{ex:mq:diff} for a simple example of
+these commands in action.
+
+\begin{figure}[ht]
+  \interaction{mq.dodiff.diff}
+  \caption{Simple uses of the \command{diff} and \command{patch} commands}
+  \label{ex:mq:diff}
+\end{figure}
+
+The type of file that \command{diff} generates (and \command{patch}
+takes as input) is called a ``patch'' or a ``diff''; there is no
+difference between a patch and a diff.  (We'll use the term ``patch'',
+since it's more commonly used.)
+
+A patch file can start with arbitrary text; the \command{patch}
+command ignores this text, but MQ uses it as the commit message when
+creating changesets.  To find the beginning of the patch content,
+\command{patch} searches for the first line that starts with the
+string ``\texttt{diff~-}''.
+
+MQ works with \emph{unified} diffs (\command{patch} can accept several
+other diff formats, but MQ doesn't).  A unified diff contains two
+kinds of header.  The \emph{file header} describes the file being
+modified; it contains the name of the file to modify.  When
+\command{patch} sees a new file header, it looks for a file with that
+name to start modifying.
+
+After the file header comes a series of \emph{hunks}.  Each hunk
+starts with a header; this identifies the range of line numbers within
+the file that the hunk should modify.  Following the header, a hunk
+starts and ends with a few (usually three) lines of text from the
+unmodified file; these are called the \emph{context} for the hunk.  If
+there's only a small amount of context between successive hunks,
+\command{diff} doesn't print a new hunk header; it just runs the hunks
+together, with a few lines of context between modifications.
+
+Each line of context begins with a space character.  Within the hunk,
+a line that begins with ``\texttt{-}'' means ``remove this line,''
+while a line that begins with ``\texttt{+}'' means ``insert this
+line.''  For example, a line that is modified is represented by one
+deletion and one insertion.
+
+We will return to some of the more subtle aspects of patches later (in
+section~\ref{sec:mq:adv-patch}), but you should have enough information
+now to use MQ.
+
+\section{Getting started with Mercurial Queues}
+\label{sec:mq:start}
+
+Because MQ is implemented as an extension, you must explicitly enable
+before you can use it.  (You don't need to download anything; MQ ships
+with the standard Mercurial distribution.)  To enable MQ, edit your
+\tildefile{.hgrc} file, and add the lines in figure~\ref{ex:mq:config}.
+
+\begin{figure}[ht]
+  \begin{codesample4}
+    [extensions]
+    hgext.mq =
+  \end{codesample4}
+  \label{ex:mq:config}
+  \caption{Contents to add to \tildefile{.hgrc} to enable the MQ extension}
+\end{figure}
+
+Once the extension is enabled, it will make a number of new commands
+available.  To verify that the extension is working, you can use
+\hgcmd{help} to see if the \hgxcmd{mq}{qinit} command is now available; see
+the example in figure~\ref{ex:mq:enabled}.
+
+\begin{figure}[ht]
+  \interaction{mq.qinit-help.help}
+  \caption{How to verify that MQ is enabled}
+  \label{ex:mq:enabled}
+\end{figure}
+
+You can use MQ with \emph{any} Mercurial repository, and its commands
+only operate within that repository.  To get started, simply prepare
+the repository using the \hgxcmd{mq}{qinit} command (see
+figure~\ref{ex:mq:qinit}).  This command creates an empty directory
+called \sdirname{.hg/patches}, where MQ will keep its metadata.  As
+with many Mercurial commands, the \hgxcmd{mq}{qinit} command prints nothing
+if it succeeds.
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qinit}
+  \caption{Preparing a repository for use with MQ}
+  \label{ex:mq:qinit}
+\end{figure}
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qnew}
+  \caption{Creating a new patch}
+  \label{ex:mq:qnew}
+\end{figure}
+
+\subsection{Creating a new patch}
+
+To begin work on a new patch, use the \hgxcmd{mq}{qnew} command.  This
+command takes one argument, the name of the patch to create.  MQ will
+use this as the name of an actual file in the \sdirname{.hg/patches}
+directory, as you can see in figure~\ref{ex:mq:qnew}.
+
+Also newly present in the \sdirname{.hg/patches} directory are two
+other files, \sfilename{series} and \sfilename{status}.  The
+\sfilename{series} file lists all of the patches that MQ knows about
+for this repository, with one patch per line.  Mercurial uses the
+\sfilename{status} file for internal book-keeping; it tracks all of the
+patches that MQ has \emph{applied} in this repository.
+
+\begin{note}
+  You may sometimes want to edit the \sfilename{series} file by hand;
+  for example, to change the sequence in which some patches are
+  applied.  However, manually editing the \sfilename{status} file is
+  almost always a bad idea, as it's easy to corrupt MQ's idea of what
+  is happening.
+\end{note}
+
+Once you have created your new patch, you can edit files in the
+working directory as you usually would.  All of the normal Mercurial
+commands, such as \hgcmd{diff} and \hgcmd{annotate}, work exactly as
+they did before.
+
+\subsection{Refreshing a patch}
+
+When you reach a point where you want to save your work, use the
+\hgxcmd{mq}{qrefresh} command (figure~\ref{ex:mq:qnew}) to update the patch
+you are working on.  This command folds the changes you have made in
+the working directory into your patch, and updates its corresponding
+changeset to contain those changes.
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qrefresh}
+  \caption{Refreshing a patch}
+  \label{ex:mq:qrefresh}
+\end{figure}
+
+You can run \hgxcmd{mq}{qrefresh} as often as you like, so it's a good way
+to ``checkpoint'' your work.  Refresh your patch at an opportune
+time; try an experiment; and if the experiment doesn't work out,
+\hgcmd{revert} your modifications back to the last time you refreshed.
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qrefresh2}
+  \caption{Refresh a patch many times to accumulate changes}
+  \label{ex:mq:qrefresh2}
+\end{figure}
+
+\subsection{Stacking and tracking patches}
+
+Once you have finished working on a patch, or need to work on another,
+you can use the \hgxcmd{mq}{qnew} command again to create a new patch.
+Mercurial will apply this patch on top of your existing patch.  See
+figure~\ref{ex:mq:qnew2} for an example.  Notice that the patch
+contains the changes in our prior patch as part of its context (you
+can see this more clearly in the output of \hgcmd{annotate}).
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qnew2}
+  \caption{Stacking a second patch on top of the first}
+  \label{ex:mq:qnew2}
+\end{figure}
+
+So far, with the exception of \hgxcmd{mq}{qnew} and \hgxcmd{mq}{qrefresh}, we've
+been careful to only use regular Mercurial commands.  However, MQ
+provides many commands that are easier to use when you are thinking
+about patches, as illustrated in figure~\ref{ex:mq:qseries}:
+
+\begin{itemize}
+\item The \hgxcmd{mq}{qseries} command lists every patch that MQ knows
+  about in this repository, from oldest to newest (most recently
+  \emph{created}).
+\item The \hgxcmd{mq}{qapplied} command lists every patch that MQ has
+  \emph{applied} in this repository, again from oldest to newest (most
+  recently applied).
+\end{itemize}
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qseries}
+  \caption{Understanding the patch stack with \hgxcmd{mq}{qseries} and
+    \hgxcmd{mq}{qapplied}}
+  \label{ex:mq:qseries}
+\end{figure}
+
+\subsection{Manipulating the patch stack}
+
+The previous discussion implied that there must be a difference
+between ``known'' and ``applied'' patches, and there is.  MQ can
+manage a patch without it being applied in the repository.
+
+An \emph{applied} patch has a corresponding changeset in the
+repository, and the effects of the patch and changeset are visible in
+the working directory.  You can undo the application of a patch using
+the \hgxcmd{mq}{qpop} command.  MQ still \emph{knows about}, or manages, a
+popped patch, but the patch no longer has a corresponding changeset in
+the repository, and the working directory does not contain the changes
+made by the patch.  Figure~\ref{fig:mq:stack} illustrates the
+difference between applied and tracked patches.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{mq-stack}
+  \caption{Applied and unapplied patches in the MQ patch stack}
+  \label{fig:mq:stack}
+\end{figure}
+
+You can reapply an unapplied, or popped, patch using the \hgxcmd{mq}{qpush}
+command.  This creates a new changeset to correspond to the patch, and
+the patch's changes once again become present in the working
+directory.  See figure~\ref{ex:mq:qpop} for examples of \hgxcmd{mq}{qpop}
+and \hgxcmd{mq}{qpush} in action.  Notice that once we have popped a patch
+or two patches, the output of \hgxcmd{mq}{qseries} remains the same, while
+that of \hgxcmd{mq}{qapplied} has changed.
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qpop}
+  \caption{Modifying the stack of applied patches}
+  \label{ex:mq:qpop}
+\end{figure}
+
+\subsection{Pushing and popping many patches}
+
+While \hgxcmd{mq}{qpush} and \hgxcmd{mq}{qpop} each operate on a single patch at
+a time by default, you can push and pop many patches in one go.  The
+\hgxopt{mq}{qpush}{-a} option to \hgxcmd{mq}{qpush} causes it to push all
+unapplied patches, while the \hgxopt{mq}{qpop}{-a} option to \hgxcmd{mq}{qpop}
+causes it to pop all applied patches.  (For some more ways to push and
+pop many patches, see section~\ref{sec:mq:perf} below.)
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qpush-a}
+  \caption{Pushing all unapplied patches}
+  \label{ex:mq:qpush-a}
+\end{figure}
+
+\subsection{Safety checks, and overriding them}
+
+Several MQ commands check the working directory before they do
+anything, and fail if they find any modifications.  They do this to
+ensure that you won't lose any changes that you have made, but not yet
+incorporated into a patch.  Figure~\ref{ex:mq:add} illustrates this;
+the \hgxcmd{mq}{qnew} command will not create a new patch if there are
+outstanding changes, caused in this case by the \hgcmd{add} of
+\filename{file3}.
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.add}
+  \caption{Forcibly creating a patch}
+  \label{ex:mq:add}
+\end{figure}
+
+Commands that check the working directory all take an ``I know what
+I'm doing'' option, which is always named \option{-f}.  The exact
+meaning of \option{-f} depends on the command.  For example,
+\hgcmdargs{qnew}{\hgxopt{mq}{qnew}{-f}} will incorporate any outstanding
+changes into the new patch it creates, but
+\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-f}} will revert modifications to any
+files affected by the patch that it is popping.  Be sure to read the
+documentation for a command's \option{-f} option before you use it!
+
+\subsection{Working on several patches at once}
+
+The \hgxcmd{mq}{qrefresh} command always refreshes the \emph{topmost}
+applied patch.  This means that you can suspend work on one patch (by
+refreshing it), pop or push to make a different patch the top, and
+work on \emph{that} patch for a while.
+
+Here's an example that illustrates how you can use this ability.
+Let's say you're developing a new feature as two patches.  The first
+is a change to the core of your software, and the second---layered on
+top of the first---changes the user interface to use the code you just
+added to the core.  If you notice a bug in the core while you're
+working on the UI patch, it's easy to fix the core.  Simply
+\hgxcmd{mq}{qrefresh} the UI patch to save your in-progress changes, and
+\hgxcmd{mq}{qpop} down to the core patch.  Fix the core bug,
+\hgxcmd{mq}{qrefresh} the core patch, and \hgxcmd{mq}{qpush} back to the UI
+patch to continue where you left off.
+
+\section{More about patches}
+\label{sec:mq:adv-patch}
+
+MQ uses the GNU \command{patch} command to apply patches, so it's
+helpful to know a few more detailed aspects of how \command{patch}
+works, and about patches themselves.
+
+\subsection{The strip count}
+
+If you look at the file headers in a patch, you will notice that the
+pathnames usually have an extra component on the front that isn't
+present in the actual path name.  This is a holdover from the way that
+people used to generate patches (people still do this, but it's
+somewhat rare with modern revision control tools).  
+
+Alice would unpack a tarball, edit her files, then decide that she
+wanted to create a patch.  So she'd rename her working directory,
+unpack the tarball again (hence the need for the rename), and use the
+\cmdopt{diff}{-r} and \cmdopt{diff}{-N} options to \command{diff} to
+recursively generate a patch between the unmodified directory and the
+modified one.  The result would be that the name of the unmodified
+directory would be at the front of the left-hand path in every file
+header, and the name of the modified directory would be at the front
+of the right-hand path.
+
+Since someone receiving a patch from the Alices of the net would be
+unlikely to have unmodified and modified directories with exactly the
+same names, the \command{patch} command has a \cmdopt{patch}{-p}
+option that indicates the number of leading path name components to
+strip when trying to apply a patch.  This number is called the
+\emph{strip count}.
+
+An option of ``\texttt{-p1}'' means ``use a strip count of one''.  If
+\command{patch} sees a file name \filename{foo/bar/baz} in a file
+header, it will strip \filename{foo} and try to patch a file named
+\filename{bar/baz}.  (Strictly speaking, the strip count refers to the
+number of \emph{path separators} (and the components that go with them
+) to strip.  A strip count of one will turn \filename{foo/bar} into
+\filename{bar}, but \filename{/foo/bar} (notice the extra leading
+slash) into \filename{foo/bar}.)
+
+The ``standard'' strip count for patches is one; almost all patches
+contain one leading path name component that needs to be stripped.
+Mercurial's \hgcmd{diff} command generates path names in this form,
+and the \hgcmd{import} command and MQ expect patches to have a strip
+count of one.
+
+If you receive a patch from someone that you want to add to your patch
+queue, and the patch needs a strip count other than one, you cannot
+just \hgxcmd{mq}{qimport} the patch, because \hgxcmd{mq}{qimport} does not yet
+have a \texttt{-p} option (see~\bug{311}).  Your best bet is to
+\hgxcmd{mq}{qnew} a patch of your own, then use \cmdargs{patch}{-p\emph{N}}
+to apply their patch, followed by \hgcmd{addremove} to pick up any
+files added or removed by the patch, followed by \hgxcmd{mq}{qrefresh}.
+This complexity may become unnecessary; see~\bug{311} for details.
+\subsection{Strategies for applying a patch}
+
+When \command{patch} applies a hunk, it tries a handful of
+successively less accurate strategies to try to make the hunk apply.
+This falling-back technique often makes it possible to take a patch
+that was generated against an old version of a file, and apply it
+against a newer version of that file.
+
+First, \command{patch} tries an exact match, where the line numbers,
+the context, and the text to be modified must apply exactly.  If it
+cannot make an exact match, it tries to find an exact match for the
+context, without honouring the line numbering information.  If this
+succeeds, it prints a line of output saying that the hunk was applied,
+but at some \emph{offset} from the original line number.
+
+If a context-only match fails, \command{patch} removes the first and
+last lines of the context, and tries a \emph{reduced} context-only
+match.  If the hunk with reduced context succeeds, it prints a message
+saying that it applied the hunk with a \emph{fuzz factor} (the number
+after the fuzz factor indicates how many lines of context
+\command{patch} had to trim before the patch applied).
+
+When neither of these techniques works, \command{patch} prints a
+message saying that the hunk in question was rejected.  It saves
+rejected hunks (also simply called ``rejects'') to a file with the
+same name, and an added \sfilename{.rej} extension.  It also saves an
+unmodified copy of the file with a \sfilename{.orig} extension; the
+copy of the file without any extensions will contain any changes made
+by hunks that \emph{did} apply cleanly.  If you have a patch that
+modifies \filename{foo} with six hunks, and one of them fails to
+apply, you will have: an unmodified \filename{foo.orig}, a
+\filename{foo.rej} containing one hunk, and \filename{foo}, containing
+the changes made by the five successful hunks.
+
+\subsection{Some quirks of patch representation}
+
+There are a few useful things to know about how \command{patch} works
+with files.
+\begin{itemize}
+\item This should already be obvious, but \command{patch} cannot
+  handle binary files.
+\item Neither does it care about the executable bit; it creates new
+  files as readable, but not executable.
+\item \command{patch} treats the removal of a file as a diff between
+  the file to be removed and the empty file.  So your idea of ``I
+  deleted this file'' looks like ``every line of this file was
+  deleted'' in a patch.
+\item It treats the addition of a file as a diff between the empty
+  file and the file to be added.  So in a patch, your idea of ``I
+  added this file'' looks like ``every line of this file was added''.
+\item It treats a renamed file as the removal of the old name, and the
+  addition of the new name.  This means that renamed files have a big
+  footprint in patches.  (Note also that Mercurial does not currently
+  try to infer when files have been renamed or copied in a patch.)
+\item \command{patch} cannot represent empty files, so you cannot use
+  a patch to represent the notion ``I added this empty file to the
+  tree''.
+\end{itemize}
+\subsection{Beware the fuzz}
+
+While applying a hunk at an offset, or with a fuzz factor, will often
+be completely successful, these inexact techniques naturally leave
+open the possibility of corrupting the patched file.  The most common
+cases typically involve applying a patch twice, or at an incorrect
+location in the file.  If \command{patch} or \hgxcmd{mq}{qpush} ever
+mentions an offset or fuzz factor, you should make sure that the
+modified files are correct afterwards.  
+
+It's often a good idea to refresh a patch that has applied with an
+offset or fuzz factor; refreshing the patch generates new context
+information that will make it apply cleanly.  I say ``often,'' not
+``always,'' because sometimes refreshing a patch will make it fail to
+apply against a different revision of the underlying files.  In some
+cases, such as when you're maintaining a patch that must sit on top of
+multiple versions of a source tree, it's acceptable to have a patch
+apply with some fuzz, provided you've verified the results of the
+patching process in such cases.
+
+\subsection{Handling rejection}
+
+If \hgxcmd{mq}{qpush} fails to apply a patch, it will print an error
+message and exit.  If it has left \sfilename{.rej} files behind, it is
+usually best to fix up the rejected hunks before you push more patches
+or do any further work.
+
+If your patch \emph{used to} apply cleanly, and no longer does because
+you've changed the underlying code that your patches are based on,
+Mercurial Queues can help; see section~\ref{sec:mq:merge} for details.
+
+Unfortunately, there aren't any great techniques for dealing with
+rejected hunks.  Most often, you'll need to view the \sfilename{.rej}
+file and edit the target file, applying the rejected hunks by hand.
+
+If you're feeling adventurous, Neil Brown, a Linux kernel hacker,
+wrote a tool called \command{wiggle}~\cite{web:wiggle}, which is more
+vigorous than \command{patch} in its attempts to make a patch apply.
+
+Another Linux kernel hacker, Chris Mason (the author of Mercurial
+Queues), wrote a similar tool called
+\command{mpatch}~\cite{web:mpatch}, which takes a simple approach to
+automating the application of hunks rejected by \command{patch}.  The
+\command{mpatch} command can help with four common reasons that a hunk
+may be rejected:
+
+\begin{itemize}
+\item The context in the middle of a hunk has changed.
+\item A hunk is missing some context at the beginning or end.
+\item A large hunk might apply better---either entirely or in
+  part---if it was broken up into smaller hunks.
+\item A hunk removes lines with slightly different content than those
+  currently present in the file.
+\end{itemize}
+
+If you use \command{wiggle} or \command{mpatch}, you should be doubly
+careful to check your results when you're done.  In fact,
+\command{mpatch} enforces this method of double-checking the tool's
+output, by automatically dropping you into a merge program when it has
+done its job, so that you can verify its work and finish off any
+remaining merges.
+
+\section{Getting the best performance out of MQ}
+\label{sec:mq:perf}
+
+MQ is very efficient at handling a large number of patches.  I ran
+some performance experiments in mid-2006 for a talk that I gave at the
+2006 EuroPython conference~\cite{web:europython}.  I used as my data
+set the Linux 2.6.17-mm1 patch series, which consists of 1,738
+patches.  I applied these on top of a Linux kernel repository
+containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux
+2.6.17.
+
+On my old, slow laptop, I was able to
+\hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} all 1,738 patches in 3.5 minutes,
+and \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} them all in 30 seconds.  (On a
+newer laptop, the time to push all patches dropped to two minutes.)  I
+could \hgxcmd{mq}{qrefresh} one of the biggest patches (which made 22,779
+lines of changes to 287 files) in 6.6 seconds.
+
+Clearly, MQ is well suited to working in large trees, but there are a
+few tricks you can use to get the best performance of it.
+
+First of all, try to ``batch'' operations together.  Every time you
+run \hgxcmd{mq}{qpush} or \hgxcmd{mq}{qpop}, these commands scan the working
+directory once to make sure you haven't made some changes and then
+forgotten to run \hgxcmd{mq}{qrefresh}.  On a small tree, the time that
+this scan takes is unnoticeable.  However, on a medium-sized tree
+(containing tens of thousands of files), it can take a second or more.
+
+The \hgxcmd{mq}{qpush} and \hgxcmd{mq}{qpop} commands allow you to push and pop
+multiple patches at a time.  You can identify the ``destination
+patch'' that you want to end up at.  When you \hgxcmd{mq}{qpush} with a
+destination specified, it will push patches until that patch is at the
+top of the applied stack.  When you \hgxcmd{mq}{qpop} to a destination, MQ
+will pop patches until the destination patch is at the top.
+
+You can identify a destination patch using either the name of the
+patch, or by number.  If you use numeric addressing, patches are
+counted from zero; this means that the first patch is zero, the second
+is one, and so on.
+
+\section{Updating your patches when the underlying code changes}
+\label{sec:mq:merge}
+
+It's common to have a stack of patches on top of an underlying
+repository that you don't modify directly.  If you're working on
+changes to third-party code, or on a feature that is taking longer to
+develop than the rate of change of the code beneath, you will often
+need to sync up with the underlying code, and fix up any hunks in your
+patches that no longer apply.  This is called \emph{rebasing} your
+patch series.
+
+The simplest way to do this is to \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}}
+your patches, then \hgcmd{pull} changes into the underlying
+repository, and finally \hgcmdargs{qpush}{\hgxopt{mq}{qpop}{-a}} your
+patches again.  MQ will stop pushing any time it runs across a patch
+that fails to apply during conflicts, allowing you to fix your
+conflicts, \hgxcmd{mq}{qrefresh} the affected patch, and continue pushing
+until you have fixed your entire stack.
+
+This approach is easy to use and works well if you don't expect
+changes to the underlying code to affect how well your patches apply.
+If your patch stack touches code that is modified frequently or
+invasively in the underlying repository, however, fixing up rejected
+hunks by hand quickly becomes tiresome.
+
+It's possible to partially automate the rebasing process.  If your
+patches apply cleanly against some revision of the underlying repo, MQ
+can use this information to help you to resolve conflicts between your
+patches and a different revision.
+
+The process is a little involved.
+\begin{enumerate}
+\item To begin, \hgcmdargs{qpush}{-a} all of your patches on top of
+  the revision where you know that they apply cleanly.
+\item Save a backup copy of your patch directory using
+  \hgcmdargs{qsave}{\hgxopt{mq}{qsave}{-e} \hgxopt{mq}{qsave}{-c}}.  This prints
+  the name of the directory that it has saved the patches in.  It will
+  save the patches to a directory called
+  \sdirname{.hg/patches.\emph{N}}, where \texttt{\emph{N}} is a small
+  integer.  It also commits a ``save changeset'' on top of your
+  applied patches; this is for internal book-keeping, and records the
+  states of the \sfilename{series} and \sfilename{status} files.
+\item Use \hgcmd{pull} to bring new changes into the underlying
+  repository.  (Don't run \hgcmdargs{pull}{-u}; see below for why.)
+\item Update to the new tip revision, using
+  \hgcmdargs{update}{\hgopt{update}{-C}} to override the patches you
+  have pushed.
+\item Merge all patches using \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}
+    \hgxopt{mq}{qpush}{-a}}.  The \hgxopt{mq}{qpush}{-m} option to \hgxcmd{mq}{qpush}
+  tells MQ to perform a three-way merge if the patch fails to apply.
+\end{enumerate}
+
+During the \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}}, each patch in the
+\sfilename{series} file is applied normally.  If a patch applies with
+fuzz or rejects, MQ looks at the queue you \hgxcmd{mq}{qsave}d, and
+performs a three-way merge with the corresponding changeset.  This
+merge uses Mercurial's normal merge machinery, so it may pop up a GUI
+merge tool to help you to resolve problems.
+
+When you finish resolving the effects of a patch, MQ refreshes your
+patch based on the result of the merge.
+
+At the end of this process, your repository will have one extra head
+from the old patch queue, and a copy of the old patch queue will be in
+\sdirname{.hg/patches.\emph{N}}. You can remove the extra head using
+\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a} \hgxopt{mq}{qpop}{-n} patches.\emph{N}}
+or \hgcmd{strip}.  You can delete \sdirname{.hg/patches.\emph{N}} once
+you are sure that you no longer need it as a backup.
+
+\section{Identifying patches}
+
+MQ commands that work with patches let you refer to a patch either by
+using its name or by a number.  By name is obvious enough; pass the
+name \filename{foo.patch} to \hgxcmd{mq}{qpush}, for example, and it will
+push patches until \filename{foo.patch} is applied.  
+
+As a shortcut, you can refer to a patch using both a name and a
+numeric offset; \texttt{foo.patch-2} means ``two patches before
+\texttt{foo.patch}'', while \texttt{bar.patch+4} means ``four patches
+after \texttt{bar.patch}''.
+
+Referring to a patch by index isn't much different.  The first patch
+printed in the output of \hgxcmd{mq}{qseries} is patch zero (yes, it's one
+of those start-at-zero counting systems); the second is patch one; and
+so on.
+
+MQ also makes it easy to work with patches when you are using normal
+Mercurial commands.  Every command that accepts a changeset ID will
+also accept the name of an applied patch.  MQ augments the tags
+normally in the repository with an eponymous one for each applied
+patch.  In addition, the special tags \index{tags!special tag
+  names!\texttt{qbase}}\texttt{qbase} and \index{tags!special tag
+  names!\texttt{qtip}}\texttt{qtip} identify the ``bottom-most'' and
+topmost applied patches, respectively.
+
+These additions to Mercurial's normal tagging capabilities make
+dealing with patches even more of a breeze.
+\begin{itemize}
+\item Want to patchbomb a mailing list with your latest series of
+  changes?
+  \begin{codesample4}
+    hg email qbase:qtip
+  \end{codesample4}
+  (Don't know what ``patchbombing'' is?  See
+  section~\ref{sec:hgext:patchbomb}.)
+\item Need to see all of the patches since \texttt{foo.patch} that
+  have touched files in a subdirectory of your tree?
+  \begin{codesample4}
+    hg log -r foo.patch:qtip \emph{subdir}
+  \end{codesample4}
+\end{itemize}
+
+Because MQ makes the names of patches available to the rest of
+Mercurial through its normal internal tag machinery, you don't need to
+type in the entire name of a patch when you want to identify it by
+name.
+
+\begin{figure}[ht]
+  \interaction{mq.id.output}
+  \caption{Using MQ's tag features to work with patches}
+  \label{ex:mq:id}
+\end{figure}
+
+Another nice consequence of representing patch names as tags is that
+when you run the \hgcmd{log} command, it will display a patch's name
+as a tag, simply as part of its normal output.  This makes it easy to
+visually distinguish applied patches from underlying ``normal''
+revisions.  Figure~\ref{ex:mq:id} shows a few normal Mercurial
+commands in use with applied patches.
+
+\section{Useful things to know about}
+
+There are a number of aspects of MQ usage that don't fit tidily into
+sections of their own, but that are good to know.  Here they are, in
+one place.
+
+\begin{itemize}
+\item Normally, when you \hgxcmd{mq}{qpop} a patch and \hgxcmd{mq}{qpush} it
+  again, the changeset that represents the patch after the pop/push
+  will have a \emph{different identity} than the changeset that
+  represented the hash beforehand.  See
+  section~\ref{sec:mqref:cmd:qpush} for information as to why this is.
+\item It's not a good idea to \hgcmd{merge} changes from another
+  branch with a patch changeset, at least if you want to maintain the
+  ``patchiness'' of that changeset and changesets below it on the
+  patch stack.  If you try to do this, it will appear to succeed, but
+  MQ will become confused.
+\end{itemize}
+
+\section{Managing patches in a repository}
+\label{sec:mq:repo}
+
+Because MQ's \sdirname{.hg/patches} directory resides outside a
+Mercurial repository's working directory, the ``underlying'' Mercurial
+repository knows nothing about the management or presence of patches.
+
+This presents the interesting possibility of managing the contents of
+the patch directory as a Mercurial repository in its own right.  This
+can be a useful way to work.  For example, you can work on a patch for
+a while, \hgxcmd{mq}{qrefresh} it, then \hgcmd{commit} the current state of
+the patch.  This lets you ``roll back'' to that version of the patch
+later on.
+
+You can then share different versions of the same patch stack among
+multiple underlying repositories.  I use this when I am developing a
+Linux kernel feature.  I have a pristine copy of my kernel sources for
+each of several CPU architectures, and a cloned repository under each
+that contains the patches I am working on.  When I want to test a
+change on a different architecture, I push my current patches to the
+patch repository associated with that kernel tree, pop and push all of
+my patches, and build and test that kernel.
+
+Managing patches in a repository makes it possible for multiple
+developers to work on the same patch series without colliding with
+each other, all on top of an underlying source base that they may or
+may not control.
+
+\subsection{MQ support for patch repositories}
+
+MQ helps you to work with the \sdirname{.hg/patches} directory as a
+repository; when you prepare a repository for working with patches
+using \hgxcmd{mq}{qinit}, you can pass the \hgxopt{mq}{qinit}{-c} option to
+create the \sdirname{.hg/patches} directory as a Mercurial repository.
+
+\begin{note}
+  If you forget to use the \hgxopt{mq}{qinit}{-c} option, you can simply go
+  into the \sdirname{.hg/patches} directory at any time and run
+  \hgcmd{init}.  Don't forget to add an entry for the
+  \sfilename{status} file to the \sfilename{.hgignore} file, though
+
+  (\hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} does this for you
+  automatically); you \emph{really} don't want to manage the
+  \sfilename{status} file.
+\end{note}
+
+As a convenience, if MQ notices that the \dirname{.hg/patches}
+directory is a repository, it will automatically \hgcmd{add} every
+patch that you create and import.
+
+MQ provides a shortcut command, \hgxcmd{mq}{qcommit}, that runs
+\hgcmd{commit} in the \sdirname{.hg/patches} directory.  This saves
+some bothersome typing.
+
+Finally, as a convenience to manage the patch directory, you can
+define the alias \command{mq} on Unix systems. For example, on Linux
+systems using the \command{bash} shell, you can include the following
+snippet in your \tildefile{.bashrc}.
+
+\begin{codesample2}
+  alias mq=`hg -R \$(hg root)/.hg/patches'
+\end{codesample2}
+
+You can then issue commands of the form \cmdargs{mq}{pull} from
+the main repository.
+
+\subsection{A few things to watch out for}
+
+MQ's support for working with a repository full of patches is limited
+in a few small respects.
+
+MQ cannot automatically detect changes that you make to the patch
+directory.  If you \hgcmd{pull}, manually edit, or \hgcmd{update}
+changes to patches or the \sfilename{series} file, you will have to
+\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} and then
+\hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} in the underlying repository to
+see those changes show up there.  If you forget to do this, you can
+confuse MQ's idea of which patches are applied.
+
+\section{Third party tools for working with patches}
+\label{sec:mq:tools}
+
+Once you've been working with patches for a while, you'll find
+yourself hungry for tools that will help you to understand and
+manipulate the patches you're dealing with.
+
+The \command{diffstat} command~\cite{web:diffstat} generates a
+histogram of the modifications made to each file in a patch.  It
+provides a good way to ``get a sense of'' a patch---which files it
+affects, and how much change it introduces to each file and as a
+whole.  (I find that it's a good idea to use \command{diffstat}'s
+\cmdopt{diffstat}{-p} option as a matter of course, as otherwise it
+will try to do clever things with prefixes of file names that
+inevitably confuse at least me.)
+
+\begin{figure}[ht]
+  \interaction{mq.tools.tools}
+  \caption{The \command{diffstat}, \command{filterdiff}, and \command{lsdiff} commands}
+  \label{ex:mq:tools}
+\end{figure}
+
+The \package{patchutils} package~\cite{web:patchutils} is invaluable.
+It provides a set of small utilities that follow the ``Unix
+philosophy;'' each does one useful thing with a patch.  The
+\package{patchutils} command I use most is \command{filterdiff}, which
+extracts subsets from a patch file.  For example, given a patch that
+modifies hundreds of files across dozens of directories, a single
+invocation of \command{filterdiff} can generate a smaller patch that
+only touches files whose names match a particular glob pattern.  See
+section~\ref{mq-collab:tips:interdiff} for another example.
+
+\section{Good ways to work with patches}
+
+Whether you are working on a patch series to submit to a free software
+or open source project, or a series that you intend to treat as a
+sequence of regular changesets when you're done, you can use some
+simple techniques to keep your work well organised.
+
+Give your patches descriptive names.  A good name for a patch might be
+\filename{rework-device-alloc.patch}, because it will immediately give
+you a hint what the purpose of the patch is.  Long names shouldn't be
+a problem; you won't be typing the names often, but you \emph{will} be
+running commands like \hgxcmd{mq}{qapplied} and \hgxcmd{mq}{qtop} over and over.
+Good naming becomes especially important when you have a number of
+patches to work with, or if you are juggling a number of different
+tasks and your patches only get a fraction of your attention.
+
+Be aware of what patch you're working on.  Use the \hgxcmd{mq}{qtop}
+command and skim over the text of your patches frequently---for
+example, using \hgcmdargs{tip}{\hgopt{tip}{-p}})---to be sure of where
+you stand.  I have several times worked on and \hgxcmd{mq}{qrefresh}ed a
+patch other than the one I intended, and it's often tricky to migrate
+changes into the right patch after making them in the wrong one.
+
+For this reason, it is very much worth investing a little time to
+learn how to use some of the third-party tools I described in
+section~\ref{sec:mq:tools}, particularly \command{diffstat} and
+\command{filterdiff}.  The former will give you a quick idea of what
+changes your patch is making, while the latter makes it easy to splice
+hunks selectively out of one patch and into another.
+
+\section{MQ cookbook}
+
+\subsection{Manage ``trivial'' patches}
+
+Because the overhead of dropping files into a new Mercurial repository
+is so low, it makes a lot of sense to manage patches this way even if
+you simply want to make a few changes to a source tarball that you
+downloaded.
+
+Begin by downloading and unpacking the source tarball,
+and turning it into a Mercurial repository.
+\interaction{mq.tarball.download}
+
+Continue by creating a patch stack and making your changes.
+\interaction{mq.tarball.qinit}
+
+Let's say a few weeks or months pass, and your package author releases
+a new version.  First, bring their changes into the repository.
+\interaction{mq.tarball.newsource}
+The pipeline starting with \hgcmd{locate} above deletes all files in
+the working directory, so that \hgcmd{commit}'s
+\hgopt{commit}{--addremove} option can actually tell which files have
+really been removed in the newer version of the source.
+
+Finally, you can apply your patches on top of the new tree.
+\interaction{mq.tarball.repush}
+
+\subsection{Combining entire patches}
+\label{sec:mq:combine}
+
+MQ provides a command, \hgxcmd{mq}{qfold} that lets you combine entire
+patches.  This ``folds'' the patches you name, in the order you name
+them, into the topmost applied patch, and concatenates their
+descriptions onto the end of its description.  The patches that you
+fold must be unapplied before you fold them.
+
+The order in which you fold patches matters.  If your topmost applied
+patch is \texttt{foo}, and you \hgxcmd{mq}{qfold} \texttt{bar} and
+\texttt{quux} into it, you will end up with a patch that has the same
+effect as if you applied first \texttt{foo}, then \texttt{bar},
+followed by \texttt{quux}.
+
+\subsection{Merging part of one patch into another}
+
+Merging \emph{part} of one patch into another is more difficult than
+combining entire patches.
+
+If you want to move changes to entire files, you can use
+\command{filterdiff}'s \cmdopt{filterdiff}{-i} and
+\cmdopt{filterdiff}{-x} options to choose the modifications to snip
+out of one patch, concatenating its output onto the end of the patch
+you want to merge into.  You usually won't need to modify the patch
+you've merged the changes from.  Instead, MQ will report some rejected
+hunks when you \hgxcmd{mq}{qpush} it (from the hunks you moved into the
+other patch), and you can simply \hgxcmd{mq}{qrefresh} the patch to drop
+the duplicate hunks.
+
+If you have a patch that has multiple hunks modifying a file, and you
+only want to move a few of those hunks, the job becomes more messy,
+but you can still partly automate it.  Use \cmdargs{lsdiff}{-nvv} to
+print some metadata about the patch.
+\interaction{mq.tools.lsdiff}
+
+This command prints three different kinds of number:
+\begin{itemize}
+\item (in the first column) a \emph{file number} to identify each file
+  modified in the patch;
+\item (on the next line, indented) the line number within a modified
+  file where a hunk starts; and
+\item (on the same line) a \emph{hunk number} to identify that hunk.
+\end{itemize}
+
+You'll have to use some visual inspection, and reading of the patch,
+to identify the file and hunk numbers you'll want, but you can then
+pass them to to \command{filterdiff}'s \cmdopt{filterdiff}{--files}
+and \cmdopt{filterdiff}{--hunks} options, to select exactly the file
+and hunk you want to extract.
+
+Once you have this hunk, you can concatenate it onto the end of your
+destination patch and continue with the remainder of
+section~\ref{sec:mq:combine}.
+
+\section{Differences between quilt and MQ}
+
+If you are already familiar with quilt, MQ provides a similar command
+set.  There are a few differences in the way that it works.
+
+You will already have noticed that most quilt commands have MQ
+counterparts that simply begin with a ``\texttt{q}''.  The exceptions
+are quilt's \texttt{add} and \texttt{remove} commands, the
+counterparts for which are the normal Mercurial \hgcmd{add} and
+\hgcmd{remove} commands.  There is no MQ equivalent of the quilt
+\texttt{edit} command.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch13-mq-collab.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,392 @@
+\chapter{Advanced uses of Mercurial Queues}
+\label{chap:mq-collab}
+
+While it's easy to pick up straightforward uses of Mercurial Queues,
+use of a little discipline and some of MQ's less frequently used
+capabilities makes it possible to work in complicated development
+environments.
+
+In this chapter, I will use as an example a technique I have used to
+manage the development of an Infiniband device driver for the Linux
+kernel.  The driver in question is large (at least as drivers go),
+with 25,000 lines of code spread across 35 source files.  It is
+maintained by a small team of developers.
+
+While much of the material in this chapter is specific to Linux, the
+same principles apply to any code base for which you're not the
+primary owner, and upon which you need to do a lot of development.
+
+\section{The problem of many targets}
+
+The Linux kernel changes rapidly, and has never been internally
+stable; developers frequently make drastic changes between releases.
+This means that a version of the driver that works well with a
+particular released version of the kernel will not even \emph{compile}
+correctly against, typically, any other version.
+
+To maintain a driver, we have to keep a number of distinct versions of
+Linux in mind.
+\begin{itemize}
+\item One target is the main Linux kernel development tree.
+  Maintenance of the code is in this case partly shared by other
+  developers in the kernel community, who make ``drive-by''
+  modifications to the driver as they develop and refine kernel
+  subsystems.
+\item We also maintain a number of ``backports'' to older versions of
+  the Linux kernel, to support the needs of customers who are running
+  older Linux distributions that do not incorporate our drivers.  (To
+  \emph{backport} a piece of code is to modify it to work in an older
+  version of its target environment than the version it was developed
+  for.)
+\item Finally, we make software releases on a schedule that is
+  necessarily not aligned with those used by Linux distributors and
+  kernel developers, so that we can deliver new features to customers
+  without forcing them to upgrade their entire kernels or
+  distributions.
+\end{itemize}
+
+\subsection{Tempting approaches that don't work well}
+
+There are two ``standard'' ways to maintain a piece of software that
+has to target many different environments.
+
+The first is to maintain a number of branches, each intended for a
+single target.  The trouble with this approach is that you must
+maintain iron discipline in the flow of changes between repositories.
+A new feature or bug fix must start life in a ``pristine'' repository,
+then percolate out to every backport repository.  Backport changes are
+more limited in the branches they should propagate to; a backport
+change that is applied to a branch where it doesn't belong will
+probably stop the driver from compiling.
+
+The second is to maintain a single source tree filled with conditional
+statements that turn chunks of code on or off depending on the
+intended target.  Because these ``ifdefs'' are not allowed in the
+Linux kernel tree, a manual or automatic process must be followed to
+strip them out and yield a clean tree.  A code base maintained in this
+fashion rapidly becomes a rat's nest of conditional blocks that are
+difficult to understand and maintain.
+
+Neither of these approaches is well suited to a situation where you
+don't ``own'' the canonical copy of a source tree.  In the case of a
+Linux driver that is distributed with the standard kernel, Linus's
+tree contains the copy of the code that will be treated by the world
+as canonical.  The upstream version of ``my'' driver can be modified
+by people I don't know, without me even finding out about it until
+after the changes show up in Linus's tree.  
+
+These approaches have the added weakness of making it difficult to
+generate well-formed patches to submit upstream.
+
+In principle, Mercurial Queues seems like a good candidate to manage a
+development scenario such as the above.  While this is indeed the
+case, MQ contains a few added features that make the job more
+pleasant.
+
+\section{Conditionally applying patches with guards}
+
+Perhaps the best way to maintain sanity with so many targets is to be
+able to choose specific patches to apply for a given situation.  MQ
+provides a feature called ``guards'' (which originates with quilt's
+\texttt{guards} command) that does just this.  To start off, let's
+create a simple repository for experimenting in.
+\interaction{mq.guards.init}
+This gives us a tiny repository that contains two patches that don't
+have any dependencies on each other, because they touch different files.
+
+The idea behind conditional application is that you can ``tag'' a
+patch with a \emph{guard}, which is simply a text string of your
+choosing, then tell MQ to select specific guards to use when applying
+patches.  MQ will then either apply, or skip over, a guarded patch,
+depending on the guards that you have selected.
+
+A patch can have an arbitrary number of guards;
+each one is \emph{positive} (``apply this patch if this guard is
+selected'') or \emph{negative} (``skip this patch if this guard is
+selected'').  A patch with no guards is always applied.
+
+\section{Controlling the guards on a patch}
+
+The \hgxcmd{mq}{qguard} command lets you determine which guards should
+apply to a patch, or display the guards that are already in effect.
+Without any arguments, it displays the guards on the current topmost
+patch.
+\interaction{mq.guards.qguard}
+To set a positive guard on a patch, prefix the name of the guard with
+a ``\texttt{+}''.
+\interaction{mq.guards.qguard.pos}
+To set a negative guard on a patch, prefix the name of the guard with
+a ``\texttt{-}''.
+\interaction{mq.guards.qguard.neg}
+
+\begin{note}
+  The \hgxcmd{mq}{qguard} command \emph{sets} the guards on a patch; it
+  doesn't \emph{modify} them.  What this means is that if you run
+  \hgcmdargs{qguard}{+a +b} on a patch, then \hgcmdargs{qguard}{+c} on
+  the same patch, the \emph{only} guard that will be set on it
+  afterwards is \texttt{+c}.
+\end{note}
+
+Mercurial stores guards in the \sfilename{series} file; the form in
+which they are stored is easy both to understand and to edit by hand.
+(In other words, you don't have to use the \hgxcmd{mq}{qguard} command if
+you don't want to; it's okay to simply edit the \sfilename{series}
+file.)
+\interaction{mq.guards.series}
+
+\section{Selecting the guards to use}
+
+The \hgxcmd{mq}{qselect} command determines which guards are active at a
+given time.  The effect of this is to determine which patches MQ will
+apply the next time you run \hgxcmd{mq}{qpush}.  It has no other effect; in
+particular, it doesn't do anything to patches that are already
+applied.
+
+With no arguments, the \hgxcmd{mq}{qselect} command lists the guards
+currently in effect, one per line of output.  Each argument is treated
+as the name of a guard to apply.
+\interaction{mq.guards.qselect.foo}
+In case you're interested, the currently selected guards are stored in
+the \sfilename{guards} file.
+\interaction{mq.guards.qselect.cat}
+We can see the effect the selected guards have when we run
+\hgxcmd{mq}{qpush}.
+\interaction{mq.guards.qselect.qpush}
+
+A guard cannot start with a ``\texttt{+}'' or ``\texttt{-}''
+character.  The name of a guard must not contain white space, but most
+other characters are acceptable.  If you try to use a guard with an
+invalid name, MQ will complain:
+\interaction{mq.guards.qselect.error} 
+Changing the selected guards changes the patches that are applied.
+\interaction{mq.guards.qselect.quux} 
+You can see in the example below that negative guards take precedence
+over positive guards.
+\interaction{mq.guards.qselect.foobar}
+
+\section{MQ's rules for applying patches}
+
+The rules that MQ uses when deciding whether to apply a patch
+are as follows.
+\begin{itemize}
+\item A patch that has no guards is always applied.
+\item If the patch has any negative guard that matches any currently
+  selected guard, the patch is skipped.
+\item If the patch has any positive guard that matches any currently
+  selected guard, the patch is applied.
+\item If the patch has positive or negative guards, but none matches
+  any currently selected guard, the patch is skipped.
+\end{itemize}
+
+\section{Trimming the work environment}
+
+In working on the device driver I mentioned earlier, I don't apply the
+patches to a normal Linux kernel tree.  Instead, I use a repository
+that contains only a snapshot of the source files and headers that are
+relevant to Infiniband development.  This repository is~1\% the size
+of a kernel repository, so it's easier to work with.
+
+I then choose a ``base'' version on top of which the patches are
+applied.  This is a snapshot of the Linux kernel tree as of a revision
+of my choosing.  When I take the snapshot, I record the changeset ID
+from the kernel repository in the commit message.  Since the snapshot
+preserves the ``shape'' and content of the relevant parts of the
+kernel tree, I can apply my patches on top of either my tiny
+repository or a normal kernel tree.
+
+Normally, the base tree atop which the patches apply should be a
+snapshot of a very recent upstream tree.  This best facilitates the
+development of patches that can easily be submitted upstream with few
+or no modifications.
+
+\section{Dividing up the \sfilename{series} file}
+
+I categorise the patches in the \sfilename{series} file into a number
+of logical groups.  Each section of like patches begins with a block
+of comments that describes the purpose of the patches that follow.
+
+The sequence of patch groups that I maintain follows.  The ordering of
+these groups is important; I'll describe why after I introduce the
+groups.
+\begin{itemize}
+\item The ``accepted'' group.  Patches that the development team has
+  submitted to the maintainer of the Infiniband subsystem, and which
+  he has accepted, but which are not present in the snapshot that the
+  tiny repository is based on.  These are ``read only'' patches,
+  present only to transform the tree into a similar state as it is in
+  the upstream maintainer's repository.
+\item The ``rework'' group.  Patches that I have submitted, but that
+  the upstream maintainer has requested modifications to before he
+  will accept them.
+\item The ``pending'' group.  Patches that I have not yet submitted to
+  the upstream maintainer, but which we have finished working on.
+  These will be ``read only'' for a while.  If the upstream maintainer
+  accepts them upon submission, I'll move them to the end of the
+  ``accepted'' group.  If he requests that I modify any, I'll move
+  them to the beginning of the ``rework'' group.
+\item The ``in progress'' group.  Patches that are actively being
+  developed, and should not be submitted anywhere yet.
+\item The ``backport'' group.  Patches that adapt the source tree to
+  older versions of the kernel tree.
+\item The ``do not ship'' group.  Patches that for some reason should
+  never be submitted upstream.  For example, one such patch might
+  change embedded driver identification strings to make it easier to
+  distinguish, in the field, between an out-of-tree version of the
+  driver and a version shipped by a distribution vendor.
+\end{itemize}
+
+Now to return to the reasons for ordering groups of patches in this
+way.  We would like the lowest patches in the stack to be as stable as
+possible, so that we will not need to rework higher patches due to
+changes in context.  Putting patches that will never be changed first
+in the \sfilename{series} file serves this purpose.
+
+We would also like the patches that we know we'll need to modify to be
+applied on top of a source tree that resembles the upstream tree as
+closely as possible.  This is why we keep accepted patches around for
+a while.
+
+The ``backport'' and ``do not ship'' patches float at the end of the
+\sfilename{series} file.  The backport patches must be applied on top
+of all other patches, and the ``do not ship'' patches might as well
+stay out of harm's way.
+
+\section{Maintaining the patch series}
+
+In my work, I use a number of guards to control which patches are to
+be applied.
+
+\begin{itemize}
+\item ``Accepted'' patches are guarded with \texttt{accepted}.  I
+  enable this guard most of the time.  When I'm applying the patches
+  on top of a tree where the patches are already present, I can turn
+  this patch off, and the patches that follow it will apply cleanly.
+\item Patches that are ``finished'', but not yet submitted, have no
+  guards.  If I'm applying the patch stack to a copy of the upstream
+  tree, I don't need to enable any guards in order to get a reasonably
+  safe source tree.
+\item Those patches that need reworking before being resubmitted are
+  guarded with \texttt{rework}.
+\item For those patches that are still under development, I use
+  \texttt{devel}.
+\item A backport patch may have several guards, one for each version
+  of the kernel to which it applies.  For example, a patch that
+  backports a piece of code to~2.6.9 will have a~\texttt{2.6.9} guard.
+\end{itemize}
+This variety of guards gives me considerable flexibility in
+determining what kind of source tree I want to end up with.  For most
+situations, the selection of appropriate guards is automated during
+the build process, but I can manually tune the guards to use for less
+common circumstances.
+
+\subsection{The art of writing backport patches}
+
+Using MQ, writing a backport patch is a simple process.  All such a
+patch has to do is modify a piece of code that uses a kernel feature
+not present in the older version of the kernel, so that the driver
+continues to work correctly under that older version.
+
+A useful goal when writing a good backport patch is to make your code
+look as if it was written for the older version of the kernel you're
+targeting.  The less obtrusive the patch, the easier it will be to
+understand and maintain.  If you're writing a collection of backport
+patches to avoid the ``rat's nest'' effect of lots of
+\texttt{\#ifdef}s (hunks of source code that are only used
+conditionally) in your code, don't introduce version-dependent
+\texttt{\#ifdef}s into the patches.  Instead, write several patches,
+each of which makes unconditional changes, and control their
+application using guards.
+
+There are two reasons to divide backport patches into a distinct
+group, away from the ``regular'' patches whose effects they modify.
+The first is that intermingling the two makes it more difficult to use
+a tool like the \hgext{patchbomb} extension to automate the process of
+submitting the patches to an upstream maintainer.  The second is that
+a backport patch could perturb the context in which a subsequent
+regular patch is applied, making it impossible to apply the regular
+patch cleanly \emph{without} the earlier backport patch already being
+applied.
+
+\section{Useful tips for developing with MQ}
+
+\subsection{Organising patches in directories}
+
+If you're working on a substantial project with MQ, it's not difficult
+to accumulate a large number of patches.  For example, I have one
+patch repository that contains over 250 patches.
+
+If you can group these patches into separate logical categories, you
+can if you like store them in different directories; MQ has no
+problems with patch names that contain path separators.
+
+\subsection{Viewing the history of a patch}
+\label{mq-collab:tips:interdiff}
+
+If you're developing a set of patches over a long time, it's a good
+idea to maintain them in a repository, as discussed in
+section~\ref{sec:mq:repo}.  If you do so, you'll quickly discover that
+using the \hgcmd{diff} command to look at the history of changes to a
+patch is unworkable.  This is in part because you're looking at the
+second derivative of the real code (a diff of a diff), but also
+because MQ adds noise to the process by modifying time stamps and
+directory names when it updates a patch.
+
+However, you can use the \hgext{extdiff} extension, which is bundled
+with Mercurial, to turn a diff of two versions of a patch into
+something readable.  To do this, you will need a third-party package
+called \package{patchutils}~\cite{web:patchutils}.  This provides a
+command named \command{interdiff}, which shows the differences between
+two diffs as a diff.  Used on two versions of the same diff, it
+generates a diff that represents the diff from the first to the second
+version.
+
+You can enable the \hgext{extdiff} extension in the usual way, by
+adding a line to the \rcsection{extensions} section of your \hgrc.
+\begin{codesample2}
+  [extensions]
+  extdiff =
+\end{codesample2}
+The \command{interdiff} command expects to be passed the names of two
+files, but the \hgext{extdiff} extension passes the program it runs a
+pair of directories, each of which can contain an arbitrary number of
+files.  We thus need a small program that will run \command{interdiff}
+on each pair of files in these two directories.  This program is
+available as \sfilename{hg-interdiff} in the \dirname{examples}
+directory of the source code repository that accompanies this book.
+\excode{hg-interdiff}
+
+With the \sfilename{hg-interdiff} program in your shell's search path,
+you can run it as follows, from inside an MQ patch directory:
+\begin{codesample2}
+  hg extdiff -p hg-interdiff -r A:B my-change.patch
+\end{codesample2}
+Since you'll probably want to use this long-winded command a lot, you
+can get \hgext{hgext} to make it available as a normal Mercurial
+command, again by editing your \hgrc.
+\begin{codesample2}
+  [extdiff]
+  cmd.interdiff = hg-interdiff
+\end{codesample2}
+This directs \hgext{hgext} to make an \texttt{interdiff} command
+available, so you can now shorten the previous invocation of
+\hgxcmd{extdiff}{extdiff} to something a little more wieldy.
+\begin{codesample2}
+  hg interdiff -r A:B my-change.patch
+\end{codesample2}
+
+\begin{note}
+  The \command{interdiff} command works well only if the underlying
+  files against which versions of a patch are generated remain the
+  same.  If you create a patch, modify the underlying files, and then
+  regenerate the patch, \command{interdiff} may not produce useful
+  output.
+\end{note}
+
+The \hgext{extdiff} extension is useful for more than merely improving
+the presentation of MQ~patches.  To read more about it, go to
+section~\ref{sec:hgext:extdiff}.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/en/ch14-hgext.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,428 @@
+\chapter{Adding functionality with extensions}
+\label{chap:hgext}
+
+While the core of Mercurial is quite complete from a functionality
+standpoint, it's deliberately shorn of fancy features.  This approach
+of preserving simplicity keeps the software easy to deal with for both
+maintainers and users.
+
+However, Mercurial doesn't box you in with an inflexible command set:
+you can add features to it as \emph{extensions} (sometimes known as
+\emph{plugins}).  We've already discussed a few of these extensions in
+earlier chapters.
+\begin{itemize}
+\item Section~\ref{sec:tour-merge:fetch} covers the \hgext{fetch}
+  extension; this combines pulling new changes and merging them with
+  local changes into a single command, \hgxcmd{fetch}{fetch}.
+\item In chapter~\ref{chap:hook}, we covered several extensions that
+  are useful for hook-related functionality: \hgext{acl} adds access
+  control lists; \hgext{bugzilla} adds integration with the Bugzilla
+  bug tracking system; and \hgext{notify} sends notification emails on
+  new changes.
+\item The Mercurial Queues patch management extension is so invaluable
+  that it merits two chapters and an appendix all to itself.
+  Chapter~\ref{chap:mq} covers the basics;
+  chapter~\ref{chap:mq-collab} discusses advanced topics; and
+  appendix~\ref{chap:mqref} goes into detail on each command.
+\end{itemize}
+
+In this chapter, we'll cover some of the other extensions that are
+available for Mercurial, and briefly touch on some of the machinery
+you'll need to know about if you want to write an extension of your
+own.
+\begin{itemize}
+\item In section~\ref{sec:hgext:inotify}, we'll discuss the
+  possibility of \emph{huge} performance improvements using the
+  \hgext{inotify} extension.
+\end{itemize}
+
+\section{Improve performance with the \hgext{inotify} extension}
+\label{sec:hgext:inotify}
+
+Are you interested in having some of the most common Mercurial
+operations run as much as a hundred times faster?  Read on!
+
+Mercurial has great performance under normal circumstances.  For
+example, when you run the \hgcmd{status} command, Mercurial has to
+scan almost every directory and file in your repository so that it can
+display file status.  Many other Mercurial commands need to do the
+same work behind the scenes; for example, the \hgcmd{diff} command
+uses the status machinery to avoid doing an expensive comparison
+operation on files that obviously haven't changed.
+
+Because obtaining file status is crucial to good performance, the
+authors of Mercurial have optimised this code to within an inch of its
+life.  However, there's no avoiding the fact that when you run
+\hgcmd{status}, Mercurial is going to have to perform at least one
+expensive system call for each managed file to determine whether it's
+changed since the last time Mercurial checked.  For a sufficiently
+large repository, this can take a long time.
+
+To put a number on the magnitude of this effect, I created a
+repository containing 150,000 managed files.  I timed \hgcmd{status}
+as taking ten seconds to run, even when \emph{none} of those files had
+been modified.
+
+Many modern operating systems contain a file notification facility.
+If a program signs up to an appropriate service, the operating system
+will notify it every time a file of interest is created, modified, or
+deleted.  On Linux systems, the kernel component that does this is
+called \texttt{inotify}.
+
+Mercurial's \hgext{inotify} extension talks to the kernel's
+\texttt{inotify} component to optimise \hgcmd{status} commands.  The
+extension has two components.  A daemon sits in the background and
+receives notifications from the \texttt{inotify} subsystem.  It also
+listens for connections from a regular Mercurial command.  The
+extension modifies Mercurial's behaviour so that instead of scanning
+the filesystem, it queries the daemon.  Since the daemon has perfect
+information about the state of the repository, it can respond with a
+result instantaneously, avoiding the need to scan every directory and
+file in the repository.
+
+Recall the ten seconds that I measured plain Mercurial as taking to
+run \hgcmd{status} on a 150,000 file repository.  With the
+\hgext{inotify} extension enabled, the time dropped to 0.1~seconds, a
+factor of \emph{one hundred} faster.
+
+Before we continue, please pay attention to some caveats.
+\begin{itemize}
+\item The \hgext{inotify} extension is Linux-specific.  Because it
+  interfaces directly to the Linux kernel's \texttt{inotify}
+  subsystem, it does not work on other operating systems.
+\item It should work on any Linux distribution that was released after
+  early~2005.  Older distributions are likely to have a kernel that
+  lacks \texttt{inotify}, or a version of \texttt{glibc} that does not
+  have the necessary interfacing support.
+\item Not all filesystems are suitable for use with the
+  \hgext{inotify} extension.  Network filesystems such as NFS are a
+  non-starter, for example, particularly if you're running Mercurial
+  on several systems, all mounting the same network filesystem.  The
+  kernel's \texttt{inotify} system has no way of knowing about changes
+  made on another system.  Most local filesystems (e.g.~ext3, XFS,
+  ReiserFS) should work fine.
+\end{itemize}
+
+The \hgext{inotify} extension is not yet shipped with Mercurial as of
+May~2007, so it's a little more involved to set up than other
+extensions.  But the performance improvement is worth it!
+
+The extension currently comes in two parts: a set of patches to the
+Mercurial source code, and a library of Python bindings to the
+\texttt{inotify} subsystem.
+\begin{note}
+  There are \emph{two} Python \texttt{inotify} binding libraries.  One
+  of them is called \texttt{pyinotify}, and is packaged by some Linux
+  distributions as \texttt{python-inotify}.  This is \emph{not} the
+  one you'll need, as it is too buggy and inefficient to be practical.
+\end{note}
+To get going, it's best to already have a functioning copy of
+Mercurial installed.
+\begin{note}
+  If you follow the instructions below, you'll be \emph{replacing} and
+  overwriting any existing installation of Mercurial that you might
+  already have, using the latest ``bleeding edge'' Mercurial code.
+  Don't say you weren't warned!
+\end{note}
+\begin{enumerate}
+\item Clone the Python \texttt{inotify} binding repository.  Build and
+  install it.
+  \begin{codesample4}
+    hg clone http://hg.kublai.com/python/inotify
+    cd inotify
+    python setup.py build --force
+    sudo python setup.py install --skip-build
+  \end{codesample4}
+\item Clone the \dirname{crew} Mercurial repository.  Clone the
+  \hgext{inotify} patch repository so that Mercurial Queues will be
+  able to apply patches to your cope of the \dirname{crew} repository.
+  \begin{codesample4}
+    hg clone http://hg.intevation.org/mercurial/crew
+    hg clone crew inotify
+    hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches
+  \end{codesample4}
+\item Make sure that you have the Mercurial Queues extension,
+  \hgext{mq}, enabled.  If you've never used MQ, read
+  section~\ref{sec:mq:start} to get started quickly.
+\item Go into the \dirname{inotify} repo, and apply all of the
+  \hgext{inotify} patches using the \hgxopt{mq}{qpush}{-a} option to
+  the \hgxcmd{mq}{qpush} command.
+  \begin{codesample4}
+    cd inotify
+    hg qpush -a
+  \end{codesample4}
+  If you get an error message from \hgxcmd{mq}{qpush}, you should not
+  continue.  Instead, ask for help.
+\item Build and install the patched version of Mercurial.
+  \begin{codesample4}
+    python setup.py build --force
+    sudo python setup.py install --skip-build
+  \end{codesample4}
+\end{enumerate}
+Once you've build a suitably patched version of Mercurial, all you
+need to do to enable the \hgext{inotify} extension is add an entry to
+your \hgrc.
+\begin{codesample2}
+  [extensions]
+  inotify =
+\end{codesample2}
+When the \hgext{inotify} extension is enabled, Mercurial will
+automatically and transparently start the status daemon the first time
+you run a command that needs status in a repository.  It runs one
+status daemon per repository.
+
+The status daemon is started silently, and runs in the background.  If
+you look at a list of running processes after you've enabled the
+\hgext{inotify} extension and run a few commands in different
+repositories, you'll thus see a few \texttt{hg} processes sitting
+around, waiting for updates from the kernel and queries from
+Mercurial.
+
+The first time you run a Mercurial command in a repository when you
+have the \hgext{inotify} extension enabled, it will run with about the
+same performance as a normal Mercurial command.  This is because the
+status daemon needs to perform a normal status scan so that it has a
+baseline against which to apply later updates from the kernel.
+However, \emph{every} subsequent command that does any kind of status
+check should be noticeably faster on repositories of even fairly
+modest size.  Better yet, the bigger your repository is, the greater a
+performance advantage you'll see.  The \hgext{inotify} daemon makes
+status operations almost instantaneous on repositories of all sizes!
+
+If you like, you can manually start a status daemon using the
+\hgxcmd{inotify}{inserve} command.  This gives you slightly finer
+control over how the daemon ought to run.  This command will of course
+only be available when the \hgext{inotify} extension is enabled.
+
+When you're using the \hgext{inotify} extension, you should notice
+\emph{no difference at all} in Mercurial's behaviour, with the sole
+exception of status-related commands running a whole lot faster than
+they used to.  You should specifically expect that commands will not
+print different output; neither should they give different results.
+If either of these situations occurs, please report a bug.
+
+\section{Flexible diff support with the \hgext{extdiff} extension}
+\label{sec:hgext:extdiff}
+
+Mercurial's built-in \hgcmd{diff} command outputs plaintext unified
+diffs.
+\interaction{extdiff.diff}
+If you would like to use an external tool to display modifications,
+you'll want to use the \hgext{extdiff} extension.  This will let you
+use, for example, a graphical diff tool.
+
+The \hgext{extdiff} extension is bundled with Mercurial, so it's easy
+to set up.  In the \rcsection{extensions} section of your \hgrc,
+simply add a one-line entry to enable the extension.
+\begin{codesample2}
+  [extensions]
+  extdiff =
+\end{codesample2}
+This introduces a command named \hgxcmd{extdiff}{extdiff}, which by
+default uses your system's \command{diff} command to generate a
+unified diff in the same form as the built-in \hgcmd{diff} command.
+\interaction{extdiff.extdiff}
+The result won't be exactly the same as with the built-in \hgcmd{diff}
+variations, because the output of \command{diff} varies from one
+system to another, even when passed the same options.
+
+As the ``\texttt{making snapshot}'' lines of output above imply, the
+\hgxcmd{extdiff}{extdiff} command works by creating two snapshots of
+your source tree.  The first snapshot is of the source revision; the
+second, of the target revision or working directory.  The
+\hgxcmd{extdiff}{extdiff} command generates these snapshots in a
+temporary directory, passes the name of each directory to an external
+diff viewer, then deletes the temporary directory.  For efficiency, it
+only snapshots the directories and files that have changed between the
+two revisions.
+
+Snapshot directory names have the same base name as your repository.
+If your repository path is \dirname{/quux/bar/foo}, then \dirname{foo}
+will be the name of each snapshot directory.  Each snapshot directory
+name has its changeset ID appended, if appropriate.  If a snapshot is
+of revision \texttt{a631aca1083f}, the directory will be named
+\dirname{foo.a631aca1083f}.  A snapshot of the working directory won't
+have a changeset ID appended, so it would just be \dirname{foo} in
+this example.  To see what this looks like in practice, look again at
+the \hgxcmd{extdiff}{extdiff} example above.  Notice that the diff has
+the snapshot directory names embedded in its header.
+
+The \hgxcmd{extdiff}{extdiff} command accepts two important options.
+The \hgxopt{extdiff}{extdiff}{-p} option lets you choose a program to
+view differences with, instead of \command{diff}.  With the
+\hgxopt{extdiff}{extdiff}{-o} option, you can change the options that
+\hgxcmd{extdiff}{extdiff} passes to the program (by default, these
+options are ``\texttt{-Npru}'', which only make sense if you're
+running \command{diff}).  In other respects, the
+\hgxcmd{extdiff}{extdiff} command acts similarly to the built-in
+\hgcmd{diff} command: you use the same option names, syntax, and
+arguments to specify the revisions you want, the files you want, and
+so on.
+
+As an example, here's how to run the normal system \command{diff}
+command, getting it to generate context diffs (using the
+\cmdopt{diff}{-c} option) instead of unified diffs, and five lines of
+context instead of the default three (passing \texttt{5} as the
+argument to the \cmdopt{diff}{-C} option).
+\interaction{extdiff.extdiff-ctx}
+
+Launching a visual diff tool is just as easy.  Here's how to launch
+the \command{kdiff3} viewer.
+\begin{codesample2}
+  hg extdiff -p kdiff3 -o ''
+\end{codesample2}
+
+If your diff viewing command can't deal with directories, you can
+easily work around this with a little scripting.  For an example of
+such scripting in action with the \hgext{mq} extension and the
+\command{interdiff} command, see
+section~\ref{mq-collab:tips:interdiff}.
+
+\subsection{Defining command aliases}
+
+It can be cumbersome to remember the options to both the
+\hgxcmd{extdiff}{extdiff} command and the diff viewer you want to use,
+so the \hgext{extdiff} extension lets you define \emph{new} commands
+that will invoke your diff viewer with exactly the right options.
+
+All you need to do is edit your \hgrc, and add a section named
+\rcsection{extdiff}.  Inside this section, you can define multiple
+commands.  Here's how to add a \texttt{kdiff3} command.  Once you've
+defined this, you can type ``\texttt{hg kdiff3}'' and the
+\hgext{extdiff} extension will run \command{kdiff3} for you.
+\begin{codesample2}
+  [extdiff]
+  cmd.kdiff3 =
+\end{codesample2}
+If you leave the right hand side of the definition empty, as above,
+the \hgext{extdiff} extension uses the name of the command you defined
+as the name of the external program to run.  But these names don't
+have to be the same.  Here, we define a command named ``\texttt{hg wibble}'', which runs \command{kdiff3}.
+\begin{codesample2}
+  [extdiff]
+  cmd.wibble = kdiff3
+\end{codesample2}
+
+You can also specify the default options that you want to invoke your
+diff viewing program with.  The prefix to use is ``\texttt{opts.}'',
+followed by the name of the command to which the options apply.  This
+example defines a ``\texttt{hg vimdiff}'' command that runs the
+\command{vim} editor's \texttt{DirDiff} extension.
+\begin{codesample2}
+  [extdiff]  
+  cmd.vimdiff = vim
+  opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'
+\end{codesample2}
+
+\section{Cherrypicking changes with the \hgext{transplant} extension}
+\label{sec:hgext:transplant}
+
+Need to have a long chat with Brendan about this.
+
+\section{Send changes via email with the \hgext{patchbomb} extension}
+\label{sec:hgext:patchbomb}
+
+Many projects have a culture of ``change review'', in which people
+send their modifications to a mailing list for others to read and
+comment on before they commit the final version to a shared
+repository.  Some projects have people who act as gatekeepers; they
+apply changes from other people to a repository to which those others
+don't have access.
+
+Mercurial makes it easy to send changes over email for review or
+application, via its \hgext{patchbomb} extension.  The extension is so
+namd because changes are formatted as patches, and it's usual to send
+one changeset per email message.  Sending a long series of changes by
+email is thus much like ``bombing'' the recipient's inbox, hence
+``patchbomb''.
+
+As usual, the basic configuration of the \hgext{patchbomb} extension
+takes just one or two lines in your \hgrc.
+\begin{codesample2}
+  [extensions]
+  patchbomb =
+\end{codesample2}
+Once you've enabled the extension, you will have a new command
+available, named \hgxcmd{patchbomb}{email}.
+
+The safest and best way to invoke the \hgxcmd{patchbomb}{email}
+command is to \emph{always} run it first with the
+\hgxopt{patchbomb}{email}{-n} option.  This will show you what the
+command \emph{would} send, without actually sending anything.  Once
+you've had a quick glance over the changes and verified that you are
+sending the right ones, you can rerun the same command, with the
+\hgxopt{patchbomb}{email}{-n} option removed.
+
+The \hgxcmd{patchbomb}{email} command accepts the same kind of
+revision syntax as every other Mercurial command.  For example, this
+command will send every revision between 7 and \texttt{tip},
+inclusive.
+\begin{codesample2}
+  hg email -n 7:tip
+\end{codesample2}
+You can also specify a \emph{repository} to compare with.  If you
+provide a repository but no revisions, the \hgxcmd{patchbomb}{email}
+command will send all revisions in the local repository that are not
+present in the remote repository.  If you additionally specify
+revisions or a branch name (the latter using the
+\hgxopt{patchbomb}{email}{-b} option), this will constrain the
+revisions sent.
+
+It's perfectly safe to run the \hgxcmd{patchbomb}{email} command
+without the names of the people you want to send to: if you do this,
+it will just prompt you for those values interactively.  (If you're
+using a Linux or Unix-like system, you should have enhanced
+\texttt{readline}-style editing capabilities when entering those
+headers, too, which is useful.)
+
+When you are sending just one revision, the \hgxcmd{patchbomb}{email}
+command will by default use the first line of the changeset
+description as the subject of the single email message it sends.
+
+If you send multiple revisions, the \hgxcmd{patchbomb}{email} command
+will usually send one message per changeset.  It will preface the
+series with an introductory message, in which you should describe the
+purpose of the series of changes you're sending.
+
+\subsection{Changing the behaviour of patchbombs}
+
+Not every project has exactly the same conventions for sending changes
+in email; the \hgext{patchbomb} extension tries to accommodate a
+number of variations through command line options.
+\begin{itemize}
+\item You can write a subject for the introductory message on the
+  command line using the \hgxopt{patchbomb}{email}{-s} option.  This
+  takes one argument, the text of the subject to use.
+\item To change the email address from which the messages originate,
+  use the \hgxopt{patchbomb}{email}{-f} option.  This takes one
+  argument, the email address to use.
+\item The default behaviour is to send unified diffs (see
+  section~\ref{sec:mq:patch} for a description of the format), one per
+  message.  You can send a binary bundle instead with the
+  \hgxopt{patchbomb}{email}{-b} option.  
+\item Unified diffs are normally prefaced with a metadata header.  You
+  can omit this, and send unadorned diffs, with the
+  \hgxopt{patchbomb}{email}{--plain} option.
+\item Diffs are normally sent ``inline'', in the same body part as the
+  description of a patch.  This makes it easiest for the largest
+  number of readers to quote and respond to parts of a diff, as some
+  mail clients will only quote the first MIME body part in a message.
+  If you'd prefer to send the description and the diff in separate
+  body parts, use the \hgxopt{patchbomb}{email}{-a} option.
+\item Instead of sending mail messages, you can write them to an
+  \texttt{mbox}-format mail folder using the
+  \hgxopt{patchbomb}{email}{-m} option.  That option takes one
+  argument, the name of the file to write to.
+\item If you would like to add a \command{diffstat}-format summary to
+  each patch, and one to the introductory message, use the
+  \hgxopt{patchbomb}{email}{-d} option.  The \command{diffstat}
+  command displays a table containing the name of each file patched,
+  the number of lines affected, and a histogram showing how much each
+  file is modified.  This gives readers a qualitative glance at how
+  complex a patch is.
+\end{itemize}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- a/en/cmdref.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-\chapter{Command reference}
-\label{cmdref}
-
-\cmdref{add}{add files at the next commit}
-\optref{add}{I}{include}
-\optref{add}{X}{exclude}
-\optref{add}{n}{dry-run}
-
-\cmdref{diff}{print changes in history or working directory}
-
-Show differences between revisions for the specified files or
-directories, using the unified diff format.  For a description of the
-unified diff format, see section~\ref{sec:mq:patch}.
-
-By default, this command does not print diffs for files that Mercurial
-considers to contain binary data.  To control this behaviour, see the
-\hgopt{diff}{-a} and \hgopt{diff}{--git} options.
-
-\subsection{Options}
-
-\loptref{diff}{nodates}
-
-Omit date and time information when printing diff headers.
-
-\optref{diff}{B}{ignore-blank-lines}
-
-Do not print changes that only insert or delete blank lines.  A line
-that contains only whitespace is not considered blank.
-
-\optref{diff}{I}{include}
-
-Include files and directories whose names match the given patterns.
-
-\optref{diff}{X}{exclude}
-
-Exclude files and directories whose names match the given patterns.
-
-\optref{diff}{a}{text}
-
-If this option is not specified, \hgcmd{diff} will refuse to print
-diffs for files that it detects as binary. Specifying \hgopt{diff}{-a}
-forces \hgcmd{diff} to treat all files as text, and generate diffs for
-all of them.
-
-This option is useful for files that are ``mostly text'' but have a
-few embedded NUL characters.  If you use it on files that contain a
-lot of binary data, its output will be incomprehensible.
-
-\optref{diff}{b}{ignore-space-change}
-
-Do not print a line if the only change to that line is in the amount
-of white space it contains.
-
-\optref{diff}{g}{git}
-
-Print \command{git}-compatible diffs.  XXX reference a format
-description.
-
-\optref{diff}{p}{show-function}
-
-Display the name of the enclosing function in a hunk header, using a
-simple heuristic.  This functionality is enabled by default, so the
-\hgopt{diff}{-p} option has no effect unless you change the value of
-the \rcitem{diff}{showfunc} config item, as in the following example.
-\interaction{cmdref.diff-p}
-
-\optref{diff}{r}{rev}
-
-Specify one or more revisions to compare.  The \hgcmd{diff} command
-accepts up to two \hgopt{diff}{-r} options to specify the revisions to
-compare.
-
-\begin{enumerate}
-\setcounter{enumi}{0}
-\item Display the differences between the parent revision of the
-  working directory and the working directory.
-\item Display the differences between the specified changeset and the
-  working directory.
-\item Display the differences between the two specified changesets.
-\end{enumerate}
-
-You can specify two revisions using either two \hgopt{diff}{-r}
-options or revision range notation.  For example, the two revision
-specifications below are equivalent.
-\begin{codesample2}
-  hg diff -r 10 -r 20
-  hg diff -r10:20
-\end{codesample2}
-
-When you provide two revisions, Mercurial treats the order of those
-revisions as significant.  Thus, \hgcmdargs{diff}{-r10:20} will
-produce a diff that will transform files from their contents as of
-revision~10 to their contents as of revision~20, while
-\hgcmdargs{diff}{-r20:10} means the opposite: the diff that will
-transform files from their revision~20 contents to their revision~10
-contents.  You cannot reverse the ordering in this way if you are
-diffing against the working directory.
-
-\optref{diff}{w}{ignore-all-space}
-
-\cmdref{version}{print version and copyright information}
-
-This command displays the version of Mercurial you are running, and
-its copyright license.  There are four kinds of version string that
-you may see.
-\begin{itemize}
-\item The string ``\texttt{unknown}''. This version of Mercurial was
-  not built in a Mercurial repository, and cannot determine its own
-  version.
-\item A short numeric string, such as ``\texttt{1.1}''. This is a
-  build of a revision of Mercurial that was identified by a specific
-  tag in the repository where it was built.  (This doesn't necessarily
-  mean that you're running an official release; someone else could
-  have added that tag to any revision in the repository where they
-  built Mercurial.)
-\item A hexadecimal string, such as ``\texttt{875489e31abe}''.  This
-  is a build of the given revision of Mercurial.
-\item A hexadecimal string followed by a date, such as
-  ``\texttt{875489e31abe+20070205}''.  This is a build of the given
-  revision of Mercurial, where the build repository contained some
-  local changes that had not been committed.
-\end{itemize}
-
-\subsection{Tips and tricks}
-
-\subsubsection{Why do the results of \hgcmd{diff} and \hgcmd{status}
-  differ?}
-\label{cmdref:diff-vs-status}
-
-When you run the \hgcmd{status} command, you'll see a list of files
-that Mercurial will record changes for the next time you perform a
-commit.  If you run the \hgcmd{diff} command, you may notice that it
-prints diffs for only a \emph{subset} of the files that \hgcmd{status}
-listed.  There are two possible reasons for this.
-
-The first is that \hgcmd{status} prints some kinds of modifications
-that \hgcmd{diff} doesn't normally display.  The \hgcmd{diff} command
-normally outputs unified diffs, which don't have the ability to
-represent some changes that Mercurial can track.  Most notably,
-traditional diffs can't represent a change in whether or not a file is
-executable, but Mercurial records this information.
-
-If you use the \hgopt{diff}{--git} option to \hgcmd{diff}, it will
-display \command{git}-compatible diffs that \emph{can} display this
-extra information.
-
-The second possible reason that \hgcmd{diff} might be printing diffs
-for a subset of the files displayed by \hgcmd{status} is that if you
-invoke it without any arguments, \hgcmd{diff} prints diffs against the
-first parent of the working directory.  If you have run \hgcmd{merge}
-to merge two changesets, but you haven't yet committed the results of
-the merge, your working directory has two parents (use \hgcmd{parents}
-to see them).  While \hgcmd{status} prints modifications relative to
-\emph{both} parents after an uncommitted merge, \hgcmd{diff} still
-operates relative only to the first parent.  You can get it to print
-diffs relative to the second parent by specifying that parent with the
-\hgopt{diff}{-r} option.  There is no way to print diffs relative to
-both parents.
-
-\subsubsection{Generating safe binary diffs}
-
-If you use the \hgopt{diff}{-a} option to force Mercurial to print
-diffs of files that are either ``mostly text'' or contain lots of
-binary data, those diffs cannot subsequently be applied by either
-Mercurial's \hgcmd{import} command or the system's \command{patch}
-command.  
-
-If you want to generate a diff of a binary file that is safe to use as
-input for \hgcmd{import}, use the \hgcmd{diff}{--git} option when you
-generate the patch.  The system \command{patch} command cannot handle
-binary patches at all.
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/collab.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1118 +0,0 @@
-\chapter{Collaborating with other people}
-\label{cha:collab}
-
-As a completely decentralised tool, Mercurial doesn't impose any
-policy on how people ought to work with each other.  However, if
-you're new to distributed revision control, it helps to have some
-tools and examples in mind when you're thinking about possible
-workflow models.
-
-\section{Mercurial's web interface}
-
-Mercurial has a powerful web interface that provides several 
-useful capabilities.
-
-For interactive use, the web interface lets you browse a single
-repository or a collection of repositories.  You can view the history
-of a repository, examine each change (comments and diffs), and view
-the contents of each directory and file.
-
-Also for human consumption, the web interface provides an RSS feed of
-the changes in a repository.  This lets you ``subscribe'' to a
-repository using your favourite feed reader, and be automatically
-notified of activity in that repository as soon as it happens.  I find
-this capability much more convenient than the model of subscribing to
-a mailing list to which notifications are sent, as it requires no
-additional configuration on the part of whoever is serving the
-repository.
-
-The web interface also lets remote users clone a repository, pull
-changes from it, and (when the server is configured to permit it) push
-changes back to it.  Mercurial's HTTP tunneling protocol aggressively
-compresses data, so that it works efficiently even over low-bandwidth
-network connections.
-
-The easiest way to get started with the web interface is to use your
-web browser to visit an existing repository, such as the master
-Mercurial repository at
-\url{http://www.selenic.com/repo/hg?style=gitweb}.
-
-If you're interested in providing a web interface to your own
-repositories, Mercurial provides two ways to do this.  The first is
-using the \hgcmd{serve} command, which is best suited to short-term
-``lightweight'' serving.  See section~\ref{sec:collab:serve} below for
-details of how to use this command.  If you have a long-lived
-repository that you'd like to make permanently available, Mercurial
-has built-in support for the CGI (Common Gateway Interface) standard,
-which all common web servers support.  See
-section~\ref{sec:collab:cgi} for details of CGI configuration.
-
-\section{Collaboration models}
-
-With a suitably flexible tool, making decisions about workflow is much
-more of a social engineering challenge than a technical one.
-Mercurial imposes few limitations on how you can structure the flow of
-work in a project, so it's up to you and your group to set up and live
-with a model that matches your own particular needs.
-
-\subsection{Factors to keep in mind}
-
-The most important aspect of any model that you must keep in mind is
-how well it matches the needs and capabilities of the people who will
-be using it.  This might seem self-evident; even so, you still can't
-afford to forget it for a moment.
-
-I once put together a workflow model that seemed to make perfect sense
-to me, but that caused a considerable amount of consternation and
-strife within my development team.  In spite of my attempts to explain
-why we needed a complex set of branches, and how changes ought to flow
-between them, a few team members revolted.  Even though they were
-smart people, they didn't want to pay attention to the constraints we
-were operating under, or face the consequences of those constraints in
-the details of the model that I was advocating.
-
-Don't sweep foreseeable social or technical problems under the rug.
-Whatever scheme you put into effect, you should plan for mistakes and
-problem scenarios.  Consider adding automated machinery to prevent, or
-quickly recover from, trouble that you can anticipate.  As an example,
-if you intend to have a branch with not-for-release changes in it,
-you'd do well to think early about the possibility that someone might
-accidentally merge those changes into a release branch.  You could
-avoid this particular problem by writing a hook that prevents changes
-from being merged from an inappropriate branch.
-
-\subsection{Informal anarchy}
-
-I wouldn't suggest an ``anything goes'' approach as something
-sustainable, but it's a model that's easy to grasp, and it works
-perfectly well in a few unusual situations.
-
-As one example, many projects have a loose-knit group of collaborators
-who rarely physically meet each other.  Some groups like to overcome
-the isolation of working at a distance by organising occasional
-``sprints''.  In a sprint, a number of people get together in a single
-location (a company's conference room, a hotel meeting room, that kind
-of place) and spend several days more or less locked in there, hacking
-intensely on a handful of projects.
-
-A sprint is the perfect place to use the \hgcmd{serve} command, since
-\hgcmd{serve} does not requires any fancy server infrastructure.  You
-can get started with \hgcmd{serve} in moments, by reading
-section~\ref{sec:collab:serve} below.  Then simply tell the person
-next to you that you're running a server, send the URL to them in an
-instant message, and you immediately have a quick-turnaround way to
-work together.  They can type your URL into their web browser and
-quickly review your changes; or they can pull a bugfix from you and
-verify it; or they can clone a branch containing a new feature and try
-it out.
-
-The charm, and the problem, with doing things in an ad hoc fashion
-like this is that only people who know about your changes, and where
-they are, can see them.  Such an informal approach simply doesn't
-scale beyond a handful people, because each individual needs to know
-about $n$ different repositories to pull from.
-
-\subsection{A single central repository}
-
-For smaller projects migrating from a centralised revision control
-tool, perhaps the easiest way to get started is to have changes flow
-through a single shared central repository.  This is also the
-most common ``building block'' for more ambitious workflow schemes.
-
-Contributors start by cloning a copy of this repository.  They can
-pull changes from it whenever they need to, and some (perhaps all)
-developers have permission to push a change back when they're ready
-for other people to see it.
-
-Under this model, it can still often make sense for people to pull
-changes directly from each other, without going through the central
-repository.  Consider a case in which I have a tentative bug fix, but
-I am worried that if I were to publish it to the central repository,
-it might subsequently break everyone else's trees as they pull it.  To
-reduce the potential for damage, I can ask you to clone my repository
-into a temporary repository of your own and test it.  This lets us put
-off publishing the potentially unsafe change until it has had a little
-testing.
-
-In this kind of scenario, people usually use the \command{ssh}
-protocol to securely push changes to the central repository, as
-documented in section~\ref{sec:collab:ssh}.  It's also usual to
-publish a read-only copy of the repository over HTTP using CGI, as in
-section~\ref{sec:collab:cgi}.  Publishing over HTTP satisfies the
-needs of people who don't have push access, and those who want to use
-web browsers to browse the repository's history.
-
-\subsection{Working with multiple branches}
-
-Projects of any significant size naturally tend to make progress on
-several fronts simultaneously.  In the case of software, it's common
-for a project to go through periodic official releases.  A release
-might then go into ``maintenance mode'' for a while after its first
-publication; maintenance releases tend to contain only bug fixes, not
-new features.  In parallel with these maintenance releases, one or
-more future releases may be under development.  People normally use
-the word ``branch'' to refer to one of these many slightly different
-directions in which development is proceeding.
-
-Mercurial is particularly well suited to managing a number of
-simultaneous, but not identical, branches.  Each ``development
-direction'' can live in its own central repository, and you can merge
-changes from one to another as the need arises.  Because repositories
-are independent of each other, unstable changes in a development
-branch will never affect a stable branch unless someone explicitly
-merges those changes in.
-
-Here's an example of how this can work in practice.  Let's say you
-have one ``main branch'' on a central server.
-\interaction{branching.init}
-People clone it, make changes locally, test them, and push them back.
-
-Once the main branch reaches a release milestone, you can use the
-\hgcmd{tag} command to give a permanent name to the milestone
-revision.
-\interaction{branching.tag}
-Let's say some ongoing development occurs on the main branch.
-\interaction{branching.main}
-Using the tag that was recorded at the milestone, people who clone
-that repository at any time in the future can use \hgcmd{update} to
-get a copy of the working directory exactly as it was when that tagged
-revision was committed.  
-\interaction{branching.update}
-
-In addition, immediately after the main branch is tagged, someone can
-then clone the main branch on the server to a new ``stable'' branch,
-also on the server.
-\interaction{branching.clone}
-
-Someone who needs to make a change to the stable branch can then clone
-\emph{that} repository, make their changes, commit, and push their
-changes back there.
-\interaction{branching.stable}
-Because Mercurial repositories are independent, and Mercurial doesn't
-move changes around automatically, the stable and main branches are
-\emph{isolated} from each other.  The changes that you made on the
-main branch don't ``leak'' to the stable branch, and vice versa.
-
-You'll often want all of your bugfixes on the stable branch to show up
-on the main branch, too.  Rather than rewrite a bugfix on the main
-branch, you can simply pull and merge changes from the stable to the
-main branch, and Mercurial will bring those bugfixes in for you.
-\interaction{branching.merge}
-The main branch will still contain changes that are not on the stable
-branch, but it will also contain all of the bugfixes from the stable
-branch.  The stable branch remains unaffected by these changes.
-
-\subsection{Feature branches}
-
-For larger projects, an effective way to manage change is to break up
-a team into smaller groups.  Each group has a shared branch of its
-own, cloned from a single ``master'' branch used by the entire
-project.  People working on an individual branch are typically quite
-isolated from developments on other branches.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{feature-branches}
-  \caption{Feature branches}
-  \label{fig:collab:feature-branches}
-\end{figure}
-
-When a particular feature is deemed to be in suitable shape, someone
-on that feature team pulls and merges from the master branch into the
-feature branch, then pushes back up to the master branch.
-
-\subsection{The release train}
-
-Some projects are organised on a ``train'' basis: a release is
-scheduled to happen every few months, and whatever features are ready
-when the ``train'' is ready to leave are allowed in.
-
-This model resembles working with feature branches.  The difference is
-that when a feature branch misses a train, someone on the feature team
-pulls and merges the changes that went out on that train release into
-the feature branch, and the team continues its work on top of that
-release so that their feature can make the next release.
-
-\subsection{The Linux kernel model}
-
-The development of the Linux kernel has a shallow hierarchical
-structure, surrounded by a cloud of apparent chaos.  Because most
-Linux developers use \command{git}, a distributed revision control
-tool with capabilities similar to Mercurial, it's useful to describe
-the way work flows in that environment; if you like the ideas, the
-approach translates well across tools.
-
-At the center of the community sits Linus Torvalds, the creator of
-Linux.  He publishes a single source repository that is considered the
-``authoritative'' current tree by the entire developer community.
-Anyone can clone Linus's tree, but he is very choosy about whose trees
-he pulls from.
-
-Linus has a number of ``trusted lieutenants''.  As a general rule, he
-pulls whatever changes they publish, in most cases without even
-reviewing those changes.  Some of those lieutenants are generally
-agreed to be ``maintainers'', responsible for specific subsystems
-within the kernel.  If a random kernel hacker wants to make a change
-to a subsystem that they want to end up in Linus's tree, they must
-find out who the subsystem's maintainer is, and ask that maintainer to
-take their change.  If the maintainer reviews their changes and agrees
-to take them, they'll pass them along to Linus in due course.
-
-Individual lieutenants have their own approaches to reviewing,
-accepting, and publishing changes; and for deciding when to feed them
-to Linus.  In addition, there are several well known branches that
-people use for different purposes.  For example, a few people maintain
-``stable'' repositories of older versions of the kernel, to which they
-apply critical fixes as needed.  Some maintainers publish multiple
-trees: one for experimental changes; one for changes that they are
-about to feed upstream; and so on.  Others just publish a single
-tree.
-
-This model has two notable features.  The first is that it's ``pull
-only''.  You have to ask, convince, or beg another developer to take a
-change from you, because there are almost no trees to which more than
-one person can push, and there's no way to push changes into a tree
-that someone else controls.
-
-The second is that it's based on reputation and acclaim.  If you're an
-unknown, Linus will probably ignore changes from you without even
-responding.  But a subsystem maintainer will probably review them, and
-will likely take them if they pass their criteria for suitability.
-The more ``good'' changes you contribute to a maintainer, the more
-likely they are to trust your judgment and accept your changes.  If
-you're well-known and maintain a long-lived branch for something Linus
-hasn't yet accepted, people with similar interests may pull your
-changes regularly to keep up with your work.
-
-Reputation and acclaim don't necessarily cross subsystem or ``people''
-boundaries.  If you're a respected but specialised storage hacker, and
-you try to fix a networking bug, that change will receive a level of
-scrutiny from a network maintainer comparable to a change from a
-complete stranger.
-
-To people who come from more orderly project backgrounds, the
-comparatively chaotic Linux kernel development process often seems
-completely insane.  It's subject to the whims of individuals; people
-make sweeping changes whenever they deem it appropriate; and the pace
-of development is astounding.  And yet Linux is a highly successful,
-well-regarded piece of software.
-
-\subsection{Pull-only versus shared-push collaboration}
-
-A perpetual source of heat in the open source community is whether a
-development model in which people only ever pull changes from others
-is ``better than'' one in which multiple people can push changes to a
-shared repository.
-
-Typically, the backers of the shared-push model use tools that
-actively enforce this approach.  If you're using a centralised
-revision control tool such as Subversion, there's no way to make a
-choice over which model you'll use: the tool gives you shared-push,
-and if you want to do anything else, you'll have to roll your own
-approach on top (such as applying a patch by hand).
-
-A good distributed revision control tool, such as Mercurial, will
-support both models.  You and your collaborators can then structure
-how you work together based on your own needs and preferences, not on
-what contortions your tools force you into.
-
-\subsection{Where collaboration meets branch management}
-
-Once you and your team set up some shared repositories and start
-propagating changes back and forth between local and shared repos, you
-begin to face a related, but slightly different challenge: that of
-managing the multiple directions in which your team may be moving at
-once.  Even though this subject is intimately related to how your team
-collaborates, it's dense enough to merit treatment of its own, in
-chapter~\ref{chap:branch}.
-
-\section{The technical side of sharing}
-
-The remainder of this chapter is devoted to the question of serving
-data to your collaborators.
-
-\section{Informal sharing with \hgcmd{serve}}
-\label{sec:collab:serve}
-
-Mercurial's \hgcmd{serve} command is wonderfully suited to small,
-tight-knit, and fast-paced group environments.  It also provides a
-great way to get a feel for using Mercurial commands over a network.
-
-Run \hgcmd{serve} inside a repository, and in under a second it will
-bring up a specialised HTTP server; this will accept connections from
-any client, and serve up data for that repository until you terminate
-it.  Anyone who knows the URL of the server you just started, and can
-talk to your computer over the network, can then use a web browser or
-Mercurial to read data from that repository.  A URL for a
-\hgcmd{serve} instance running on a laptop is likely to look something
-like \Verb|http://my-laptop.local:8000/|.
-
-The \hgcmd{serve} command is \emph{not} a general-purpose web server.
-It can do only two things:
-\begin{itemize}
-\item Allow people to browse the history of the repository it's
-  serving, from their normal web browsers.
-\item Speak Mercurial's wire protocol, so that people can
-  \hgcmd{clone} or \hgcmd{pull} changes from that repository.
-\end{itemize}
-In particular, \hgcmd{serve} won't allow remote users to \emph{modify}
-your repository.  It's intended for read-only use.
-
-If you're getting started with Mercurial, there's nothing to prevent
-you from using \hgcmd{serve} to serve up a repository on your own
-computer, then use commands like \hgcmd{clone}, \hgcmd{incoming}, and
-so on to talk to that server as if the repository was hosted remotely.
-This can help you to quickly get acquainted with using commands on
-network-hosted repositories.
-
-\subsection{A few things to keep in mind}
-
-Because it provides unauthenticated read access to all clients, you
-should only use \hgcmd{serve} in an environment where you either don't
-care, or have complete control over, who can access your network and
-pull data from your repository.
-
-The \hgcmd{serve} command knows nothing about any firewall software
-you might have installed on your system or network.  It cannot detect
-or control your firewall software.  If other people are unable to talk
-to a running \hgcmd{serve} instance, the second thing you should do
-(\emph{after} you make sure that they're using the correct URL) is
-check your firewall configuration.
-
-By default, \hgcmd{serve} listens for incoming connections on
-port~8000.  If another process is already listening on the port you
-want to use, you can specify a different port to listen on using the
-\hgopt{serve}{-p} option.
-
-Normally, when \hgcmd{serve} starts, it prints no output, which can be
-a bit unnerving.  If you'd like to confirm that it is indeed running
-correctly, and find out what URL you should send to your
-collaborators, start it with the \hggopt{-v} option.
-
-\section{Using the Secure Shell (ssh) protocol}
-\label{sec:collab:ssh}
-
-You can pull and push changes securely over a network connection using
-the Secure Shell (\texttt{ssh}) protocol.  To use this successfully,
-you may have to do a little bit of configuration on the client or
-server sides.
-
-If you're not familiar with ssh, it's a network protocol that lets you
-securely communicate with another computer.  To use it with Mercurial,
-you'll be setting up one or more user accounts on a server so that
-remote users can log in and execute commands.
-
-(If you \emph{are} familiar with ssh, you'll probably find some of the
-material that follows to be elementary in nature.)
-
-\subsection{How to read and write ssh URLs}
-
-An ssh URL tends to look like this:
-\begin{codesample2}
-  ssh://bos@hg.serpentine.com:22/hg/hgbook
-\end{codesample2}
-\begin{enumerate}
-\item The ``\texttt{ssh://}'' part tells Mercurial to use the ssh
-  protocol.
-\item The ``\texttt{bos@}'' component indicates what username to log
-  into the server as.  You can leave this out if the remote username
-  is the same as your local username.
-\item The ``\texttt{hg.serpentine.com}'' gives the hostname of the
-  server to log into.
-\item The ``:22'' identifies the port number to connect to the server
-  on.  The default port is~22, so you only need to specify this part
-  if you're \emph{not} using port~22.
-\item The remainder of the URL is the local path to the repository on
-  the server.
-\end{enumerate}
-
-There's plenty of scope for confusion with the path component of ssh
-URLs, as there is no standard way for tools to interpret it.  Some
-programs behave differently than others when dealing with these paths.
-This isn't an ideal situation, but it's unlikely to change.  Please
-read the following paragraphs carefully.
-
-Mercurial treats the path to a repository on the server as relative to
-the remote user's home directory.  For example, if user \texttt{foo}
-on the server has a home directory of \dirname{/home/foo}, then an ssh
-URL that contains a path component of \dirname{bar}
-\emph{really} refers to the directory \dirname{/home/foo/bar}.
-
-If you want to specify a path relative to another user's home
-directory, you can use a path that starts with a tilde character
-followed by the user's name (let's call them \texttt{otheruser}), like
-this.
-\begin{codesample2}
-  ssh://server/~otheruser/hg/repo
-\end{codesample2}
-
-And if you really want to specify an \emph{absolute} path on the
-server, begin the path component with two slashes, as in this example.
-\begin{codesample2}
-  ssh://server//absolute/path
-\end{codesample2}
-
-\subsection{Finding an ssh client for your system}
-
-Almost every Unix-like system comes with OpenSSH preinstalled.  If
-you're using such a system, run \Verb|which ssh| to find out if
-the \command{ssh} command is installed (it's usually in
-\dirname{/usr/bin}).  In the unlikely event that it isn't present,
-take a look at your system documentation to figure out how to install
-it.
-
-On Windows, you'll first need to download a suitable ssh
-client.  There are two alternatives.
-\begin{itemize}
-\item Simon Tatham's excellent PuTTY package~\cite{web:putty} provides
-  a complete suite of ssh client commands.
-\item If you have a high tolerance for pain, you can use the Cygwin
-  port of OpenSSH.
-\end{itemize}
-In either case, you'll need to edit your \hgini\ file to tell
-Mercurial where to find the actual client command.  For example, if
-you're using PuTTY, you'll need to use the \command{plink} command as
-a command-line ssh client.
-\begin{codesample2}
-  [ui]
-  ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key"
-\end{codesample2}
-
-\begin{note}
-  The path to \command{plink} shouldn't contain any whitespace
-  characters, or Mercurial may not be able to run it correctly (so
-  putting it in \dirname{C:\\Program Files} is probably not a good
-  idea).
-\end{note}
-
-\subsection{Generating a key pair}
-
-To avoid the need to repetitively type a password every time you need
-to use your ssh client, I recommend generating a key pair.  On a
-Unix-like system, the \command{ssh-keygen} command will do the trick.
-On Windows, if you're using PuTTY, the \command{puttygen} command is
-what you'll need.
-
-When you generate a key pair, it's usually \emph{highly} advisable to
-protect it with a passphrase.  (The only time that you might not want
-to do this is when you're using the ssh protocol for automated tasks
-on a secure network.)
-
-Simply generating a key pair isn't enough, however.  You'll need to
-add the public key to the set of authorised keys for whatever user
-you're logging in remotely as.  For servers using OpenSSH (the vast
-majority), this will mean adding the public key to a list in a file
-called \sfilename{authorized\_keys} in their \sdirname{.ssh}
-directory.
-
-On a Unix-like system, your public key will have a \filename{.pub}
-extension.  If you're using \command{puttygen} on Windows, you can
-save the public key to a file of your choosing, or paste it from the
-window it's displayed in straight into the
-\sfilename{authorized\_keys} file.
-
-\subsection{Using an authentication agent}
-
-An authentication agent is a daemon that stores passphrases in memory
-(so it will forget passphrases if you log out and log back in again).
-An ssh client will notice if it's running, and query it for a
-passphrase.  If there's no authentication agent running, or the agent
-doesn't store the necessary passphrase, you'll have to type your
-passphrase every time Mercurial tries to communicate with a server on
-your behalf (e.g.~whenever you pull or push changes).
-
-The downside of storing passphrases in an agent is that it's possible
-for a well-prepared attacker to recover the plain text of your
-passphrases, in some cases even if your system has been power-cycled.
-You should make your own judgment as to whether this is an acceptable
-risk.  It certainly saves a lot of repeated typing.
-
-On Unix-like systems, the agent is called \command{ssh-agent}, and
-it's often run automatically for you when you log in.  You'll need to
-use the \command{ssh-add} command to add passphrases to the agent's
-store.  On Windows, if you're using PuTTY, the \command{pageant}
-command acts as the agent.  It adds an icon to your system tray that
-will let you manage stored passphrases.
-
-\subsection{Configuring the server side properly}
-
-Because ssh can be fiddly to set up if you're new to it, there's a
-variety of things that can go wrong.  Add Mercurial on top, and
-there's plenty more scope for head-scratching.  Most of these
-potential problems occur on the server side, not the client side.  The
-good news is that once you've gotten a configuration working, it will
-usually continue to work indefinitely.
-
-Before you try using Mercurial to talk to an ssh server, it's best to
-make sure that you can use the normal \command{ssh} or \command{putty}
-command to talk to the server first.  If you run into problems with
-using these commands directly, Mercurial surely won't work.  Worse, it
-will obscure the underlying problem.  Any time you want to debug
-ssh-related Mercurial problems, you should drop back to making sure
-that plain ssh client commands work first, \emph{before} you worry
-about whether there's a problem with Mercurial.
-
-The first thing to be sure of on the server side is that you can
-actually log in from another machine at all.  If you can't use
-\command{ssh} or \command{putty} to log in, the error message you get
-may give you a few hints as to what's wrong.  The most common problems
-are as follows.
-\begin{itemize}
-\item If you get a ``connection refused'' error, either there isn't an
-  SSH daemon running on the server at all, or it's inaccessible due to
-  firewall configuration.
-\item If you get a ``no route to host'' error, you either have an
-  incorrect address for the server or a seriously locked down firewall
-  that won't admit its existence at all.
-\item If you get a ``permission denied'' error, you may have mistyped
-  the username on the server, or you could have mistyped your key's
-  passphrase or the remote user's password.
-\end{itemize}
-In summary, if you're having trouble talking to the server's ssh
-daemon, first make sure that one is running at all.  On many systems
-it will be installed, but disabled, by default.  Once you're done with
-this step, you should then check that the server's firewall is
-configured to allow incoming connections on the port the ssh daemon is
-listening on (usually~22).  Don't worry about more exotic
-possibilities for misconfiguration until you've checked these two
-first.
-
-If you're using an authentication agent on the client side to store
-passphrases for your keys, you ought to be able to log into the server
-without being prompted for a passphrase or a password.  If you're
-prompted for a passphrase, there are a few possible culprits.
-\begin{itemize}
-\item You might have forgotten to use \command{ssh-add} or
-  \command{pageant} to store the passphrase.
-\item You might have stored the passphrase for the wrong key.
-\end{itemize}
-If you're being prompted for the remote user's password, there are
-another few possible problems to check.
-\begin{itemize}
-\item Either the user's home directory or their \sdirname{.ssh}
-  directory might have excessively liberal permissions.  As a result,
-  the ssh daemon will not trust or read their
-  \sfilename{authorized\_keys} file.  For example, a group-writable
-  home or \sdirname{.ssh} directory will often cause this symptom.
-\item The user's \sfilename{authorized\_keys} file may have a problem.
-  If anyone other than the user owns or can write to that file, the
-  ssh daemon will not trust or read it.
-\end{itemize}
-
-In the ideal world, you should be able to run the following command
-successfully, and it should print exactly one line of output, the
-current date and time.
-\begin{codesample2}
-  ssh myserver date
-\end{codesample2}
-
-If, on your server, you have login scripts that print banners or other
-junk even when running non-interactive commands like this, you should
-fix them before you continue, so that they only print output if
-they're run interactively.  Otherwise these banners will at least
-clutter up Mercurial's output.  Worse, they could potentially cause
-problems with running Mercurial commands remotely.  Mercurial makes
-tries to detect and ignore banners in non-interactive \command{ssh}
-sessions, but it is not foolproof.  (If you're editing your login
-scripts on your server, the usual way to see if a login script is
-running in an interactive shell is to check the return code from the
-command \Verb|tty -s|.)
-
-Once you've verified that plain old ssh is working with your server,
-the next step is to ensure that Mercurial runs on the server.  The
-following command should run successfully:
-\begin{codesample2}
-  ssh myserver hg version
-\end{codesample2}
-If you see an error message instead of normal \hgcmd{version} output,
-this is usually because you haven't installed Mercurial to
-\dirname{/usr/bin}.  Don't worry if this is the case; you don't need
-to do that.  But you should check for a few possible problems.
-\begin{itemize}
-\item Is Mercurial really installed on the server at all?  I know this
-  sounds trivial, but it's worth checking!
-\item Maybe your shell's search path (usually set via the \envar{PATH}
-  environment variable) is simply misconfigured.
-\item Perhaps your \envar{PATH} environment variable is only being set
-  to point to the location of the \command{hg} executable if the login
-  session is interactive.  This can happen if you're setting the path
-  in the wrong shell login script.  See your shell's documentation for
-  details.
-\item The \envar{PYTHONPATH} environment variable may need to contain
-  the path to the Mercurial Python modules.  It might not be set at
-  all; it could be incorrect; or it may be set only if the login is
-  interactive.
-\end{itemize}
-
-If you can run \hgcmd{version} over an ssh connection, well done!
-You've got the server and client sorted out.  You should now be able
-to use Mercurial to access repositories hosted by that username on
-that server.  If you run into problems with Mercurial and ssh at this
-point, try using the \hggopt{--debug} option to get a clearer picture
-of what's going on.
-
-\subsection{Using compression with ssh}
-
-Mercurial does not compress data when it uses the ssh protocol,
-because the ssh protocol can transparently compress data.  However,
-the default behaviour of ssh clients is \emph{not} to request
-compression.
-
-Over any network other than a fast LAN (even a wireless network),
-using compression is likely to significantly speed up Mercurial's
-network operations.  For example, over a WAN, someone measured
-compression as reducing the amount of time required to clone a
-particularly large repository from~51 minutes to~17 minutes.
-
-Both \command{ssh} and \command{plink} accept a \cmdopt{ssh}{-C}
-option which turns on compression.  You can easily edit your \hgrc\ to
-enable compression for all of Mercurial's uses of the ssh protocol.
-\begin{codesample2}
-  [ui]
-  ssh = ssh -C
-\end{codesample2}
-
-If you use \command{ssh}, you can configure it to always use
-compression when talking to your server.  To do this, edit your
-\sfilename{.ssh/config} file (which may not yet exist), as follows.
-\begin{codesample2}
-  Host hg
-    Compression yes
-    HostName hg.example.com
-\end{codesample2}
-This defines an alias, \texttt{hg}.  When you use it on the
-\command{ssh} command line or in a Mercurial \texttt{ssh}-protocol
-URL, it will cause \command{ssh} to connect to \texttt{hg.example.com}
-and use compression.  This gives you both a shorter name to type and
-compression, each of which is a good thing in its own right.
-
-\section{Serving over HTTP using CGI}
-\label{sec:collab:cgi}
-
-Depending on how ambitious you are, configuring Mercurial's CGI
-interface can take anything from a few moments to several hours.
-
-We'll begin with the simplest of examples, and work our way towards a
-more complex configuration.  Even for the most basic case, you're
-almost certainly going to need to read and modify your web server's
-configuration.
-
-\begin{note}
-  Configuring a web server is a complex, fiddly, and highly
-  system-dependent activity.  I can't possibly give you instructions
-  that will cover anything like all of the cases you will encounter.
-  Please use your discretion and judgment in following the sections
-  below.  Be prepared to make plenty of mistakes, and to spend a lot
-  of time reading your server's error logs.
-\end{note}
-
-\subsection{Web server configuration checklist}
-
-Before you continue, do take a few moments to check a few aspects of
-your system's setup.
-
-\begin{enumerate}
-\item Do you have a web server installed at all?  Mac OS X ships with
-  Apache, but many other systems may not have a web server installed.
-\item If you have a web server installed, is it actually running?  On
-  most systems, even if one is present, it will be disabled by
-  default.
-\item Is your server configured to allow you to run CGI programs in
-  the directory where you plan to do so?  Most servers default to
-  explicitly disabling the ability to run CGI programs.
-\end{enumerate}
-
-If you don't have a web server installed, and don't have substantial
-experience configuring Apache, you should consider using the
-\texttt{lighttpd} web server instead of Apache.  Apache has a
-well-deserved reputation for baroque and confusing configuration.
-While \texttt{lighttpd} is less capable in some ways than Apache, most
-of these capabilities are not relevant to serving Mercurial
-repositories.  And \texttt{lighttpd} is undeniably \emph{much} easier
-to get started with than Apache.
-
-\subsection{Basic CGI configuration}
-
-On Unix-like systems, it's common for users to have a subdirectory
-named something like \dirname{public\_html} in their home directory,
-from which they can serve up web pages.  A file named \filename{foo}
-in this directory will be accessible at a URL of the form
-\texttt{http://www.example.com/\~{}username/foo}.
-
-To get started, find the \sfilename{hgweb.cgi} script that should be
-present in your Mercurial installation.  If you can't quickly find a
-local copy on your system, simply download one from the master
-Mercurial repository at
-\url{http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi}.
-
-You'll need to copy this script into your \dirname{public\_html}
-directory, and ensure that it's executable.
-\begin{codesample2}
-  cp .../hgweb.cgi ~/public_html
-  chmod 755 ~/public_html/hgweb.cgi
-\end{codesample2}
-The \texttt{755} argument to \command{chmod} is a little more general
-than just making the script executable: it ensures that the script is
-executable by anyone, and that ``group'' and ``other'' write
-permissions are \emph{not} set.  If you were to leave those write
-permissions enabled, Apache's \texttt{suexec} subsystem would likely
-refuse to execute the script.  In fact, \texttt{suexec} also insists
-that the \emph{directory} in which the script resides must not be
-writable by others.
-\begin{codesample2}
-  chmod 755 ~/public_html
-\end{codesample2}
-
-\subsubsection{What could \emph{possibly} go wrong?}
-\label{sec:collab:wtf}
-
-Once you've copied the CGI script into place, go into a web browser,
-and try to open the URL \url{http://myhostname/~myuser/hgweb.cgi},
-\emph{but} brace yourself for instant failure.  There's a high
-probability that trying to visit this URL will fail, and there are
-many possible reasons for this.  In fact, you're likely to stumble
-over almost every one of the possible errors below, so please read
-carefully.  The following are all of the problems I ran into on a
-system running Fedora~7, with a fresh installation of Apache, and a
-user account that I created specially to perform this exercise.
-
-Your web server may have per-user directories disabled.  If you're
-using Apache, search your config file for a \texttt{UserDir}
-directive.  If there's none present, per-user directories will be
-disabled.  If one exists, but its value is \texttt{disabled}, then
-per-user directories will be disabled.  Otherwise, the string after
-\texttt{UserDir} gives the name of the subdirectory that Apache will
-look in under your home directory, for example \dirname{public\_html}.
-
-Your file access permissions may be too restrictive.  The web server
-must be able to traverse your home directory and directories under
-your \dirname{public\_html} directory, and read files under the latter
-too.  Here's a quick recipe to help you to make your permissions more
-appropriate.
-\begin{codesample2}
-  chmod 755 ~
-  find ~/public_html -type d -print0 | xargs -0r chmod 755
-  find ~/public_html -type f -print0 | xargs -0r chmod 644
-\end{codesample2}
-
-The other possibility with permissions is that you might get a
-completely empty window when you try to load the script.  In this
-case, it's likely that your access permissions are \emph{too
-  permissive}.  Apache's \texttt{suexec} subsystem won't execute a
-script that's group-~or world-writable, for example.
-
-Your web server may be configured to disallow execution of CGI
-programs in your per-user web directory.  Here's Apache's
-default per-user configuration from my Fedora system.
-\begin{codesample2}
-  <Directory /home/*/public_html>
-      AllowOverride FileInfo AuthConfig Limit
-      Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
-      <Limit GET POST OPTIONS>
-          Order allow,deny
-          Allow from all
-      </Limit>
-      <LimitExcept GET POST OPTIONS>
-          Order deny,allow
-          Deny from all
-      </LimitExcept>
-  </Directory>
-\end{codesample2}
-If you find a similar-looking \texttt{Directory} group in your Apache
-configuration, the directive to look at inside it is \texttt{Options}.
-Add \texttt{ExecCGI} to the end of this list if it's missing, and
-restart the web server.
-
-If you find that Apache serves you the text of the CGI script instead
-of executing it, you may need to either uncomment (if already present)
-or add a directive like this.
-\begin{codesample2}
-  AddHandler cgi-script .cgi
-\end{codesample2}
-
-The next possibility is that you might be served with a colourful
-Python backtrace claiming that it can't import a
-\texttt{mercurial}-related module.  This is actually progress!  The
-server is now capable of executing your CGI script.  This error is
-only likely to occur if you're running a private installation of
-Mercurial, instead of a system-wide version.  Remember that the web
-server runs the CGI program without any of the environment variables
-that you take for granted in an interactive session.  If this error
-happens to you, edit your copy of \sfilename{hgweb.cgi} and follow the
-directions inside it to correctly set your \envar{PYTHONPATH}
-environment variable.
-
-Finally, you are \emph{certain} to by served with another colourful
-Python backtrace: this one will complain that it can't find
-\dirname{/path/to/repository}.  Edit your \sfilename{hgweb.cgi} script
-and replace the \dirname{/path/to/repository} string with the complete
-path to the repository you want to serve up.
-
-At this point, when you try to reload the page, you should be
-presented with a nice HTML view of your repository's history.  Whew!
-
-\subsubsection{Configuring lighttpd}
-
-To be exhaustive in my experiments, I tried configuring the
-increasingly popular \texttt{lighttpd} web server to serve the same
-repository as I described with Apache above.  I had already overcome
-all of the problems I outlined with Apache, many of which are not
-server-specific.  As a result, I was fairly sure that my file and
-directory permissions were good, and that my \sfilename{hgweb.cgi}
-script was properly edited.
-
-Once I had Apache running, getting \texttt{lighttpd} to serve the
-repository was a snap (in other words, even if you're trying to use
-\texttt{lighttpd}, you should read the Apache section).  I first had
-to edit the \texttt{mod\_access} section of its config file to enable
-\texttt{mod\_cgi} and \texttt{mod\_userdir}, both of which were
-disabled by default on my system.  I then added a few lines to the end
-of the config file, to configure these modules.
-\begin{codesample2}
-  userdir.path = "public_html"
-  cgi.assign = ( ".cgi" => "" )
-\end{codesample2}
-With this done, \texttt{lighttpd} ran immediately for me.  If I had
-configured \texttt{lighttpd} before Apache, I'd almost certainly have
-run into many of the same system-level configuration problems as I did
-with Apache.  However, I found \texttt{lighttpd} to be noticeably
-easier to configure than Apache, even though I've used Apache for over
-a decade, and this was my first exposure to \texttt{lighttpd}.
-
-\subsection{Sharing multiple repositories with one CGI script}
-
-The \sfilename{hgweb.cgi} script only lets you publish a single
-repository, which is an annoying restriction.  If you want to publish
-more than one without wracking yourself with multiple copies of the
-same script, each with different names, a better choice is to use the
-\sfilename{hgwebdir.cgi} script.
-
-The procedure to configure \sfilename{hgwebdir.cgi} is only a little
-more involved than for \sfilename{hgweb.cgi}.  First, you must obtain
-a copy of the script.  If you don't have one handy, you can download a
-copy from the master Mercurial repository at
-\url{http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi}.
-
-You'll need to copy this script into your \dirname{public\_html}
-directory, and ensure that it's executable.
-\begin{codesample2}
-  cp .../hgwebdir.cgi ~/public_html
-  chmod 755 ~/public_html ~/public_html/hgwebdir.cgi
-\end{codesample2}
-With basic configuration out of the way, try to visit
-\url{http://myhostname/~myuser/hgwebdir.cgi} in your browser.  It
-should display an empty list of repositories.  If you get a blank
-window or error message, try walking through the list of potential
-problems in section~\ref{sec:collab:wtf}.
-
-The \sfilename{hgwebdir.cgi} script relies on an external
-configuration file.  By default, it searches for a file named
-\sfilename{hgweb.config} in the same directory as itself.  You'll need
-to create this file, and make it world-readable.  The format of the
-file is similar to a Windows ``ini'' file, as understood by Python's
-\texttt{ConfigParser}~\cite{web:configparser} module.
-
-The easiest way to configure \sfilename{hgwebdir.cgi} is with a
-section named \texttt{collections}.  This will automatically publish
-\emph{every} repository under the directories you name.  The section
-should look like this:
-\begin{codesample2}
-  [collections]
-  /my/root = /my/root
-\end{codesample2}
-Mercurial interprets this by looking at the directory name on the
-\emph{right} hand side of the ``\texttt{=}'' sign; finding
-repositories in that directory hierarchy; and using the text on the
-\emph{left} to strip off matching text from the names it will actually
-list in the web interface.  The remaining component of a path after
-this stripping has occurred is called a ``virtual path''.
-
-Given the example above, if we have a repository whose local path is
-\dirname{/my/root/this/repo}, the CGI script will strip the leading
-\dirname{/my/root} from the name, and publish the repository with a
-virtual path of \dirname{this/repo}.  If the base URL for our CGI
-script is \url{http://myhostname/~myuser/hgwebdir.cgi}, the complete
-URL for that repository will be
-\url{http://myhostname/~myuser/hgwebdir.cgi/this/repo}.
-
-If we replace \dirname{/my/root} on the left hand side of this example
-with \dirname{/my}, then \sfilename{hgwebdir.cgi} will only strip off
-\dirname{/my} from the repository name, and will give us a virtual
-path of \dirname{root/this/repo} instead of \dirname{this/repo}.
-
-The \sfilename{hgwebdir.cgi} script will recursively search each
-directory listed in the \texttt{collections} section of its
-configuration file, but it will \texttt{not} recurse into the
-repositories it finds.
-
-The \texttt{collections} mechanism makes it easy to publish many
-repositories in a ``fire and forget'' manner.  You only need to set up
-the CGI script and configuration file one time.  Afterwards, you can
-publish or unpublish a repository at any time by simply moving it
-into, or out of, the directory hierarchy in which you've configured
-\sfilename{hgwebdir.cgi} to look.
-
-\subsubsection{Explicitly specifying which repositories to publish}
-
-In addition to the \texttt{collections} mechanism, the
-\sfilename{hgwebdir.cgi} script allows you to publish a specific list
-of repositories.  To do so, create a \texttt{paths} section, with
-contents of the following form.
-\begin{codesample2}
-  [paths]
-  repo1 = /my/path/to/some/repo
-  repo2 = /some/path/to/another
-\end{codesample2}
-In this case, the virtual path (the component that will appear in a
-URL) is on the left hand side of each definition, while the path to
-the repository is on the right.  Notice that there does not need to be
-any relationship between the virtual path you choose and the location
-of a repository in your filesystem.
-
-If you wish, you can use both the \texttt{collections} and
-\texttt{paths} mechanisms simultaneously in a single configuration
-file.
-
-\begin{note}
-  If multiple repositories have the same virtual path,
-  \sfilename{hgwebdir.cgi} will not report an error.  Instead, it will
-  behave unpredictably.
-\end{note}
-
-\subsection{Downloading source archives}
-
-Mercurial's web interface lets users download an archive of any
-revision.  This archive will contain a snapshot of the working
-directory as of that revision, but it will not contain a copy of the
-repository data.
-
-By default, this feature is not enabled.  To enable it, you'll need to
-add an \rcitem{web}{allow\_archive} item to the \rcsection{web}
-section of your \hgrc.
-
-\subsection{Web configuration options}
-
-Mercurial's web interfaces (the \hgcmd{serve} command, and the
-\sfilename{hgweb.cgi} and \sfilename{hgwebdir.cgi} scripts) have a
-number of configuration options that you can set.  These belong in a
-section named \rcsection{web}.
-\begin{itemize}
-\item[\rcitem{web}{allow\_archive}] Determines which (if any) archive
-  download mechanisms Mercurial supports.  If you enable this
-  feature, users of the web interface will be able to download an
-  archive of whatever revision of a repository they are viewing.
-  To enable the archive feature, this item must take the form of a
-  sequence of words drawn from the list below.
-  \begin{itemize}
-  \item[\texttt{bz2}] A \command{tar} archive, compressed using
-    \texttt{bzip2} compression.  This has the best compression ratio,
-    but uses the most CPU time on the server.
-  \item[\texttt{gz}] A \command{tar} archive, compressed using
-    \texttt{gzip} compression.
-  \item[\texttt{zip}] A \command{zip} archive, compressed using LZW
-    compression.  This format has the worst compression ratio, but is
-    widely used in the Windows world.
-  \end{itemize}
-  If you provide an empty list, or don't have an
-  \rcitem{web}{allow\_archive} entry at all, this feature will be
-  disabled.  Here is an example of how to enable all three supported
-  formats.
-  \begin{codesample4}
-    [web]
-    allow_archive = bz2 gz zip
-  \end{codesample4}
-\item[\rcitem{web}{allowpull}] Boolean.  Determines whether the web
-  interface allows remote users to \hgcmd{pull} and \hgcmd{clone} this
-  repository over~HTTP.  If set to \texttt{no} or \texttt{false}, only
-  the ``human-oriented'' portion of the web interface is available.
-\item[\rcitem{web}{contact}] String.  A free-form (but preferably
-  brief) string identifying the person or group in charge of the
-  repository.  This often contains the name and email address of a
-  person or mailing list.  It often makes sense to place this entry in
-  a repository's own \sfilename{.hg/hgrc} file, but it can make sense
-  to use in a global \hgrc\ if every repository has a single
-  maintainer.
-\item[\rcitem{web}{maxchanges}] Integer.  The default maximum number
-  of changesets to display in a single page of output.
-\item[\rcitem{web}{maxfiles}] Integer.  The default maximum number
-  of modified files to display in a single page of output.
-\item[\rcitem{web}{stripes}] Integer.  If the web interface displays
-  alternating ``stripes'' to make it easier to visually align rows
-  when you are looking at a table, this number controls the number of
-  rows in each stripe.
-\item[\rcitem{web}{style}] Controls the template Mercurial uses to
-  display the web interface.  Mercurial ships with two web templates,
-  named \texttt{default} and \texttt{gitweb} (the latter is much more
-  visually attractive).  You can also specify a custom template of
-  your own; see chapter~\ref{chap:template} for details.  Here, you
-  can see how to enable the \texttt{gitweb} style.
-  \begin{codesample4}
-    [web]
-    style = gitweb
-  \end{codesample4}
-\item[\rcitem{web}{templates}] Path.  The directory in which to search
-  for template files.  By default, Mercurial searches in the directory
-  in which it was installed.
-\end{itemize}
-If you are using \sfilename{hgwebdir.cgi}, you can place a few
-configuration items in a \rcsection{web} section of the
-\sfilename{hgweb.config} file instead of a \hgrc\ file, for
-convenience.  These items are \rcitem{web}{motd} and
-\rcitem{web}{style}.
-
-\subsubsection{Options specific to an individual repository}
-
-A few \rcsection{web} configuration items ought to be placed in a
-repository's local \sfilename{.hg/hgrc}, rather than a user's or
-global \hgrc.
-\begin{itemize}
-\item[\rcitem{web}{description}] String.  A free-form (but preferably
-  brief) string that describes the contents or purpose of the
-  repository.
-\item[\rcitem{web}{name}] String.  The name to use for the repository
-  in the web interface.  This overrides the default name, which is the
-  last component of the repository's path.
-\end{itemize}
-
-\subsubsection{Options specific to the \hgcmd{serve} command}
-
-Some of the items in the \rcsection{web} section of a \hgrc\ file are
-only for use with the \hgcmd{serve} command.
-\begin{itemize}
-\item[\rcitem{web}{accesslog}] Path.  The name of a file into which to
-  write an access log.  By default, the \hgcmd{serve} command writes
-  this information to standard output, not to a file.  Log entries are
-  written in the standard ``combined'' file format used by almost all
-  web servers.
-\item[\rcitem{web}{address}] String.  The local address on which the
-  server should listen for incoming connections.  By default, the
-  server listens on all addresses.
-\item[\rcitem{web}{errorlog}] Path.  The name of a file into which to
-  write an error log.  By default, the \hgcmd{serve} command writes this
-  information to standard error, not to a file.
-\item[\rcitem{web}{ipv6}] Boolean.  Whether to use the IPv6 protocol.
-  By default, IPv6 is not used. 
-\item[\rcitem{web}{port}] Integer.  The TCP~port number on which the
-  server should listen.  The default port number used is~8000.
-\end{itemize}
-
-\subsubsection{Choosing the right \hgrc\ file to add \rcsection{web}
-  items to}
-
-It is important to remember that a web server like Apache or
-\texttt{lighttpd} will run under a user~ID that is different to yours.
-CGI scripts run by your server, such as \sfilename{hgweb.cgi}, will
-usually also run under that user~ID.
-
-If you add \rcsection{web} items to your own personal \hgrc\ file, CGI
-scripts won't read that \hgrc\ file.  Those settings will thus only
-affect the behaviour of the \hgcmd{serve} command when you run it.  To
-cause CGI scripts to see your settings, either create a \hgrc\ file in
-the home directory of the user ID that runs your web server, or add
-those settings to a system-wide \hgrc\ file.
-
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/concepts.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,577 +0,0 @@
-\chapter{Behind the scenes}
-\label{chap:concepts}
-
-Unlike many revision control systems, the concepts upon which
-Mercurial is built are simple enough that it's easy to understand how
-the software really works.  Knowing this certainly isn't necessary,
-but I find it useful to have a ``mental model'' of what's going on.
-
-This understanding gives me confidence that Mercurial has been
-carefully designed to be both \emph{safe} and \emph{efficient}.  And
-just as importantly, if it's easy for me to retain a good idea of what
-the software is doing when I perform a revision control task, I'm less
-likely to be surprised by its behaviour.
-
-In this chapter, we'll initially cover the core concepts behind
-Mercurial's design, then continue to discuss some of the interesting
-details of its implementation.
-
-\section{Mercurial's historical record}
-
-\subsection{Tracking the history of a single file}
-
-When Mercurial tracks modifications to a file, it stores the history
-of that file in a metadata object called a \emph{filelog}.  Each entry
-in the filelog contains enough information to reconstruct one revision
-of the file that is being tracked.  Filelogs are stored as files in
-the \sdirname{.hg/store/data} directory.  A filelog contains two kinds
-of information: revision data, and an index to help Mercurial to find
-a revision efficiently.
-
-A file that is large, or has a lot of history, has its filelog stored
-in separate data (``\texttt{.d}'' suffix) and index (``\texttt{.i}''
-suffix) files.  For small files without much history, the revision
-data and index are combined in a single ``\texttt{.i}'' file.  The
-correspondence between a file in the working directory and the filelog
-that tracks its history in the repository is illustrated in
-figure~\ref{fig:concepts:filelog}.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{filelog}
-  \caption{Relationships between files in working directory and
-    filelogs in repository}
-  \label{fig:concepts:filelog}
-\end{figure}
-
-\subsection{Managing tracked files}
-
-Mercurial uses a structure called a \emph{manifest} to collect
-together information about the files that it tracks.  Each entry in
-the manifest contains information about the files present in a single
-changeset.  An entry records which files are present in the changeset,
-the revision of each file, and a few other pieces of file metadata.
-
-\subsection{Recording changeset information}
-
-The \emph{changelog} contains information about each changeset.  Each
-revision records who committed a change, the changeset comment, other
-pieces of changeset-related information, and the revision of the
-manifest to use.
-
-\subsection{Relationships between revisions}
-
-Within a changelog, a manifest, or a filelog, each revision stores a
-pointer to its immediate parent (or to its two parents, if it's a
-merge revision).  As I mentioned above, there are also relationships
-between revisions \emph{across} these structures, and they are
-hierarchical in nature.
-
-For every changeset in a repository, there is exactly one revision
-stored in the changelog.  Each revision of the changelog contains a
-pointer to a single revision of the manifest.  A revision of the
-manifest stores a pointer to a single revision of each filelog tracked
-when that changeset was created.  These relationships are illustrated
-in figure~\ref{fig:concepts:metadata}.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{metadata}
-  \caption{Metadata relationships}
-  \label{fig:concepts:metadata}
-\end{figure}
-
-As the illustration shows, there is \emph{not} a ``one to one''
-relationship between revisions in the changelog, manifest, or filelog.
-If the manifest hasn't changed between two changesets, the changelog
-entries for those changesets will point to the same revision of the
-manifest.  If a file that Mercurial tracks hasn't changed between two
-changesets, the entry for that file in the two revisions of the
-manifest will point to the same revision of its filelog.
-
-\section{Safe, efficient storage}
-
-The underpinnings of changelogs, manifests, and filelogs are provided
-by a single structure called the \emph{revlog}.
-
-\subsection{Efficient storage}
-
-The revlog provides efficient storage of revisions using a
-\emph{delta} mechanism.  Instead of storing a complete copy of a file
-for each revision, it stores the changes needed to transform an older
-revision into the new revision.  For many kinds of file data, these
-deltas are typically a fraction of a percent of the size of a full
-copy of a file.
-
-Some obsolete revision control systems can only work with deltas of
-text files.  They must either store binary files as complete snapshots
-or encoded into a text representation, both of which are wasteful
-approaches.  Mercurial can efficiently handle deltas of files with
-arbitrary binary contents; it doesn't need to treat text as special.
-
-\subsection{Safe operation}
-\label{sec:concepts:txn}
-
-Mercurial only ever \emph{appends} data to the end of a revlog file.
-It never modifies a section of a file after it has written it.  This
-is both more robust and efficient than schemes that need to modify or
-rewrite data.
-
-In addition, Mercurial treats every write as part of a
-\emph{transaction} that can span a number of files.  A transaction is
-\emph{atomic}: either the entire transaction succeeds and its effects
-are all visible to readers in one go, or the whole thing is undone.
-This guarantee of atomicity means that if you're running two copies of
-Mercurial, where one is reading data and one is writing it, the reader
-will never see a partially written result that might confuse it.
-
-The fact that Mercurial only appends to files makes it easier to
-provide this transactional guarantee.  The easier it is to do stuff
-like this, the more confident you should be that it's done correctly.
-
-\subsection{Fast retrieval}
-
-Mercurial cleverly avoids a pitfall common to all earlier
-revision control systems: the problem of \emph{inefficient retrieval}.
-Most revision control systems store the contents of a revision as an
-incremental series of modifications against a ``snapshot''.  To
-reconstruct a specific revision, you must first read the snapshot, and
-then every one of the revisions between the snapshot and your target
-revision.  The more history that a file accumulates, the more
-revisions you must read, hence the longer it takes to reconstruct a
-particular revision.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{snapshot}
-  \caption{Snapshot of a revlog, with incremental deltas}
-  \label{fig:concepts:snapshot}
-\end{figure}
-
-The innovation that Mercurial applies to this problem is simple but
-effective.  Once the cumulative amount of delta information stored
-since the last snapshot exceeds a fixed threshold, it stores a new
-snapshot (compressed, of course), instead of another delta.  This
-makes it possible to reconstruct \emph{any} revision of a file
-quickly.  This approach works so well that it has since been copied by
-several other revision control systems.
-
-Figure~\ref{fig:concepts:snapshot} illustrates the idea.  In an entry
-in a revlog's index file, Mercurial stores the range of entries from
-the data file that it must read to reconstruct a particular revision.
-
-\subsubsection{Aside: the influence of video compression}
-
-If you're familiar with video compression or have ever watched a TV
-feed through a digital cable or satellite service, you may know that
-most video compression schemes store each frame of video as a delta
-against its predecessor frame.  In addition, these schemes use
-``lossy'' compression techniques to increase the compression ratio, so
-visual errors accumulate over the course of a number of inter-frame
-deltas.
-
-Because it's possible for a video stream to ``drop out'' occasionally
-due to signal glitches, and to limit the accumulation of artefacts
-introduced by the lossy compression process, video encoders
-periodically insert a complete frame (called a ``key frame'') into the
-video stream; the next delta is generated against that frame.  This
-means that if the video signal gets interrupted, it will resume once
-the next key frame is received.  Also, the accumulation of encoding
-errors restarts anew with each key frame.
-
-\subsection{Identification and strong integrity}
-
-Along with delta or snapshot information, a revlog entry contains a
-cryptographic hash of the data that it represents.  This makes it
-difficult to forge the contents of a revision, and easy to detect
-accidental corruption.  
-
-Hashes provide more than a mere check against corruption; they are
-used as the identifiers for revisions.  The changeset identification
-hashes that you see as an end user are from revisions of the
-changelog.  Although filelogs and the manifest also use hashes,
-Mercurial only uses these behind the scenes.
-
-Mercurial verifies that hashes are correct when it retrieves file
-revisions and when it pulls changes from another repository.  If it
-encounters an integrity problem, it will complain and stop whatever
-it's doing.
-
-In addition to the effect it has on retrieval efficiency, Mercurial's
-use of periodic snapshots makes it more robust against partial data
-corruption.  If a revlog becomes partly corrupted due to a hardware
-error or system bug, it's often possible to reconstruct some or most
-revisions from the uncorrupted sections of the revlog, both before and
-after the corrupted section.  This would not be possible with a
-delta-only storage model.
-
-\section{Revision history, branching,
-  and merging}
-
-Every entry in a Mercurial revlog knows the identity of its immediate
-ancestor revision, usually referred to as its \emph{parent}.  In fact,
-a revision contains room for not one parent, but two.  Mercurial uses
-a special hash, called the ``null ID'', to represent the idea ``there
-is no parent here''.  This hash is simply a string of zeroes.
-
-In figure~\ref{fig:concepts:revlog}, you can see an example of the
-conceptual structure of a revlog.  Filelogs, manifests, and changelogs
-all have this same structure; they differ only in the kind of data
-stored in each delta or snapshot.
-
-The first revision in a revlog (at the bottom of the image) has the
-null ID in both of its parent slots.  For a ``normal'' revision, its
-first parent slot contains the ID of its parent revision, and its
-second contains the null ID, indicating that the revision has only one
-real parent.  Any two revisions that have the same parent ID are
-branches.  A revision that represents a merge between branches has two
-normal revision IDs in its parent slots.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{revlog}
-  \caption{}
-  \label{fig:concepts:revlog}
-\end{figure}
-
-\section{The working directory}
-
-In the working directory, Mercurial stores a snapshot of the files
-from the repository as of a particular changeset.
-
-The working directory ``knows'' which changeset it contains.  When you
-update the working directory to contain a particular changeset,
-Mercurial looks up the appropriate revision of the manifest to find
-out which files it was tracking at the time that changeset was
-committed, and which revision of each file was then current.  It then
-recreates a copy of each of those files, with the same contents it had
-when the changeset was committed.
-
-The \emph{dirstate} contains Mercurial's knowledge of the working
-directory.  This details which changeset the working directory is
-updated to, and all of the files that Mercurial is tracking in the
-working directory.
-
-Just as a revision of a revlog has room for two parents, so that it
-can represent either a normal revision (with one parent) or a merge of
-two earlier revisions, the dirstate has slots for two parents.  When
-you use the \hgcmd{update} command, the changeset that you update to
-is stored in the ``first parent'' slot, and the null ID in the second.
-When you \hgcmd{merge} with another changeset, the first parent
-remains unchanged, and the second parent is filled in with the
-changeset you're merging with.  The \hgcmd{parents} command tells you
-what the parents of the dirstate are.
-
-\subsection{What happens when you commit}
-
-The dirstate stores parent information for more than just book-keeping
-purposes.  Mercurial uses the parents of the dirstate as \emph{the
-  parents of a new changeset} when you perform a commit.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{wdir}
-  \caption{The working directory can have two parents}
-  \label{fig:concepts:wdir}
-\end{figure}
-
-Figure~\ref{fig:concepts:wdir} shows the normal state of the working
-directory, where it has a single changeset as parent.  That changeset
-is the \emph{tip}, the newest changeset in the repository that has no
-children.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{wdir-after-commit}
-  \caption{The working directory gains new parents after a commit}
-  \label{fig:concepts:wdir-after-commit}
-\end{figure}
-
-It's useful to think of the working directory as ``the changeset I'm
-about to commit''.  Any files that you tell Mercurial that you've
-added, removed, renamed, or copied will be reflected in that
-changeset, as will modifications to any files that Mercurial is
-already tracking; the new changeset will have the parents of the
-working directory as its parents.
-
-After a commit, Mercurial will update the parents of the working
-directory, so that the first parent is the ID of the new changeset,
-and the second is the null ID.  This is shown in
-figure~\ref{fig:concepts:wdir-after-commit}.  Mercurial doesn't touch
-any of the files in the working directory when you commit; it just
-modifies the dirstate to note its new parents.
-
-\subsection{Creating a new head}
-
-It's perfectly normal to update the working directory to a changeset
-other than the current tip.  For example, you might want to know what
-your project looked like last Tuesday, or you could be looking through
-changesets to see which one introduced a bug.  In cases like this, the
-natural thing to do is update the working directory to the changeset
-you're interested in, and then examine the files in the working
-directory directly to see their contents as they were when you
-committed that changeset.  The effect of this is shown in
-figure~\ref{fig:concepts:wdir-pre-branch}.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{wdir-pre-branch}
-  \caption{The working directory, updated to an older changeset}
-  \label{fig:concepts:wdir-pre-branch}
-\end{figure}
-
-Having updated the working directory to an older changeset, what
-happens if you make some changes, and then commit?  Mercurial behaves
-in the same way as I outlined above.  The parents of the working
-directory become the parents of the new changeset.  This new changeset
-has no children, so it becomes the new tip.  And the repository now
-contains two changesets that have no children; we call these
-\emph{heads}.  You can see the structure that this creates in
-figure~\ref{fig:concepts:wdir-branch}.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{wdir-branch}
-  \caption{After a commit made while synced to an older changeset}
-  \label{fig:concepts:wdir-branch}
-\end{figure}
-
-\begin{note}
-  If you're new to Mercurial, you should keep in mind a common
-  ``error'', which is to use the \hgcmd{pull} command without any
-  options.  By default, the \hgcmd{pull} command \emph{does not}
-  update the working directory, so you'll bring new changesets into
-  your repository, but the working directory will stay synced at the
-  same changeset as before the pull.  If you make some changes and
-  commit afterwards, you'll thus create a new head, because your
-  working directory isn't synced to whatever the current tip is.
-
-  I put the word ``error'' in quotes because all that you need to do
-  to rectify this situation is \hgcmd{merge}, then \hgcmd{commit}.  In
-  other words, this almost never has negative consequences; it just
-  surprises people.  I'll discuss other ways to avoid this behaviour,
-  and why Mercurial behaves in this initially surprising way, later
-  on.
-\end{note}
-
-\subsection{Merging heads}
-
-When you run the \hgcmd{merge} command, Mercurial leaves the first
-parent of the working directory unchanged, and sets the second parent
-to the changeset you're merging with, as shown in
-figure~\ref{fig:concepts:wdir-merge}.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{wdir-merge}
-  \caption{Merging two heads}
-  \label{fig:concepts:wdir-merge}
-\end{figure}
-
-Mercurial also has to modify the working directory, to merge the files
-managed in the two changesets.  Simplified a little, the merging
-process goes like this, for every file in the manifests of both
-changesets.
-\begin{itemize}
-\item If neither changeset has modified a file, do nothing with that
-  file.
-\item If one changeset has modified a file, and the other hasn't,
-  create the modified copy of the file in the working directory.
-\item If one changeset has removed a file, and the other hasn't (or
-  has also deleted it), delete the file from the working directory.
-\item If one changeset has removed a file, but the other has modified
-  the file, ask the user what to do: keep the modified file, or remove
-  it?
-\item If both changesets have modified a file, invoke an external
-  merge program to choose the new contents for the merged file.  This
-  may require input from the user.
-\item If one changeset has modified a file, and the other has renamed
-  or copied the file, make sure that the changes follow the new name
-  of the file.
-\end{itemize}
-There are more details---merging has plenty of corner cases---but
-these are the most common choices that are involved in a merge.  As
-you can see, most cases are completely automatic, and indeed most
-merges finish automatically, without requiring your input to resolve
-any conflicts.
-
-When you're thinking about what happens when you commit after a merge,
-once again the working directory is ``the changeset I'm about to
-commit''.  After the \hgcmd{merge} command completes, the working
-directory has two parents; these will become the parents of the new
-changeset.
-
-Mercurial lets you perform multiple merges, but you must commit the
-results of each individual merge as you go.  This is necessary because
-Mercurial only tracks two parents for both revisions and the working
-directory.  While it would be technically possible to merge multiple
-changesets at once, the prospect of user confusion and making a
-terrible mess of a merge immediately becomes overwhelming.
-
-\section{Other interesting design features}
-
-In the sections above, I've tried to highlight some of the most
-important aspects of Mercurial's design, to illustrate that it pays
-careful attention to reliability and performance.  However, the
-attention to detail doesn't stop there.  There are a number of other
-aspects of Mercurial's construction that I personally find
-interesting.  I'll detail a few of them here, separate from the ``big
-ticket'' items above, so that if you're interested, you can gain a
-better idea of the amount of thinking that goes into a well-designed
-system.
-
-\subsection{Clever compression}
-
-When appropriate, Mercurial will store both snapshots and deltas in
-compressed form.  It does this by always \emph{trying to} compress a
-snapshot or delta, but only storing the compressed version if it's
-smaller than the uncompressed version.
-
-This means that Mercurial does ``the right thing'' when storing a file
-whose native form is compressed, such as a \texttt{zip} archive or a
-JPEG image.  When these types of files are compressed a second time,
-the resulting file is usually bigger than the once-compressed form,
-and so Mercurial will store the plain \texttt{zip} or JPEG.
-
-Deltas between revisions of a compressed file are usually larger than
-snapshots of the file, and Mercurial again does ``the right thing'' in
-these cases.  It finds that such a delta exceeds the threshold at
-which it should store a complete snapshot of the file, so it stores
-the snapshot, again saving space compared to a naive delta-only
-approach.
-
-\subsubsection{Network recompression}
-
-When storing revisions on disk, Mercurial uses the ``deflate''
-compression algorithm (the same one used by the popular \texttt{zip}
-archive format), which balances good speed with a respectable
-compression ratio.  However, when transmitting revision data over a
-network connection, Mercurial uncompresses the compressed revision
-data.
-
-If the connection is over HTTP, Mercurial recompresses the entire
-stream of data using a compression algorithm that gives a better
-compression ratio (the Burrows-Wheeler algorithm from the widely used
-\texttt{bzip2} compression package).  This combination of algorithm
-and compression of the entire stream (instead of a revision at a time)
-substantially reduces the number of bytes to be transferred, yielding
-better network performance over almost all kinds of network.
-
-(If the connection is over \command{ssh}, Mercurial \emph{doesn't}
-recompress the stream, because \command{ssh} can already do this
-itself.)
-
-\subsection{Read/write ordering and atomicity}
-
-Appending to files isn't the whole story when it comes to guaranteeing
-that a reader won't see a partial write.  If you recall
-figure~\ref{fig:concepts:metadata}, revisions in the changelog point to
-revisions in the manifest, and revisions in the manifest point to
-revisions in filelogs.  This hierarchy is deliberate.
-
-A writer starts a transaction by writing filelog and manifest data,
-and doesn't write any changelog data until those are finished.  A
-reader starts by reading changelog data, then manifest data, followed
-by filelog data.
-
-Since the writer has always finished writing filelog and manifest data
-before it writes to the changelog, a reader will never read a pointer
-to a partially written manifest revision from the changelog, and it will
-never read a pointer to a partially written filelog revision from the
-manifest.
-
-\subsection{Concurrent access}
-
-The read/write ordering and atomicity guarantees mean that Mercurial
-never needs to \emph{lock} a repository when it's reading data, even
-if the repository is being written to while the read is occurring.
-This has a big effect on scalability; you can have an arbitrary number
-of Mercurial processes safely reading data from a repository safely
-all at once, no matter whether it's being written to or not.
-
-The lockless nature of reading means that if you're sharing a
-repository on a multi-user system, you don't need to grant other local
-users permission to \emph{write} to your repository in order for them
-to be able to clone it or pull changes from it; they only need
-\emph{read} permission.  (This is \emph{not} a common feature among
-revision control systems, so don't take it for granted!  Most require
-readers to be able to lock a repository to access it safely, and this
-requires write permission on at least one directory, which of course
-makes for all kinds of nasty and annoying security and administrative
-problems.)
-
-Mercurial uses locks to ensure that only one process can write to a
-repository at a time (the locking mechanism is safe even over
-filesystems that are notoriously hostile to locking, such as NFS).  If
-a repository is locked, a writer will wait for a while to retry if the
-repository becomes unlocked, but if the repository remains locked for
-too long, the process attempting to write will time out after a while.
-This means that your daily automated scripts won't get stuck forever
-and pile up if a system crashes unnoticed, for example.  (Yes, the
-timeout is configurable, from zero to infinity.)
-
-\subsubsection{Safe dirstate access}
-
-As with revision data, Mercurial doesn't take a lock to read the
-dirstate file; it does acquire a lock to write it.  To avoid the
-possibility of reading a partially written copy of the dirstate file,
-Mercurial writes to a file with a unique name in the same directory as
-the dirstate file, then renames the temporary file atomically to
-\filename{dirstate}.  The file named \filename{dirstate} is thus
-guaranteed to be complete, not partially written.
-
-\subsection{Avoiding seeks}
-
-Critical to Mercurial's performance is the avoidance of seeks of the
-disk head, since any seek is far more expensive than even a
-comparatively large read operation.
-
-This is why, for example, the dirstate is stored in a single file.  If
-there were a dirstate file per directory that Mercurial tracked, the
-disk would seek once per directory.  Instead, Mercurial reads the
-entire single dirstate file in one step.
-
-Mercurial also uses a ``copy on write'' scheme when cloning a
-repository on local storage.  Instead of copying every revlog file
-from the old repository into the new repository, it makes a ``hard
-link'', which is a shorthand way to say ``these two names point to the
-same file''.  When Mercurial is about to write to one of a revlog's
-files, it checks to see if the number of names pointing at the file is
-greater than one.  If it is, more than one repository is using the
-file, so Mercurial makes a new copy of the file that is private to
-this repository.
-
-A few revision control developers have pointed out that this idea of
-making a complete private copy of a file is not very efficient in its
-use of storage.  While this is true, storage is cheap, and this method
-gives the highest performance while deferring most book-keeping to the
-operating system.  An alternative scheme would most likely reduce
-performance and increase the complexity of the software, each of which
-is much more important to the ``feel'' of day-to-day use.
-
-\subsection{Other contents of the dirstate}
-
-Because Mercurial doesn't force you to tell it when you're modifying a
-file, it uses the dirstate to store some extra information so it can
-determine efficiently whether you have modified a file.  For each file
-in the working directory, it stores the time that it last modified the
-file itself, and the size of the file at that time.  
-
-When you explicitly \hgcmd{add}, \hgcmd{remove}, \hgcmd{rename} or
-\hgcmd{copy} files, Mercurial updates the dirstate so that it knows
-what to do with those files when you commit.
-
-When Mercurial is checking the states of files in the working
-directory, it first checks a file's modification time.  If that has
-not changed, the file must not have been modified.  If the file's size
-has changed, the file must have been modified.  If the modification
-time has changed, but the size has not, only then does Mercurial need
-to read the actual contents of the file to see if they've changed.
-Storing these few extra pieces of information dramatically reduces the
-amount of data that Mercurial needs to read, which yields large
-performance improvements compared to other revision control systems.
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End:
--- a/en/daily.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,381 +0,0 @@
-\chapter{Mercurial in daily use}
-\label{chap:daily}
-
-\section{Telling Mercurial which files to track}
-
-Mercurial does not work with files in your repository unless you tell
-it to manage them.  The \hgcmd{status} command will tell you which
-files Mercurial doesn't know about; it uses a ``\texttt{?}'' to
-display such files.
-
-To tell Mercurial to track a file, use the \hgcmd{add} command.  Once
-you have added a file, the entry in the output of \hgcmd{status} for
-that file changes from ``\texttt{?}'' to ``\texttt{A}''.
-\interaction{daily.files.add}
-
-After you run a \hgcmd{commit}, the files that you added before the
-commit will no longer be listed in the output of \hgcmd{status}.  The
-reason for this is that \hgcmd{status} only tells you about
-``interesting'' files---those that you have modified or told Mercurial
-to do something with---by default.  If you have a repository that
-contains thousands of files, you will rarely want to know about files
-that Mercurial is tracking, but that have not changed.  (You can still
-get this information; we'll return to this later.)
-
-Once you add a file, Mercurial doesn't do anything with it
-immediately.  Instead, it will take a snapshot of the file's state the
-next time you perform a commit.  It will then continue to track the
-changes you make to the file every time you commit, until you remove
-the file.
-
-\subsection{Explicit versus implicit file naming}
-
-A useful behaviour that Mercurial has is that if you pass the name of
-a directory to a command, every Mercurial command will treat this as
-``I want to operate on every file in this directory and its
-subdirectories''.
-\interaction{daily.files.add-dir}
-Notice in this example that Mercurial printed the names of the files
-it added, whereas it didn't do so when we added the file named
-\filename{a} in the earlier example.
-
-What's going on is that in the former case, we explicitly named the
-file to add on the command line, so the assumption that Mercurial
-makes in such cases is that you know what you were doing, and it
-doesn't print any output.
-
-However, when we \emph{imply} the names of files by giving the name of
-a directory, Mercurial takes the extra step of printing the name of
-each file that it does something with.  This makes it more clear what
-is happening, and reduces the likelihood of a silent and nasty
-surprise.  This behaviour is common to most Mercurial commands.
-
-\subsection{Aside: Mercurial tracks files, not directories}
-
-Mercurial does not track directory information.  Instead, it tracks
-the path to a file.  Before creating a file, it first creates any
-missing directory components of the path.  After it deletes a file, it
-then deletes any empty directories that were in the deleted file's
-path.  This sounds like a trivial distinction, but it has one minor
-practical consequence: it is not possible to represent a completely
-empty directory in Mercurial.
-
-Empty directories are rarely useful, and there are unintrusive
-workarounds that you can use to achieve an appropriate effect.  The
-developers of Mercurial thus felt that the complexity that would be
-required to manage empty directories was not worth the limited benefit
-this feature would bring.
-
-If you need an empty directory in your repository, there are a few
-ways to achieve this. One is to create a directory, then \hgcmd{add} a
-``hidden'' file to that directory.  On Unix-like systems, any file
-name that begins with a period (``\texttt{.}'') is treated as hidden
-by most commands and GUI tools.  This approach is illustrated in
-figure~\ref{ex:daily:hidden}.
-
-\begin{figure}[ht]
-  \interaction{daily.files.hidden}
-  \caption{Simulating an empty directory using a hidden file}
-  \label{ex:daily:hidden}
-\end{figure}
-
-Another way to tackle a need for an empty directory is to simply
-create one in your automated build scripts before they will need it.
-
-\section{How to stop tracking a file}
-
-Once you decide that a file no longer belongs in your repository, use
-the \hgcmd{remove} command; this deletes the file, and tells Mercurial
-to stop tracking it.  A removed file is represented in the output of
-\hgcmd{status} with a ``\texttt{R}''.
-\interaction{daily.files.remove}
-
-After you \hgcmd{remove} a file, Mercurial will no longer track
-changes to that file, even if you recreate a file with the same name
-in your working directory.  If you do recreate a file with the same
-name and want Mercurial to track the new file, simply \hgcmd{add} it.
-Mercurial will know that the newly added file is not related to the
-old file of the same name.
-
-\subsection{Removing a file does not affect its history}
-
-It is important to understand that removing a file has only two
-effects.
-\begin{itemize}
-\item It removes the current version of the file from the working
-  directory.
-\item It stops Mercurial from tracking changes to the file, from the
-  time of the next commit.
-\end{itemize}
-Removing a file \emph{does not} in any way alter the \emph{history} of
-the file.
-
-If you update the working directory to a changeset in which a file
-that you have removed was still tracked, it will reappear in the
-working directory, with the contents it had when you committed that
-changeset.  If you then update the working directory to a later
-changeset, in which the file had been removed, Mercurial will once
-again remove the file from the working directory.
-
-\subsection{Missing files}
-
-Mercurial considers a file that you have deleted, but not used
-\hgcmd{remove} to delete, to be \emph{missing}.  A missing file is
-represented with ``\texttt{!}'' in the output of \hgcmd{status}.
-Mercurial commands will not generally do anything with missing files.
-\interaction{daily.files.missing}
-
-If your repository contains a file that \hgcmd{status} reports as
-missing, and you want the file to stay gone, you can run
-\hgcmdargs{remove}{\hgopt{remove}{--after}} at any time later on, to
-tell Mercurial that you really did mean to remove the file.
-\interaction{daily.files.remove-after}
-
-On the other hand, if you deleted the missing file by accident, use
-\hgcmdargs{revert}{\emph{filename}} to recover the file.  It will
-reappear, in unmodified form.
-\interaction{daily.files.recover-missing}
-
-\subsection{Aside: why tell Mercurial explicitly to 
-  remove a file?}
-
-You might wonder why Mercurial requires you to explicitly tell it that
-you are deleting a file.  Early during the development of Mercurial,
-it let you delete a file however you pleased; Mercurial would notice
-the absence of the file automatically when you next ran a
-\hgcmd{commit}, and stop tracking the file.  In practice, this made it
-too easy to accidentally remove a file without noticing.
-
-\subsection{Useful shorthand---adding and removing files
-  in one step}
-
-Mercurial offers a combination command, \hgcmd{addremove}, that adds
-untracked files and marks missing files as removed.  
-\interaction{daily.files.addremove}
-The \hgcmd{commit} command also provides a \hgopt{commit}{-A} option
-that performs this same add-and-remove, immediately followed by a
-commit.
-\interaction{daily.files.commit-addremove}
-
-\section{Copying files}
-
-Mercurial provides a \hgcmd{copy} command that lets you make a new
-copy of a file.  When you copy a file using this command, Mercurial
-makes a record of the fact that the new file is a copy of the original
-file.  It treats these copied files specially when you merge your work
-with someone else's.
-
-\subsection{The results of copying during a merge}
-
-What happens during a merge is that changes ``follow'' a copy.  To
-best illustrate what this means, let's create an example.  We'll start
-with the usual tiny repository that contains a single file.
-\interaction{daily.copy.init}
-We need to do some work in parallel, so that we'll have something to
-merge.  So let's clone our repository.
-\interaction{daily.copy.clone}
-Back in our initial repository, let's use the \hgcmd{copy} command to
-make a copy of the first file we created.
-\interaction{daily.copy.copy}
-
-If we look at the output of the \hgcmd{status} command afterwards, the
-copied file looks just like a normal added file.
-\interaction{daily.copy.status}
-But if we pass the \hgopt{status}{-C} option to \hgcmd{status}, it
-prints another line of output: this is the file that our newly-added
-file was copied \emph{from}.
-\interaction{daily.copy.status-copy}
-
-Now, back in the repository we cloned, let's make a change in
-parallel.  We'll add a line of content to the original file that we
-created.
-\interaction{daily.copy.other}
-Now we have a modified \filename{file} in this repository.  When we
-pull the changes from the first repository, and merge the two heads,
-Mercurial will propagate the changes that we made locally to
-\filename{file} into its copy, \filename{new-file}.
-\interaction{daily.copy.merge}
-
-\subsection{Why should changes follow copies?}
-\label{sec:daily:why-copy}
-
-This behaviour, of changes to a file propagating out to copies of the
-file, might seem esoteric, but in most cases it's highly desirable.
-
-First of all, remember that this propagation \emph{only} happens when
-you merge.  So if you \hgcmd{copy} a file, and subsequently modify the
-original file during the normal course of your work, nothing will
-happen.
-
-The second thing to know is that modifications will only propagate
-across a copy as long as the repository that you're pulling changes
-from \emph{doesn't know} about the copy.
-
-The reason that Mercurial does this is as follows.  Let's say I make
-an important bug fix in a source file, and commit my changes.
-Meanwhile, you've decided to \hgcmd{copy} the file in your repository,
-without knowing about the bug or having seen the fix, and you have
-started hacking on your copy of the file.
-
-If you pulled and merged my changes, and Mercurial \emph{didn't}
-propagate changes across copies, your source file would now contain
-the bug, and unless you remembered to propagate the bug fix by hand,
-the bug would \emph{remain} in your copy of the file.
-
-By automatically propagating the change that fixed the bug from the
-original file to the copy, Mercurial prevents this class of problem.
-To my knowledge, Mercurial is the \emph{only} revision control system
-that propagates changes across copies like this.
-
-Once your change history has a record that the copy and subsequent
-merge occurred, there's usually no further need to propagate changes
-from the original file to the copied file, and that's why Mercurial
-only propagates changes across copies until this point, and no
-further.
-
-\subsection{How to make changes \emph{not} follow a copy}
-
-If, for some reason, you decide that this business of automatically
-propagating changes across copies is not for you, simply use your
-system's normal file copy command (on Unix-like systems, that's
-\command{cp}) to make a copy of a file, then \hgcmd{add} the new copy
-by hand.  Before you do so, though, please do reread
-section~\ref{sec:daily:why-copy}, and make an informed decision that
-this behaviour is not appropriate to your specific case.
-
-\subsection{Behaviour of the \hgcmd{copy} command}
-
-When you use the \hgcmd{copy} command, Mercurial makes a copy of each
-source file as it currently stands in the working directory.  This
-means that if you make some modifications to a file, then \hgcmd{copy}
-it without first having committed those changes, the new copy will
-also contain the modifications you have made up until that point.  (I
-find this behaviour a little counterintuitive, which is why I mention
-it here.)
-
-The \hgcmd{copy} command acts similarly to the Unix \command{cp}
-command (you can use the \hgcmd{cp} alias if you prefer).  The last
-argument is the \emph{destination}, and all prior arguments are
-\emph{sources}.  If you pass it a single file as the source, and the
-destination does not exist, it creates a new file with that name.
-\interaction{daily.copy.simple}
-If the destination is a directory, Mercurial copies its sources into
-that directory.
-\interaction{daily.copy.dir-dest}
-Copying a directory is recursive, and preserves the directory
-structure of the source.
-\interaction{daily.copy.dir-src}
-If the source and destination are both directories, the source tree is
-recreated in the destination directory.
-\interaction{daily.copy.dir-src-dest}
-
-As with the \hgcmd{rename} command, if you copy a file manually and
-then want Mercurial to know that you've copied the file, simply use
-the \hgopt{copy}{--after} option to \hgcmd{copy}.
-\interaction{daily.copy.after}
-
-\section{Renaming files}
-
-It's rather more common to need to rename a file than to make a copy
-of it.  The reason I discussed the \hgcmd{copy} command before talking
-about renaming files is that Mercurial treats a rename in essentially
-the same way as a copy.  Therefore, knowing what Mercurial does when
-you copy a file tells you what to expect when you rename a file.
-
-When you use the \hgcmd{rename} command, Mercurial makes a copy of
-each source file, then deletes it and marks the file as removed.
-\interaction{daily.rename.rename}
-The \hgcmd{status} command shows the newly copied file as added, and
-the copied-from file as removed.
-\interaction{daily.rename.status}
-As with the results of a \hgcmd{copy}, we must use the
-\hgopt{status}{-C} option to \hgcmd{status} to see that the added file
-is really being tracked by Mercurial as a copy of the original, now
-removed, file.
-\interaction{daily.rename.status-copy}
-
-As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about
-a rename after the fact using the \hgopt{rename}{--after} option.  In
-most other respects, the behaviour of the \hgcmd{rename} command, and
-the options it accepts, are similar to the \hgcmd{copy} command.
-
-\subsection{Renaming files and merging changes}
-
-Since Mercurial's rename is implemented as copy-and-remove, the same
-propagation of changes happens when you merge after a rename as after
-a copy.
-
-If I modify a file, and you rename it to a new name, and then we merge
-our respective changes, my modifications to the file under its
-original name will be propagated into the file under its new name.
-(This is something you might expect to ``simply work,'' but not all
-revision control systems actually do this.)
-
-Whereas having changes follow a copy is a feature where you can
-perhaps nod and say ``yes, that might be useful,'' it should be clear
-that having them follow a rename is definitely important.  Without
-this facility, it would simply be too easy for changes to become
-orphaned when files are renamed.
-
-\subsection{Divergent renames and merging}
-
-The case of diverging names occurs when two developers start with a
-file---let's call it \filename{foo}---in their respective
-repositories.
-
-\interaction{rename.divergent.clone}
-Anne renames the file to \filename{bar}.
-\interaction{rename.divergent.rename.anne}
-Meanwhile, Bob renames it to \filename{quux}.
-\interaction{rename.divergent.rename.bob}
-
-I like to think of this as a conflict because each developer has
-expressed different intentions about what the file ought to be named.
-
-What do you think should happen when they merge their work?
-Mercurial's actual behaviour is that it always preserves \emph{both}
-names when it merges changesets that contain divergent renames.
-\interaction{rename.divergent.merge}
-
-Notice that Mercurial does warn about the divergent renames, but it
-leaves it up to you to do something about the divergence after the merge.
-
-\subsection{Convergent renames and merging}
-
-Another kind of rename conflict occurs when two people choose to
-rename different \emph{source} files to the same \emph{destination}.
-In this case, Mercurial runs its normal merge machinery, and lets you
-guide it to a suitable resolution.
-
-\subsection{Other name-related corner cases}
-
-Mercurial has a longstanding bug in which it fails to handle a merge
-where one side has a file with a given name, while another has a
-directory with the same name.  This is documented as~\bug{29}.
-\interaction{issue29.go}
-
-\section{Recovering from mistakes}
-
-Mercurial has some useful commands that will help you to recover from
-some common mistakes.
-
-The \hgcmd{revert} command lets you undo changes that you have made to
-your working directory.  For example, if you \hgcmd{add} a file by
-accident, just run \hgcmd{revert} with the name of the file you added,
-and while the file won't be touched in any way, it won't be tracked
-for adding by Mercurial any longer, either.  You can also use
-\hgcmd{revert} to get rid of erroneous changes to a file.
-
-It's useful to remember that the \hgcmd{revert} command is useful for
-changes that you have not yet committed.  Once you've committed a
-change, if you decide it was a mistake, you can still do something
-about it, though your options may be more limited.
-
-For more information about the \hgcmd{revert} command, and details
-about how to deal with changes you have already committed, see
-chapter~\ref{chap:undo}.
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/examples/backout.manual.log.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/backout.manual.log.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,13 +1,13 @@
 $ \textbf{hg log --style compact}
-3[tip]:1   
+3[tip]:1      2009-01-30 06:32 +0000   bos
   back out second change
 
-2   
+2      2009-01-30 06:32 +0000   bos
   third change
 
-1   
+1      2009-01-30 06:32 +0000   bos
   second change
 
-0   
+0      2009-01-30 06:32 +0000   bos
   first change
 
--- a/en/examples/backout.simple.log.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/backout.simple.log.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,10 +1,10 @@
 $ \textbf{hg log --style compact}
-2[tip]   
+2[tip]      2009-01-30 06:32 +0000   bos
   back out second change
 
-1   
+1      2009-01-30 06:32 +0000   bos
   second change
 
-0   
+0      2009-01-30 06:32 +0000   bos
   first change
 
--- a/en/examples/bisect	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect	Mon Feb 09 22:59:50 2009 -0800
@@ -1,8 +1,11 @@
 #!/bin/bash
 
-# Don't add the bisect extension. That's not needed anymore. 
-#echo '[extensions]' >> $HGRC
-#echo 'hbisect =' >> $HGRC
+if  hg -v | head -1 | grep -e "version 0.*"
+then
+#On mercurial 1.0 and later bisect is a builtin
+echo '[extensions]' >> $HGRC
+echo 'hbisect =' >> $HGRC
+fi
 
 # XXX There's some kind of horrible nondeterminism in the execution of
 # bisect at the moment.  Ugh.
@@ -34,15 +37,15 @@
 
 #$ name: search.init
 
-hg bisect --init
+hg bisect init
 
 #$ name: search.bad-init
 
-hg bisect --bad
+hg bisect bad
 
 #$ name: search.good-init
 
-hg bisect --good 10
+hg bisect good 10
 
 #$ name: search.step1
 
@@ -67,7 +70,7 @@
   fi
 
   echo this revision is $result
-  hg bisect --$result
+  hg bisect $result
 }
   
 #$ name: search.step2
@@ -82,7 +85,7 @@
 
 #$ name: search.reset
 
-hg bisect --reset
+hg bisect reset
 
 #$ name:
 
--- a/en/examples/bisect.commits.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect.commits.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,16 +1,3 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
@@ -21,25 +8,3 @@
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
--- a/en/examples/bisect.help.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect.help.out	Mon Feb 09 22:59:50 2009 -0800
@@ -19,3 +19,15 @@
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
--- a/en/examples/bisect.init.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect.init.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,3 +1,2 @@
 
 
-
--- a/en/examples/bisect.search.bad-init.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect.search.bad-init.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,22 +1,2 @@
-
-
-
-
-
-
-
-
-
 
 
-
-
-
-
-
-
-
-
-
-
-
--- a/en/examples/bisect.search.good-init.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect.search.good-init.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,22 +1,4 @@
-
-
-
-
-
-
-
 
 
 
 
-
-
-
-
-
-
-
-
-
-
-
--- a/en/examples/bisect.search.init.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect.search.init.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,22 +1,2 @@
-
-
-
-
-
-
-
-
-
 
 
-
-
-
-
-
-
-
-
-
-
-
--- a/en/examples/bisect.search.reset.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect.search.reset.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,22 +1,2 @@
-
-
-
-
-
-
-
-
-
 
 
-
-
-
-
-
-
-
-
-
-
-
--- a/en/examples/bisect.search.rest.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect.search.rest.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,19 +1,3 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 
 
 
@@ -33,37 +17,3 @@
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
--- a/en/examples/bisect.search.step1.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect.search.step1.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,7 +1,3 @@
-
-
-
-
 
 
 
@@ -13,18 +9,3 @@
 
 
 
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
--- a/en/examples/bisect.search.step2.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/bisect.search.step2.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,23 +1,5 @@
-
-
-
-
-
-
-
 
 
 
 
 
-
-
-
-
-
-
-
-
-
-
-
--- a/en/examples/branch-repo.bugfix.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/branch-repo.bugfix.out	Mon Feb 09 22:59:50 2009 -0800
@@ -5,7 +5,7 @@
 $ \textbf{echo 'I fixed a bug using only echo!' >> myfile}
 $ \textbf{hg commit -m 'Important fix for 1.0.1'}
 $ \textbf{hg push}
-pushing to /tmp/branch-repo4rF-PL/myproject-1.0.1
+pushing to 
 searching for changes
 adding changesets
 adding manifests
--- a/en/examples/branching.stable.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/branching.stable.out	Mon Feb 09 22:59:50 2009 -0800
@@ -5,7 +5,7 @@
 $ \textbf{echo 'This is a fix to a boring feature.' > myfile}
 $ \textbf{hg commit -m 'Fix a bug'}
 $ \textbf{hg push}
-pushing to /tmp/branchingfJgZac/stable
+pushing to 
 searching for changes
 adding changesets
 adding manifests
--- a/en/examples/cmdref.diff-p.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/cmdref.diff-p.out	Mon Feb 09 22:59:50 2009 -0800
@@ -14,7 +14,7 @@
 diff -r  myfile.c
 
 
-@@ -1,4 +1,4 @@ int myfunc()
+@@ -1,4 +1,4 @@
  int myfunc()
  \{
 -    return 1;
--- a/en/examples/mq.guards.qselect.foo.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.guards.qselect.foo.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,5 +1,5 @@
 $ \textbf{hg qpop -a}
-Patch queue now empty
+patch queue now empty
 $ \textbf{hg qselect}
 no active guards
 $ \textbf{hg qselect foo}
--- a/en/examples/mq.guards.qselect.foobar.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.guards.qselect.foobar.out	Mon Feb 09 22:59:50 2009 -0800
@@ -5,4 +5,4 @@
 $ \textbf{hg qpush -a}
 applying hello.patch
 applying goodbye.patch
-Now at: goodbye.patch
+now at: goodbye.patch
--- a/en/examples/mq.guards.qselect.qpush.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.guards.qselect.qpush.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,4 +1,4 @@
 $ \textbf{hg qpush -a}
 applying hello.patch
 applying goodbye.patch
-Now at: goodbye.patch
+now at: goodbye.patch
--- a/en/examples/mq.guards.qselect.quux.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.guards.qselect.quux.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,6 +1,6 @@
 $ \textbf{hg qselect quux}
 number of guarded, applied patches has changed from 0 to 2
 $ \textbf{hg qpop -a}
-Patch queue now empty
+patch queue now empty
 $ \textbf{hg qpush -a}
 patch series already fully applied
--- a/en/examples/mq.tarball.newsource.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.tarball.newsource.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,5 +1,5 @@
 $ \textbf{hg qpop -a}
-Patch queue now empty
+patch queue now empty
 $ \textbf{cd ..}
 $ \textbf{download netplug-1.2.8.tar.bz2}
 $ \textbf{hg clone netplug-1.2.5 netplug-1.2.8}
--- a/en/examples/mq.tarball.repush.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.tarball.repush.out	Mon Feb 09 22:59:50 2009 -0800
@@ -10,4 +10,4 @@
 $ \textbf{hg qpush -a}
 (working directory not at tip)
 applying build-fix.patch
-Now at: build-fix.patch
+now at: build-fix.patch
--- a/en/examples/mq.tutorial.qnew2.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.tutorial.qnew2.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,15 +1,15 @@
 $ \textbf{hg qnew second.patch}
 $ \textbf{hg log --style=compact --limit=2}
-2[qtip,second.patch,tip]   
+2[qtip,second.patch,tip]      2009-01-30 06:34 +0000   bos
   [mq]: second.patch
 
-1[first.patch,qbase]   
+1[first.patch,qbase]      2009-01-30 06:34 +0000   bos
   [mq]: first.patch
 
 $ \textbf{echo 'line 4' >> file1}
 $ \textbf{hg qrefresh}
 $ \textbf{hg tip --style=compact --patch}
-2[qtip,second.patch,tip]   
+2[qtip,second.patch,tip]      2009-01-30 06:34 +0000   bos
   [mq]: second.patch
 
 diff -r  -r  file1
--- a/en/examples/mq.tutorial.qpop.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.tutorial.qpop.out	Mon Feb 09 22:59:50 2009 -0800
@@ -2,7 +2,7 @@
 first.patch
 second.patch
 $ \textbf{hg qpop}
-Now at: first.patch
+now at: first.patch
 $ \textbf{hg qseries}
 first.patch
 second.patch
--- a/en/examples/mq.tutorial.qpush-a.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.tutorial.qpush-a.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,6 +1,6 @@
 $ \textbf{hg qpush -a}
 applying second.patch
-Now at: second.patch
+now at: second.patch
 $ \textbf{cat file1}
 line 1
 line 2
--- a/en/examples/mq.tutorial.qrefresh.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.tutorial.qrefresh.out	Mon Feb 09 22:59:50 2009 -0800
@@ -9,7 +9,7 @@
 $ \textbf{hg qrefresh}
 $ \textbf{hg diff}
 $ \textbf{hg tip --style=compact --patch}
-1[qtip,first.patch,tip,qbase]   
+1[qtip,first.patch,tip,qbase]      2009-01-30 06:34 +0000   bos
   [mq]: first.patch
 
 diff -r  -r  file1
--- a/en/examples/mq.tutorial.qrefresh2.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/mq.tutorial.qrefresh2.out	Mon Feb 09 22:59:50 2009 -0800
@@ -3,7 +3,7 @@
 M file1
 $ \textbf{hg qrefresh}
 $ \textbf{hg tip --style=compact --patch}
-1[qtip,first.patch,tip,qbase]   
+1[qtip,first.patch,tip,qbase]      2009-01-30 06:34 +0000   bos
   [mq]: first.patch
 
 diff -r  -r  file1
--- a/en/examples/run-example	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/run-example	Mon Feb 09 22:59:50 2009 -0800
@@ -61,9 +61,10 @@
     
     timeout = 10
 
-    def __init__(self, name, verbose):
+    def __init__(self, name, verbose, keep_change):
         self.name = name
         self.verbose = verbose
+        self.keep_change = keep_change
         self.poll = select.poll()
 
     def parse(self):
@@ -320,7 +321,11 @@
             return False
         else:
             print >> sys.stderr, '\nOutput of %s has changed!' % base
-            os.system('diff -u %s %s 1>&2' % (oldname, errname))
+            if self.keep_change:
+                os.rename(errname, oldname)
+                return False
+            else:
+                os.system('diff -u %s %s 1>&2' % (oldname, errname))
             return True
 
 def print_help(exit, msg=None):
@@ -330,19 +335,23 @@
     print >> sys.stderr, 'Options:'
     print >> sys.stderr, '  -a --all       run all tests in this directory'
     print >> sys.stderr, '  -h --help      print this help message'
+    print >> sys.stderr, '     --help      keep new output as desired output'
     print >> sys.stderr, '  -v --verbose   display extra debug output'
     sys.exit(exit)
 
 def main(path='.'):
     opts, args = getopt.getopt(sys.argv[1:], '?ahv',
-                               ['all', 'help', 'verbose'])
+                               ['all', 'help', 'keep', 'verbose'])
     verbose = False
     run_all = False
+    keep_change = False
     for o, a in opts:
         if o in ('-h', '-?', '--help'):
             print_help(0)
         if o in ('-a', '--all'):
             run_all = True
+        if o in ('--keep',):
+            keep_change = True
         if o in ('-v', '--verbose'):
             verbose = True
     errs = 0
@@ -355,7 +364,7 @@
                 errs += 1
                 continue
             if stat.S_ISREG(st.st_mode) and st.st_mode & 0111:
-                if example(a, verbose).run():
+                if example(a, verbose, keep_change).run():
                     errs += 1
             else:
                 print >> sys.stderr, '%s: not a file, or not executable' % a
@@ -376,7 +385,7 @@
                     raise
                 continue
             if stat.S_ISREG(st.st_mode) and st.st_mode & 0111:
-                if example(pathname, verbose).run():
+                if example(pathname, verbose, keep_change).run():
                     errs += 1
         print >> open(os.path.join(path, '.run'), 'w'), time.asctime()
     else:
--- a/en/examples/template.svnstyle	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/template.svnstyle	Mon Feb 09 22:59:50 2009 -0800
@@ -34,6 +34,7 @@
 hg log -r0 --template '{node}'
 
 #$ name: simplest
+#$ ignore: \d+-\d+-\d+ \d+:\d+ \+.*
 
 cat svn.style
 hg log -r1 --style svn.style
--- a/en/examples/template.svnstyle.result.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/template.svnstyle.result.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,7 +1,7 @@
 $ \textbf{hg log -r1 --style svn.style}
 ------------------------------------------------------------------------
 
-r1 | bos 
+r1 | bos | 2009-01-30 06:40 +0000 (Fri, 30 Jan 2009 06:40:17 +0000)
 
 added line to end of <<hello>> file.
 
--- a/en/examples/tour-merge-conflict	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/tour-merge-conflict	Mon Feb 09 22:59:50 2009 -0800
@@ -56,6 +56,7 @@
 #$ ignore: [<>]{7} /tmp/.*
 
 export HGMERGE=merge
+echo 'XXX this is broken and must be fixed'
 hg merge
 cat letter.txt
 
--- a/en/examples/tour-merge-conflict.merge.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/tour-merge-conflict.merge.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,4 +1,6 @@
 $ \textbf{export HGMERGE=merge}
+$ \textbf{echo 'XXX this is broken and must be fixed'}
+XXX this is broken and must be fixed
 $ \textbf{hg merge}
 merging letter.txt
 merge: warning: conflicts during merge
--- a/en/examples/tour.help.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/tour.help.out	Mon Feb 09 22:59:50 2009 -0800
@@ -9,8 +9,7 @@
     If no directory is given, the current directory is used.
 
     It is possible to specify an ssh:// URL as the destination.
-    Look at the help text for the pull command for important details
-    about ssh:// URLs.
+    See 'hg help urls' for more information.
 
 options:
 
--- a/en/examples/tour.ls.out	Wed Jan 21 14:16:38 2009 +0100
+++ b/en/examples/tour.ls.out	Mon Feb 09 22:59:50 2009 -0800
@@ -1,5 +1,5 @@
 $ \textbf{ls -l}
-total 4
+
 
 $ \textbf{ls hello}
 Makefile  hello.c
--- a/en/filenames.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,306 +0,0 @@
-\chapter{File names and pattern matching}
-\label{chap:names}
-
-Mercurial provides mechanisms that let you work with file names in a
-consistent and expressive way.
-
-\section{Simple file naming}
-
-Mercurial uses a unified piece of machinery ``under the hood'' to
-handle file names.  Every command behaves uniformly with respect to
-file names.  The way in which commands work with file names is as
-follows.
-
-If you explicitly name real files on the command line, Mercurial works
-with exactly those files, as you would expect.
-\interaction{filenames.files}
-
-When you provide a directory name, Mercurial will interpret this as
-``operate on every file in this directory and its subdirectories''.
-Mercurial traverses the files and subdirectories in a directory in
-alphabetical order.  When it encounters a subdirectory, it will
-traverse that subdirectory before continuing with the current
-directory.
-\interaction{filenames.dirs}
-
-\section{Running commands without any file names}
-
-Mercurial's commands that work with file names have useful default
-behaviours when you invoke them without providing any file names or
-patterns.  What kind of behaviour you should expect depends on what
-the command does.  Here are a few rules of thumb you can use to
-predict what a command is likely to do if you don't give it any names
-to work with.
-\begin{itemize}
-\item Most commands will operate on the entire working directory.
-  This is what the \hgcmd{add} command does, for example.
-\item If the command has effects that are difficult or impossible to
-  reverse, it will force you to explicitly provide at least one name
-  or pattern (see below).  This protects you from accidentally
-  deleting files by running \hgcmd{remove} with no arguments, for
-  example.
-\end{itemize}
-
-It's easy to work around these default behaviours if they don't suit
-you.  If a command normally operates on the whole working directory,
-you can invoke it on just the current directory and its subdirectories
-by giving it the name ``\dirname{.}''.
-\interaction{filenames.wdir-subdir}
-
-Along the same lines, some commands normally print file names relative
-to the root of the repository, even if you're invoking them from a
-subdirectory.  Such a command will print file names relative to your
-subdirectory if you give it explicit names.  Here, we're going to run
-\hgcmd{status} from a subdirectory, and get it to operate on the
-entire working directory while printing file names relative to our
-subdirectory, by passing it the output of the \hgcmd{root} command.
-\interaction{filenames.wdir-relname}
-
-\section{Telling you what's going on}
-
-The \hgcmd{add} example in the preceding section illustrates something
-else that's helpful about Mercurial commands.  If a command operates
-on a file that you didn't name explicitly on the command line, it will
-usually print the name of the file, so that you will not be surprised
-what's going on.
-
-The principle here is of \emph{least surprise}.  If you've exactly
-named a file on the command line, there's no point in repeating it
-back at you.  If Mercurial is acting on a file \emph{implicitly},
-because you provided no names, or a directory, or a pattern (see
-below), it's safest to tell you what it's doing.
-
-For commands that behave this way, you can silence them using the
-\hggopt{-q} option.  You can also get them to print the name of every
-file, even those you've named explicitly, using the \hggopt{-v}
-option.
-
-\section{Using patterns to identify files}
-
-In addition to working with file and directory names, Mercurial lets
-you use \emph{patterns} to identify files.  Mercurial's pattern
-handling is expressive.
-
-On Unix-like systems (Linux, MacOS, etc.), the job of matching file
-names to patterns normally falls to the shell.  On these systems, you
-must explicitly tell Mercurial that a name is a pattern.  On Windows,
-the shell does not expand patterns, so Mercurial will automatically
-identify names that are patterns, and expand them for you.
-
-To provide a pattern in place of a regular name on the command line,
-the mechanism is simple:
-\begin{codesample2}
-  syntax:patternbody
-\end{codesample2}
-That is, a pattern is identified by a short text string that says what
-kind of pattern this is, followed by a colon, followed by the actual
-pattern.
-
-Mercurial supports two kinds of pattern syntax.  The most frequently
-used is called \texttt{glob}; this is the same kind of pattern
-matching used by the Unix shell, and should be familiar to Windows
-command prompt users, too.  
-
-When Mercurial does automatic pattern matching on Windows, it uses
-\texttt{glob} syntax.  You can thus omit the ``\texttt{glob:}'' prefix
-on Windows, but it's safe to use it, too.
-
-The \texttt{re} syntax is more powerful; it lets you specify patterns
-using regular expressions, also known as regexps.
-
-By the way, in the examples that follow, notice that I'm careful to
-wrap all of my patterns in quote characters, so that they won't get
-expanded by the shell before Mercurial sees them.
-
-\subsection{Shell-style \texttt{glob} patterns}
-
-This is an overview of the kinds of patterns you can use when you're
-matching on glob patterns.
-
-The ``\texttt{*}'' character matches any string, within a single
-directory.
-\interaction{filenames.glob.star}
-
-The ``\texttt{**}'' pattern matches any string, and crosses directory
-boundaries.  It's not a standard Unix glob token, but it's accepted by
-several popular Unix shells, and is very useful.
-\interaction{filenames.glob.starstar}
-
-The ``\texttt{?}'' pattern matches any single character.
-\interaction{filenames.glob.question}
-
-The ``\texttt{[}'' character begins a \emph{character class}.  This
-matches any single character within the class.  The class ends with a
-``\texttt{]}'' character.  A class may contain multiple \emph{range}s
-of the form ``\texttt{a-f}'', which is shorthand for
-``\texttt{abcdef}''.
-\interaction{filenames.glob.range}
-If the first character after the ``\texttt{[}'' in a character class
-is a ``\texttt{!}'', it \emph{negates} the class, making it match any
-single character not in the class.
-
-A ``\texttt{\{}'' begins a group of subpatterns, where the whole group
-matches if any subpattern in the group matches.  The ``\texttt{,}''
-character separates subpatterns, and ``\texttt{\}}'' ends the group.
-\interaction{filenames.glob.group}
-
-\subsubsection{Watch out!}
-
-Don't forget that if you want to match a pattern in any directory, you
-should not be using the ``\texttt{*}'' match-any token, as this will
-only match within one directory.  Instead, use the ``\texttt{**}''
-token.  This small example illustrates the difference between the two.
-\interaction{filenames.glob.star-starstar}
-
-\subsection{Regular expression matching with \texttt{re} patterns}
-
-Mercurial accepts the same regular expression syntax as the Python
-programming language (it uses Python's regexp engine internally).
-This is based on the Perl language's regexp syntax, which is the most
-popular dialect in use (it's also used in Java, for example).
-
-I won't discuss Mercurial's regexp dialect in any detail here, as
-regexps are not often used.  Perl-style regexps are in any case
-already exhaustively documented on a multitude of web sites, and in
-many books.  Instead, I will focus here on a few things you should
-know if you find yourself needing to use regexps with Mercurial.
-
-A regexp is matched against an entire file name, relative to the root
-of the repository.  In other words, even if you're already in
-subbdirectory \dirname{foo}, if you want to match files under this
-directory, your pattern must start with ``\texttt{foo/}''.
-
-One thing to note, if you're familiar with Perl-style regexps, is that
-Mercurial's are \emph{rooted}.  That is, a regexp starts matching
-against the beginning of a string; it doesn't look for a match
-anywhere within the string.  To match anywhere in a string, start
-your pattern with ``\texttt{.*}''.
-
-\section{Filtering files}
-
-Not only does Mercurial give you a variety of ways to specify files;
-it lets you further winnow those files using \emph{filters}.  Commands
-that work with file names accept two filtering options.
-\begin{itemize}
-\item \hggopt{-I}, or \hggopt{--include}, lets you specify a pattern
-  that file names must match in order to be processed.
-\item \hggopt{-X}, or \hggopt{--exclude}, gives you a way to
-  \emph{avoid} processing files, if they match this pattern.
-\end{itemize}
-You can provide multiple \hggopt{-I} and \hggopt{-X} options on the
-command line, and intermix them as you please.  Mercurial interprets
-the patterns you provide using glob syntax by default (but you can use
-regexps if you need to).
-
-You can read a \hggopt{-I} filter as ``process only the files that
-match this filter''.
-\interaction{filenames.filter.include}
-The \hggopt{-X} filter is best read as ``process only the files that
-don't match this pattern''.
-\interaction{filenames.filter.exclude}
-
-\section{Ignoring unwanted files and directories}
-
-XXX.
-
-\section{Case sensitivity}
-\label{sec:names:case}
-
-If you're working in a mixed development environment that contains
-both Linux (or other Unix) systems and Macs or Windows systems, you
-should keep in the back of your mind the knowledge that they treat the
-case (``N'' versus ``n'') of file names in incompatible ways.  This is
-not very likely to affect you, and it's easy to deal with if it does,
-but it could surprise you if you don't know about it.
-
-Operating systems and filesystems differ in the way they handle the
-\emph{case} of characters in file and directory names.  There are
-three common ways to handle case in names.
-\begin{itemize}
-\item Completely case insensitive.  Uppercase and lowercase versions
-  of a letter are treated as identical, both when creating a file and
-  during subsequent accesses.  This is common on older DOS-based
-  systems.
-\item Case preserving, but insensitive.  When a file or directory is
-  created, the case of its name is stored, and can be retrieved and
-  displayed by the operating system.  When an existing file is being
-  looked up, its case is ignored.  This is the standard arrangement on
-  Windows and MacOS.  The names \filename{foo} and \filename{FoO}
-  identify the same file.  This treatment of uppercase and lowercase
-  letters as interchangeable is also referred to as \emph{case
-    folding}.
-\item Case sensitive.  The case of a name is significant at all times.
-  The names \filename{foo} and {FoO} identify different files.  This
-  is the way Linux and Unix systems normally work.
-\end{itemize}
-
-On Unix-like systems, it is possible to have any or all of the above
-ways of handling case in action at once.  For example, if you use a
-USB thumb drive formatted with a FAT32 filesystem on a Linux system,
-Linux will handle names on that filesystem in a case preserving, but
-insensitive, way.
-
-\subsection{Safe, portable repository storage}
-
-Mercurial's repository storage mechanism is \emph{case safe}.  It
-translates file names so that they can be safely stored on both case
-sensitive and case insensitive filesystems.  This means that you can
-use normal file copying tools to transfer a Mercurial repository onto,
-for example, a USB thumb drive, and safely move that drive and
-repository back and forth between a Mac, a PC running Windows, and a
-Linux box.
-
-\subsection{Detecting case conflicts}
-
-When operating in the working directory, Mercurial honours the naming
-policy of the filesystem where the working directory is located.  If
-the filesystem is case preserving, but insensitive, Mercurial will
-treat names that differ only in case as the same.
-
-An important aspect of this approach is that it is possible to commit
-a changeset on a case sensitive (typically Linux or Unix) filesystem
-that will cause trouble for users on case insensitive (usually Windows
-and MacOS) users.  If a Linux user commits changes to two files, one
-named \filename{myfile.c} and the other named \filename{MyFile.C},
-they will be stored correctly in the repository.  And in the working
-directories of other Linux users, they will be correctly represented
-as separate files.
-
-If a Windows or Mac user pulls this change, they will not initially
-have a problem, because Mercurial's repository storage mechanism is
-case safe.  However, once they try to \hgcmd{update} the working
-directory to that changeset, or \hgcmd{merge} with that changeset,
-Mercurial will spot the conflict between the two file names that the
-filesystem would treat as the same, and forbid the update or merge
-from occurring.
-
-\subsection{Fixing a case conflict}
-
-If you are using Windows or a Mac in a mixed environment where some of
-your collaborators are using Linux or Unix, and Mercurial reports a
-case folding conflict when you try to \hgcmd{update} or \hgcmd{merge},
-the procedure to fix the problem is simple.
-
-Just find a nearby Linux or Unix box, clone the problem repository
-onto it, and use Mercurial's \hgcmd{rename} command to change the
-names of any offending files or directories so that they will no
-longer cause case folding conflicts.  Commit this change, \hgcmd{pull}
-or \hgcmd{push} it across to your Windows or MacOS system, and
-\hgcmd{update} to the revision with the non-conflicting names.
-
-The changeset with case-conflicting names will remain in your
-project's history, and you still won't be able to \hgcmd{update} your
-working directory to that changeset on a Windows or MacOS system, but
-you can continue development unimpeded.
-
-\begin{note}
-  Prior to version~0.9.3, Mercurial did not use a case safe repository
-  storage mechanism, and did not detect case folding conflicts.  If
-  you are using an older version of Mercurial on Windows or MacOS, I
-  strongly recommend that you upgrade.
-\end{note}
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/hgext.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,429 +0,0 @@
-\chapter{Adding functionality with extensions}
-\label{chap:hgext}
-
-While the core of Mercurial is quite complete from a functionality
-standpoint, it's deliberately shorn of fancy features.  This approach
-of preserving simplicity keeps the software easy to deal with for both
-maintainers and users.
-
-However, Mercurial doesn't box you in with an inflexible command set:
-you can add features to it as \emph{extensions} (sometimes known as
-\emph{plugins}).  We've already discussed a few of these extensions in
-earlier chapters.
-\begin{itemize}
-\item Section~\ref{sec:tour-merge:fetch} covers the \hgext{fetch}
-  extension; this combines pulling new changes and merging them with
-  local changes into a single command, \hgxcmd{fetch}{fetch}.
-\item In chapter~\ref{chap:hook}, we covered several extensions that
-  are useful for hook-related functionality: \hgext{acl} adds access
-  control lists; \hgext{bugzilla} adds integration with the Bugzilla
-  bug tracking system; and \hgext{notify} sends notification emails on
-  new changes.
-\item The Mercurial Queues patch management extension is so invaluable
-  that it merits two chapters and an appendix all to itself.
-  Chapter~\ref{chap:mq} covers the basics;
-  chapter~\ref{chap:mq-collab} discusses advanced topics; and
-  appendix~\ref{chap:mqref} goes into detail on each command.
-\end{itemize}
-
-In this chapter, we'll cover some of the other extensions that are
-available for Mercurial, and briefly touch on some of the machinery
-you'll need to know about if you want to write an extension of your
-own.
-\begin{itemize}
-\item In section~\ref{sec:hgext:inotify}, we'll discuss the
-  possibility of \emph{huge} performance improvements using the
-  \hgext{inotify} extension.
-\end{itemize}
-
-\section{Improve performance with the \hgext{inotify} extension}
-\label{sec:hgext:inotify}
-
-Are you interested in having some of the most common Mercurial
-operations run as much as a hundred times faster?  Read on!
-
-Mercurial has great performance under normal circumstances.  For
-example, when you run the \hgcmd{status} command, Mercurial has to
-scan almost every directory and file in your repository so that it can
-display file status.  Many other Mercurial commands need to do the
-same work behind the scenes; for example, the \hgcmd{diff} command
-uses the status machinery to avoid doing an expensive comparison
-operation on files that obviously haven't changed.
-
-Because obtaining file status is crucial to good performance, the
-authors of Mercurial have optimised this code to within an inch of its
-life.  However, there's no avoiding the fact that when you run
-\hgcmd{status}, Mercurial is going to have to perform at least one
-expensive system call for each managed file to determine whether it's
-changed since the last time Mercurial checked.  For a sufficiently
-large repository, this can take a long time.
-
-To put a number on the magnitude of this effect, I created a
-repository containing 150,000 managed files.  I timed \hgcmd{status}
-as taking ten seconds to run, even when \emph{none} of those files had
-been modified.
-
-Many modern operating systems contain a file notification facility.
-If a program signs up to an appropriate service, the operating system
-will notify it every time a file of interest is created, modified, or
-deleted.  On Linux systems, the kernel component that does this is
-called \texttt{inotify}.
-
-Mercurial's \hgext{inotify} extension talks to the kernel's
-\texttt{inotify} component to optimise \hgcmd{status} commands.  The
-extension has two components.  A daemon sits in the background and
-receives notifications from the \texttt{inotify} subsystem.  It also
-listens for connections from a regular Mercurial command.  The
-extension modifies Mercurial's behaviour so that instead of scanning
-the filesystem, it queries the daemon.  Since the daemon has perfect
-information about the state of the repository, it can respond with a
-result instantaneously, avoiding the need to scan every directory and
-file in the repository.
-
-Recall the ten seconds that I measured plain Mercurial as taking to
-run \hgcmd{status} on a 150,000 file repository.  With the
-\hgext{inotify} extension enabled, the time dropped to 0.1~seconds, a
-factor of \emph{one hundred} faster.
-
-Before we continue, please pay attention to some caveats.
-\begin{itemize}
-\item The \hgext{inotify} extension is Linux-specific.  Because it
-  interfaces directly to the Linux kernel's \texttt{inotify}
-  subsystem, it does not work on other operating systems.
-\item It should work on any Linux distribution that was released after
-  early~2005.  Older distributions are likely to have a kernel that
-  lacks \texttt{inotify}, or a version of \texttt{glibc} that does not
-  have the necessary interfacing support.
-\item Not all filesystems are suitable for use with the
-  \hgext{inotify} extension.  Network filesystems such as NFS are a
-  non-starter, for example, particularly if you're running Mercurial
-  on several systems, all mounting the same network filesystem.  The
-  kernel's \texttt{inotify} system has no way of knowing about changes
-  made on another system.  Most local filesystems (e.g.~ext3, XFS,
-  ReiserFS) should work fine.
-\end{itemize}
-
-The \hgext{inotify} extension is not yet shipped with Mercurial as of
-May~2007, so it's a little more involved to set up than other
-extensions.  But the performance improvement is worth it!
-
-The extension currently comes in two parts: a set of patches to the
-Mercurial source code, and a library of Python bindings to the
-\texttt{inotify} subsystem.
-\begin{note}
-  There are \emph{two} Python \texttt{inotify} binding libraries.  One
-  of them is called \texttt{pyinotify}, and is packaged by some Linux
-  distributions as \texttt{python-inotify}.  This is \emph{not} the
-  one you'll need, as it is too buggy and inefficient to be practical.
-\end{note}
-To get going, it's best to already have a functioning copy of
-Mercurial installed.
-\begin{note}
-  If you follow the instructions below, you'll be \emph{replacing} and
-  overwriting any existing installation of Mercurial that you might
-  already have, using the latest ``bleeding edge'' Mercurial code.
-  Don't say you weren't warned!
-\end{note}
-\begin{enumerate}
-\item Clone the Python \texttt{inotify} binding repository.  Build and
-  install it.
-  \begin{codesample4}
-    hg clone http://hg.kublai.com/python/inotify
-    cd inotify
-    python setup.py build --force
-    sudo python setup.py install --skip-build
-  \end{codesample4}
-\item Clone the \dirname{crew} Mercurial repository.  Clone the
-  \hgext{inotify} patch repository so that Mercurial Queues will be
-  able to apply patches to your cope of the \dirname{crew} repository.
-  \begin{codesample4}
-    hg clone http://hg.intevation.org/mercurial/crew
-    hg clone crew inotify
-    hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches
-  \end{codesample4}
-\item Make sure that you have the Mercurial Queues extension,
-  \hgext{mq}, enabled.  If you've never used MQ, read
-  section~\ref{sec:mq:start} to get started quickly.
-\item Go into the \dirname{inotify} repo, and apply all of the
-  \hgext{inotify} patches using the \hgxopt{mq}{qpush}{-a} option to
-  the \hgxcmd{mq}{qpush} command.
-  \begin{codesample4}
-    cd inotify
-    hg qpush -a
-  \end{codesample4}
-  If you get an error message from \hgxcmd{mq}{qpush}, you should not
-  continue.  Instead, ask for help.
-\item Build and install the patched version of Mercurial.
-  \begin{codesample4}
-    python setup.py build --force
-    sudo python setup.py install --skip-build
-  \end{codesample4}
-\end{enumerate}
-Once you've build a suitably patched version of Mercurial, all you
-need to do to enable the \hgext{inotify} extension is add an entry to
-your \hgrc.
-\begin{codesample2}
-  [extensions]
-  inotify =
-\end{codesample2}
-When the \hgext{inotify} extension is enabled, Mercurial will
-automatically and transparently start the status daemon the first time
-you run a command that needs status in a repository.  It runs one
-status daemon per repository.
-
-The status daemon is started silently, and runs in the background.  If
-you look at a list of running processes after you've enabled the
-\hgext{inotify} extension and run a few commands in different
-repositories, you'll thus see a few \texttt{hg} processes sitting
-around, waiting for updates from the kernel and queries from
-Mercurial.
-
-The first time you run a Mercurial command in a repository when you
-have the \hgext{inotify} extension enabled, it will run with about the
-same performance as a normal Mercurial command.  This is because the
-status daemon needs to perform a normal status scan so that it has a
-baseline against which to apply later updates from the kernel.
-However, \emph{every} subsequent command that does any kind of status
-check should be noticeably faster on repositories of even fairly
-modest size.  Better yet, the bigger your repository is, the greater a
-performance advantage you'll see.  The \hgext{inotify} daemon makes
-status operations almost instantaneous on repositories of all sizes!
-
-If you like, you can manually start a status daemon using the
-\hgxcmd{inotify}{inserve} command.  This gives you slightly finer
-control over how the daemon ought to run.  This command will of course
-only be available when the \hgext{inotify} extension is enabled.
-
-When you're using the \hgext{inotify} extension, you should notice
-\emph{no difference at all} in Mercurial's behaviour, with the sole
-exception of status-related commands running a whole lot faster than
-they used to.  You should specifically expect that commands will not
-print different output; neither should they give different results.
-If either of these situations occurs, please report a bug.
-
-\section{Flexible diff support with the \hgext{extdiff} extension}
-\label{sec:hgext:extdiff}
-
-Mercurial's built-in \hgcmd{diff} command outputs plaintext unified
-diffs.
-\interaction{extdiff.diff}
-If you would like to use an external tool to display modifications,
-you'll want to use the \hgext{extdiff} extension.  This will let you
-use, for example, a graphical diff tool.
-
-The \hgext{extdiff} extension is bundled with Mercurial, so it's easy
-to set up.  In the \rcsection{extensions} section of your \hgrc,
-simply add a one-line entry to enable the extension.
-\begin{codesample2}
-  [extensions]
-  extdiff =
-\end{codesample2}
-This introduces a command named \hgxcmd{extdiff}{extdiff}, which by
-default uses your system's \command{diff} command to generate a
-unified diff in the same form as the built-in \hgcmd{diff} command.
-\interaction{extdiff.extdiff}
-The result won't be exactly the same as with the built-in \hgcmd{diff}
-variations, because the output of \command{diff} varies from one
-system to another, even when passed the same options.
-
-As the ``\texttt{making snapshot}'' lines of output above imply, the
-\hgxcmd{extdiff}{extdiff} command works by creating two snapshots of
-your source tree.  The first snapshot is of the source revision; the
-second, of the target revision or working directory.  The
-\hgxcmd{extdiff}{extdiff} command generates these snapshots in a
-temporary directory, passes the name of each directory to an external
-diff viewer, then deletes the temporary directory.  For efficiency, it
-only snapshots the directories and files that have changed between the
-two revisions.
-
-Snapshot directory names have the same base name as your repository.
-If your repository path is \dirname{/quux/bar/foo}, then \dirname{foo}
-will be the name of each snapshot directory.  Each snapshot directory
-name has its changeset ID appended, if appropriate.  If a snapshot is
-of revision \texttt{a631aca1083f}, the directory will be named
-\dirname{foo.a631aca1083f}.  A snapshot of the working directory won't
-have a changeset ID appended, so it would just be \dirname{foo} in
-this example.  To see what this looks like in practice, look again at
-the \hgxcmd{extdiff}{extdiff} example above.  Notice that the diff has
-the snapshot directory names embedded in its header.
-
-The \hgxcmd{extdiff}{extdiff} command accepts two important options.
-The \hgxopt{extdiff}{extdiff}{-p} option lets you choose a program to
-view differences with, instead of \command{diff}.  With the
-\hgxopt{extdiff}{extdiff}{-o} option, you can change the options that
-\hgxcmd{extdiff}{extdiff} passes to the program (by default, these
-options are ``\texttt{-Npru}'', which only make sense if you're
-running \command{diff}).  In other respects, the
-\hgxcmd{extdiff}{extdiff} command acts similarly to the built-in
-\hgcmd{diff} command: you use the same option names, syntax, and
-arguments to specify the revisions you want, the files you want, and
-so on.
-
-As an example, here's how to run the normal system \command{diff}
-command, getting it to generate context diffs (using the
-\cmdopt{diff}{-c} option) instead of unified diffs, and five lines of
-context instead of the default three (passing \texttt{5} as the
-argument to the \cmdopt{diff}{-C} option).
-\interaction{extdiff.extdiff-ctx}
-
-Launching a visual diff tool is just as easy.  Here's how to launch
-the \command{kdiff3} viewer.
-\begin{codesample2}
-  hg extdiff -p kdiff3 -o ''
-\end{codesample2}
-
-If your diff viewing command can't deal with directories, you can
-easily work around this with a little scripting.  For an example of
-such scripting in action with the \hgext{mq} extension and the
-\command{interdiff} command, see
-section~\ref{mq-collab:tips:interdiff}.
-
-\subsection{Defining command aliases}
-
-It can be cumbersome to remember the options to both the
-\hgxcmd{extdiff}{extdiff} command and the diff viewer you want to use,
-so the \hgext{extdiff} extension lets you define \emph{new} commands
-that will invoke your diff viewer with exactly the right options.
-
-All you need to do is edit your \hgrc, and add a section named
-\rcsection{extdiff}.  Inside this section, you can define multiple
-commands.  Here's how to add a \texttt{kdiff3} command.  Once you've
-defined this, you can type ``\texttt{hg kdiff3}'' and the
-\hgext{extdiff} extension will run \command{kdiff3} for you.
-\begin{codesample2}
-  [extdiff]
-  cmd.kdiff3 =
-\end{codesample2}
-If you leave the right hand side of the definition empty, as above,
-the \hgext{extdiff} extension uses the name of the command you defined
-as the name of the external program to run.  But these names don't
-have to be the same.  Here, we define a command named ``\texttt{hg
-  wibble}'', which runs \command{kdiff3}.
-\begin{codesample2}
-  [extdiff]
-  cmd.wibble = kdiff3
-\end{codesample2}
-
-You can also specify the default options that you want to invoke your
-diff viewing program with.  The prefix to use is ``\texttt{opts.}'',
-followed by the name of the command to which the options apply.  This
-example defines a ``\texttt{hg vimdiff}'' command that runs the
-\command{vim} editor's \texttt{DirDiff} extension.
-\begin{codesample2}
-  [extdiff]  
-  cmd.vimdiff = vim
-  opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'
-\end{codesample2}
-
-\section{Cherrypicking changes with the \hgext{transplant} extension}
-\label{sec:hgext:transplant}
-
-Need to have a long chat with Brendan about this.
-
-\section{Send changes via email with the \hgext{patchbomb} extension}
-\label{sec:hgext:patchbomb}
-
-Many projects have a culture of ``change review'', in which people
-send their modifications to a mailing list for others to read and
-comment on before they commit the final version to a shared
-repository.  Some projects have people who act as gatekeepers; they
-apply changes from other people to a repository to which those others
-don't have access.
-
-Mercurial makes it easy to send changes over email for review or
-application, via its \hgext{patchbomb} extension.  The extension is so
-namd because changes are formatted as patches, and it's usual to send
-one changeset per email message.  Sending a long series of changes by
-email is thus much like ``bombing'' the recipient's inbox, hence
-``patchbomb''.
-
-As usual, the basic configuration of the \hgext{patchbomb} extension
-takes just one or two lines in your \hgrc.
-\begin{codesample2}
-  [extensions]
-  patchbomb =
-\end{codesample2}
-Once you've enabled the extension, you will have a new command
-available, named \hgxcmd{patchbomb}{email}.
-
-The safest and best way to invoke the \hgxcmd{patchbomb}{email}
-command is to \emph{always} run it first with the
-\hgxopt{patchbomb}{email}{-n} option.  This will show you what the
-command \emph{would} send, without actually sending anything.  Once
-you've had a quick glance over the changes and verified that you are
-sending the right ones, you can rerun the same command, with the
-\hgxopt{patchbomb}{email}{-n} option removed.
-
-The \hgxcmd{patchbomb}{email} command accepts the same kind of
-revision syntax as every other Mercurial command.  For example, this
-command will send every revision between 7 and \texttt{tip},
-inclusive.
-\begin{codesample2}
-  hg email -n 7:tip
-\end{codesample2}
-You can also specify a \emph{repository} to compare with.  If you
-provide a repository but no revisions, the \hgxcmd{patchbomb}{email}
-command will send all revisions in the local repository that are not
-present in the remote repository.  If you additionally specify
-revisions or a branch name (the latter using the
-\hgxopt{patchbomb}{email}{-b} option), this will constrain the
-revisions sent.
-
-It's perfectly safe to run the \hgxcmd{patchbomb}{email} command
-without the names of the people you want to send to: if you do this,
-it will just prompt you for those values interactively.  (If you're
-using a Linux or Unix-like system, you should have enhanced
-\texttt{readline}-style editing capabilities when entering those
-headers, too, which is useful.)
-
-When you are sending just one revision, the \hgxcmd{patchbomb}{email}
-command will by default use the first line of the changeset
-description as the subject of the single email message it sends.
-
-If you send multiple revisions, the \hgxcmd{patchbomb}{email} command
-will usually send one message per changeset.  It will preface the
-series with an introductory message, in which you should describe the
-purpose of the series of changes you're sending.
-
-\subsection{Changing the behaviour of patchbombs}
-
-Not every project has exactly the same conventions for sending changes
-in email; the \hgext{patchbomb} extension tries to accommodate a
-number of variations through command line options.
-\begin{itemize}
-\item You can write a subject for the introductory message on the
-  command line using the \hgxopt{patchbomb}{email}{-s} option.  This
-  takes one argument, the text of the subject to use.
-\item To change the email address from which the messages originate,
-  use the \hgxopt{patchbomb}{email}{-f} option.  This takes one
-  argument, the email address to use.
-\item The default behaviour is to send unified diffs (see
-  section~\ref{sec:mq:patch} for a description of the format), one per
-  message.  You can send a binary bundle instead with the
-  \hgxopt{patchbomb}{email}{-b} option.  
-\item Unified diffs are normally prefaced with a metadata header.  You
-  can omit this, and send unadorned diffs, with the
-  \hgxopt{patchbomb}{email}{--plain} option.
-\item Diffs are normally sent ``inline'', in the same body part as the
-  description of a patch.  This makes it easiest for the largest
-  number of readers to quote and respond to parts of a diff, as some
-  mail clients will only quote the first MIME body part in a message.
-  If you'd prefer to send the description and the diff in separate
-  body parts, use the \hgxopt{patchbomb}{email}{-a} option.
-\item Instead of sending mail messages, you can write them to an
-  \texttt{mbox}-format mail folder using the
-  \hgxopt{patchbomb}{email}{-m} option.  That option takes one
-  argument, the name of the file to write to.
-\item If you would like to add a \command{diffstat}-format summary to
-  each patch, and one to the introductory message, use the
-  \hgxopt{patchbomb}{email}{-d} option.  The \command{diffstat}
-  command displays a table containing the name of each file patched,
-  the number of lines affected, and a histogram showing how much each
-  file is modified.  This gives readers a qualitative glance at how
-  complex a patch is.
-\end{itemize}
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/hook.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1413 +0,0 @@
-\chapter{Handling repository events with hooks}
-\label{chap:hook}
-
-Mercurial offers a powerful mechanism to let you perform automated
-actions in response to events that occur in a repository.  In some
-cases, you can even control Mercurial's response to those events.
-
-The name Mercurial uses for one of these actions is a \emph{hook}.
-Hooks are called ``triggers'' in some revision control systems, but
-the two names refer to the same idea.
-
-\section{An overview of hooks in Mercurial}
-
-Here is a brief list of the hooks that Mercurial supports.  We will
-revisit each of these hooks in more detail later, in
-section~\ref{sec:hook:ref}.
-
-\begin{itemize}
-\item[\small\hook{changegroup}] This is run after a group of
-  changesets has been brought into the repository from elsewhere.
-\item[\small\hook{commit}] This is run after a new changeset has been
-  created in the local repository.
-\item[\small\hook{incoming}] This is run once for each new changeset
-  that is brought into the repository from elsewhere.  Notice the
-  difference from \hook{changegroup}, which is run once per
-  \emph{group} of changesets brought in.
-\item[\small\hook{outgoing}] This is run after a group of changesets
-  has been transmitted from this repository.
-\item[\small\hook{prechangegroup}] This is run before starting to
-  bring a group of changesets into the repository.
-\item[\small\hook{precommit}] Controlling. This is run before starting
-  a commit.
-\item[\small\hook{preoutgoing}] Controlling. This is run before
-  starting to transmit a group of changesets from this repository.
-\item[\small\hook{pretag}] Controlling. This is run before creating a tag.
-\item[\small\hook{pretxnchangegroup}] Controlling. This is run after a
-  group of changesets has been brought into the local repository from
-  another, but before the transaction completes that will make the
-  changes permanent in the repository.
-\item[\small\hook{pretxncommit}] Controlling. This is run after a new
-  changeset has been created in the local repository, but before the
-  transaction completes that will make it permanent.
-\item[\small\hook{preupdate}] Controlling. This is run before starting
-  an update or merge of the working directory.
-\item[\small\hook{tag}] This is run after a tag is created.
-\item[\small\hook{update}] This is run after an update or merge of the
-  working directory has finished.
-\end{itemize}
-Each of the hooks whose description begins with the word
-``Controlling'' has the ability to determine whether an activity can
-proceed.  If the hook succeeds, the activity may proceed; if it fails,
-the activity is either not permitted or undone, depending on the hook.
-
-\section{Hooks and security}
-
-\subsection{Hooks are run with your privileges}
-
-When you run a Mercurial command in a repository, and the command
-causes a hook to run, that hook runs on \emph{your} system, under
-\emph{your} user account, with \emph{your} privilege level.  Since
-hooks are arbitrary pieces of executable code, you should treat them
-with an appropriate level of suspicion.  Do not install a hook unless
-you are confident that you know who created it and what it does.
-
-In some cases, you may be exposed to hooks that you did not install
-yourself.  If you work with Mercurial on an unfamiliar system,
-Mercurial will run hooks defined in that system's global \hgrc\ file.
-
-If you are working with a repository owned by another user, Mercurial
-can run hooks defined in that user's repository, but it will still run
-them as ``you''.  For example, if you \hgcmd{pull} from that
-repository, and its \sfilename{.hg/hgrc} defines a local
-\hook{outgoing} hook, that hook will run under your user account, even
-though you don't own that repository.
-
-\begin{note}
-  This only applies if you are pulling from a repository on a local or
-  network filesystem.  If you're pulling over http or ssh, any
-  \hook{outgoing} hook will run under whatever account is executing
-  the server process, on the server.
-\end{note}
-
-XXX To see what hooks are defined in a repository, use the
-\hgcmdargs{config}{hooks} command.  If you are working in one
-repository, but talking to another that you do not own (e.g.~using
-\hgcmd{pull} or \hgcmd{incoming}), remember that it is the other
-repository's hooks you should be checking, not your own.
-
-\subsection{Hooks do not propagate}
-
-In Mercurial, hooks are not revision controlled, and do not propagate
-when you clone, or pull from, a repository.  The reason for this is
-simple: a hook is a completely arbitrary piece of executable code.  It
-runs under your user identity, with your privilege level, on your
-machine.
-
-It would be extremely reckless for any distributed revision control
-system to implement revision-controlled hooks, as this would offer an
-easily exploitable way to subvert the accounts of users of the
-revision control system.
-
-Since Mercurial does not propagate hooks, if you are collaborating
-with other people on a common project, you should not assume that they
-are using the same Mercurial hooks as you are, or that theirs are
-correctly configured.  You should document the hooks you expect people
-to use.
-
-In a corporate intranet, this is somewhat easier to control, as you
-can for example provide a ``standard'' installation of Mercurial on an
-NFS filesystem, and use a site-wide \hgrc\ file to define hooks that
-all users will see.  However, this too has its limits; see below.
-
-\subsection{Hooks can be overridden}
-
-Mercurial allows you to override a hook definition by redefining the
-hook.  You can disable it by setting its value to the empty string, or
-change its behaviour as you wish.
-
-If you deploy a system-~or site-wide \hgrc\ file that defines some
-hooks, you should thus understand that your users can disable or
-override those hooks.
-
-\subsection{Ensuring that critical hooks are run}
-
-Sometimes you may want to enforce a policy that you do not want others
-to be able to work around.  For example, you may have a requirement
-that every changeset must pass a rigorous set of tests.  Defining this
-requirement via a hook in a site-wide \hgrc\ won't work for remote
-users on laptops, and of course local users can subvert it at will by
-overriding the hook.
-
-Instead, you can set up your policies for use of Mercurial so that
-people are expected to propagate changes through a well-known
-``canonical'' server that you have locked down and configured
-appropriately.
-
-One way to do this is via a combination of social engineering and
-technology.  Set up a restricted-access account; users can push
-changes over the network to repositories managed by this account, but
-they cannot log into the account and run normal shell commands.  In
-this scenario, a user can commit a changeset that contains any old
-garbage they want.
-
-When someone pushes a changeset to the server that everyone pulls
-from, the server will test the changeset before it accepts it as
-permanent, and reject it if it fails to pass the test suite.  If
-people only pull changes from this filtering server, it will serve to
-ensure that all changes that people pull have been automatically
-vetted.
-
-\section{Care with \texttt{pretxn} hooks in a shared-access repository}
-
-If you want to use hooks to do some automated work in a repository
-that a number of people have shared access to, you need to be careful
-in how you do this.
-
-Mercurial only locks a repository when it is writing to the
-repository, and only the parts of Mercurial that write to the
-repository pay attention to locks.  Write locks are necessary to
-prevent multiple simultaneous writers from scribbling on each other's
-work, corrupting the repository.
-
-Because Mercurial is careful with the order in which it reads and
-writes data, it does not need to acquire a lock when it wants to read
-data from the repository.  The parts of Mercurial that read from the
-repository never pay attention to locks.  This lockless reading scheme
-greatly increases performance and concurrency.
-
-With great performance comes a trade-off, though, one which has the
-potential to cause you trouble unless you're aware of it.  To describe
-this requires a little detail about how Mercurial adds changesets to a
-repository and reads those changes.
-
-When Mercurial \emph{writes} metadata, it writes it straight into the
-destination file.  It writes file data first, then manifest data
-(which contains pointers to the new file data), then changelog data
-(which contains pointers to the new manifest data).  Before the first
-write to each file, it stores a record of where the end of the file
-was in its transaction log.  If the transaction must be rolled back,
-Mercurial simply truncates each file back to the size it was before the
-transaction began.
-
-When Mercurial \emph{reads} metadata, it reads the changelog first,
-then everything else.  Since a reader will only access parts of the
-manifest or file metadata that it can see in the changelog, it can
-never see partially written data.
-
-Some controlling hooks (\hook{pretxncommit} and
-\hook{pretxnchangegroup}) run when a transaction is almost complete.
-All of the metadata has been written, but Mercurial can still roll the
-transaction back and cause the newly-written data to disappear.
-
-If one of these hooks runs for long, it opens a window of time during
-which a reader can see the metadata for changesets that are not yet
-permanent, and should not be thought of as ``really there''.  The
-longer the hook runs, the longer that window is open.
-
-\subsection{The problem illustrated}
-
-In principle, a good use for the \hook{pretxnchangegroup} hook would
-be to automatically build and test incoming changes before they are
-accepted into a central repository.  This could let you guarantee that
-nobody can push changes to this repository that ``break the build''.
-But if a client can pull changes while they're being tested, the
-usefulness of the test is zero; an unsuspecting someone can pull
-untested changes, potentially breaking their build.
-
-The safest technological answer to this challenge is to set up such a
-``gatekeeper'' repository as \emph{unidirectional}.  Let it take
-changes pushed in from the outside, but do not allow anyone to pull
-changes from it (use the \hook{preoutgoing} hook to lock it down).
-Configure a \hook{changegroup} hook so that if a build or test
-succeeds, the hook will push the new changes out to another repository
-that people \emph{can} pull from.
-
-In practice, putting a centralised bottleneck like this in place is
-not often a good idea, and transaction visibility has nothing to do
-with the problem.  As the size of a project---and the time it takes to
-build and test---grows, you rapidly run into a wall with this ``try
-before you buy'' approach, where you have more changesets to test than
-time in which to deal with them.  The inevitable result is frustration
-on the part of all involved.
-
-An approach that scales better is to get people to build and test
-before they push, then run automated builds and tests centrally
-\emph{after} a push, to be sure all is well.  The advantage of this
-approach is that it does not impose a limit on the rate at which the
-repository can accept changes.
-
-\section{A short tutorial on using hooks}
-\label{sec:hook:simple}
-
-It is easy to write a Mercurial hook.  Let's start with a hook that
-runs when you finish a \hgcmd{commit}, and simply prints the hash of
-the changeset you just created.  The hook is called \hook{commit}.
-
-\begin{figure}[ht]
-  \interaction{hook.simple.init}
-  \caption{A simple hook that runs when a changeset is committed}
-  \label{ex:hook:init}
-\end{figure}
-
-All hooks follow the pattern in example~\ref{ex:hook:init}.  You add
-an entry to the \rcsection{hooks} section of your \hgrc.  On the left
-is the name of the event to trigger on; on the right is the action to
-take.  As you can see, you can run an arbitrary shell command in a
-hook.  Mercurial passes extra information to the hook using
-environment variables (look for \envar{HG\_NODE} in the example).
-
-\subsection{Performing multiple actions per event}
-
-Quite often, you will want to define more than one hook for a
-particular kind of event, as shown in example~\ref{ex:hook:ext}.
-Mercurial lets you do this by adding an \emph{extension} to the end of
-a hook's name.  You extend a hook's name by giving the name of the
-hook, followed by a full stop (the ``\texttt{.}'' character), followed
-by some more text of your choosing.  For example, Mercurial will run
-both \texttt{commit.foo} and \texttt{commit.bar} when the
-\texttt{commit} event occurs.
-
-\begin{figure}[ht]
-  \interaction{hook.simple.ext}
-  \caption{Defining a second \hook{commit} hook}
-  \label{ex:hook:ext}
-\end{figure}
-
-To give a well-defined order of execution when there are multiple
-hooks defined for an event, Mercurial sorts hooks by extension, and
-executes the hook commands in this sorted order.  In the above
-example, it will execute \texttt{commit.bar} before
-\texttt{commit.foo}, and \texttt{commit} before both.
-
-It is a good idea to use a somewhat descriptive extension when you
-define a new hook.  This will help you to remember what the hook was
-for.  If the hook fails, you'll get an error message that contains the
-hook name and extension, so using a descriptive extension could give
-you an immediate hint as to why the hook failed (see
-section~\ref{sec:hook:perm} for an example).
-
-\subsection{Controlling whether an activity can proceed}
-\label{sec:hook:perm}
-
-In our earlier examples, we used the \hook{commit} hook, which is
-run after a commit has completed.  This is one of several Mercurial
-hooks that run after an activity finishes.  Such hooks have no way of
-influencing the activity itself.
-
-Mercurial defines a number of events that occur before an activity
-starts; or after it starts, but before it finishes.  Hooks that
-trigger on these events have the added ability to choose whether the
-activity can continue, or will abort.  
-
-The \hook{pretxncommit} hook runs after a commit has all but
-completed.  In other words, the metadata representing the changeset
-has been written out to disk, but the transaction has not yet been
-allowed to complete.  The \hook{pretxncommit} hook has the ability to
-decide whether the transaction can complete, or must be rolled back.
-
-If the \hook{pretxncommit} hook exits with a status code of zero, the
-transaction is allowed to complete; the commit finishes; and the
-\hook{commit} hook is run.  If the \hook{pretxncommit} hook exits with
-a non-zero status code, the transaction is rolled back; the metadata
-representing the changeset is erased; and the \hook{commit} hook is
-not run.
-
-\begin{figure}[ht]
-  \interaction{hook.simple.pretxncommit}
-  \caption{Using the \hook{pretxncommit} hook to control commits}
-  \label{ex:hook:pretxncommit}
-\end{figure}
-
-The hook in example~\ref{ex:hook:pretxncommit} checks that a commit
-comment contains a bug ID.  If it does, the commit can complete.  If
-not, the commit is rolled back.
-
-\section{Writing your own hooks}
-
-When you are writing a hook, you might find it useful to run Mercurial
-either with the \hggopt{-v} option, or the \rcitem{ui}{verbose} config
-item set to ``true''.  When you do so, Mercurial will print a message
-before it calls each hook.
-
-\subsection{Choosing how your hook should run}
-\label{sec:hook:lang}
-
-You can write a hook either as a normal program---typically a shell
-script---or as a Python function that is executed within the Mercurial
-process.
-
-Writing a hook as an external program has the advantage that it
-requires no knowledge of Mercurial's internals.  You can call normal
-Mercurial commands to get any added information you need.  The
-trade-off is that external hooks are slower than in-process hooks.
-
-An in-process Python hook has complete access to the Mercurial API,
-and does not ``shell out'' to another process, so it is inherently
-faster than an external hook.  It is also easier to obtain much of the
-information that a hook requires by using the Mercurial API than by
-running Mercurial commands.
-
-If you are comfortable with Python, or require high performance,
-writing your hooks in Python may be a good choice.  However, when you
-have a straightforward hook to write and you don't need to care about
-performance (probably the majority of hooks), a shell script is
-perfectly fine.
-
-\subsection{Hook parameters}
-\label{sec:hook:param}
-
-Mercurial calls each hook with a set of well-defined parameters.  In
-Python, a parameter is passed as a keyword argument to your hook
-function.  For an external program, a parameter is passed as an
-environment variable.
-
-Whether your hook is written in Python or as a shell script, the
-hook-specific parameter names and values will be the same.  A boolean
-parameter will be represented as a boolean value in Python, but as the
-number 1 (for ``true'') or 0 (for ``false'') as an environment
-variable for an external hook.  If a hook parameter is named
-\texttt{foo}, the keyword argument for a Python hook will also be
-named \texttt{foo}, while the environment variable for an external
-hook will be named \texttt{HG\_FOO}.
-
-\subsection{Hook return values and activity control}
-
-A hook that executes successfully must exit with a status of zero if
-external, or return boolean ``false'' if in-process.  Failure is
-indicated with a non-zero exit status from an external hook, or an
-in-process hook returning boolean ``true''.  If an in-process hook
-raises an exception, the hook is considered to have failed.
-
-For a hook that controls whether an activity can proceed, zero/false
-means ``allow'', while non-zero/true/exception means ``deny''.
-
-\subsection{Writing an external hook}
-
-When you define an external hook in your \hgrc\ and the hook is run,
-its value is passed to your shell, which interprets it.  This means
-that you can use normal shell constructs in the body of the hook.
-
-An executable hook is always run with its current directory set to a
-repository's root directory.
-
-Each hook parameter is passed in as an environment variable; the name
-is upper-cased, and prefixed with the string ``\texttt{HG\_}''.
-
-With the exception of hook parameters, Mercurial does not set or
-modify any environment variables when running a hook.  This is useful
-to remember if you are writing a site-wide hook that may be run by a
-number of different users with differing environment variables set.
-In multi-user situations, you should not rely on environment variables
-being set to the values you have in your environment when testing the
-hook.
-
-\subsection{Telling Mercurial to use an in-process hook}
-
-The \hgrc\ syntax for defining an in-process hook is slightly
-different than for an executable hook.  The value of the hook must
-start with the text ``\texttt{python:}'', and continue with the
-fully-qualified name of a callable object to use as the hook's value.
-
-The module in which a hook lives is automatically imported when a hook
-is run.  So long as you have the module name and \envar{PYTHONPATH}
-right, it should ``just work''.
-
-The following \hgrc\ example snippet illustrates the syntax and
-meaning of the notions we just described.
-\begin{codesample2}
-  [hooks]
-  commit.example = python:mymodule.submodule.myhook
-\end{codesample2}
-When Mercurial runs the \texttt{commit.example} hook, it imports
-\texttt{mymodule.submodule}, looks for the callable object named
-\texttt{myhook}, and calls it.
-
-\subsection{Writing an in-process hook}
-
-The simplest in-process hook does nothing, but illustrates the basic
-shape of the hook API:
-\begin{codesample2}
-  def myhook(ui, repo, **kwargs):
-      pass
-\end{codesample2}
-The first argument to a Python hook is always a
-\pymodclass{mercurial.ui}{ui} object.  The second is a repository object;
-at the moment, it is always an instance of
-\pymodclass{mercurial.localrepo}{localrepository}.  Following these two
-arguments are other keyword arguments.  Which ones are passed in
-depends on the hook being called, but a hook can ignore arguments it
-doesn't care about by dropping them into a keyword argument dict, as
-with \texttt{**kwargs} above.
-
-\section{Some hook examples}
-
-\subsection{Writing meaningful commit messages}
-
-It's hard to imagine a useful commit message being very short.  The
-simple \hook{pretxncommit} hook of figure~\ref{ex:hook:msglen.go}
-will prevent you from committing a changeset with a message that is
-less than ten bytes long.
-
-\begin{figure}[ht]
-  \interaction{hook.msglen.go}
-  \caption{A hook that forbids overly short commit messages}
-  \label{ex:hook:msglen.go}
-\end{figure}
-
-\subsection{Checking for trailing whitespace}
-
-An interesting use of a commit-related hook is to help you to write
-cleaner code.  A simple example of ``cleaner code'' is the dictum that
-a change should not add any new lines of text that contain ``trailing
-whitespace''.  Trailing whitespace is a series of space and tab
-characters at the end of a line of text.  In most cases, trailing
-whitespace is unnecessary, invisible noise, but it is occasionally
-problematic, and people often prefer to get rid of it.
-
-You can use either the \hook{precommit} or \hook{pretxncommit} hook to
-tell whether you have a trailing whitespace problem.  If you use the
-\hook{precommit} hook, the hook will not know which files you are
-committing, so it will have to check every modified file in the
-repository for trailing white space.  If you want to commit a change
-to just the file \filename{foo}, but the file \filename{bar} contains
-trailing whitespace, doing a check in the \hook{precommit} hook will
-prevent you from committing \filename{foo} due to the problem with
-\filename{bar}.  This doesn't seem right.
-
-Should you choose the \hook{pretxncommit} hook, the check won't occur
-until just before the transaction for the commit completes.  This will
-allow you to check for problems only the exact files that are being
-committed.  However, if you entered the commit message interactively
-and the hook fails, the transaction will roll back; you'll have to
-re-enter the commit message after you fix the trailing whitespace and
-run \hgcmd{commit} again.
-
-\begin{figure}[ht]
-  \interaction{hook.ws.simple}
-  \caption{A simple hook that checks for trailing whitespace}
-  \label{ex:hook:ws.simple}
-\end{figure}
-
-Figure~\ref{ex:hook:ws.simple} introduces a simple \hook{pretxncommit}
-hook that checks for trailing whitespace.  This hook is short, but not
-very helpful.  It exits with an error status if a change adds a line
-with trailing whitespace to any file, but does not print any
-information that might help us to identify the offending file or
-line.  It also has the nice property of not paying attention to
-unmodified lines; only lines that introduce new trailing whitespace
-cause problems.
-
-\begin{figure}[ht]
-  \interaction{hook.ws.better}
-  \caption{A better trailing whitespace hook}
-  \label{ex:hook:ws.better}
-\end{figure}
-
-The example of figure~\ref{ex:hook:ws.better} is much more complex,
-but also more useful.  It parses a unified diff to see if any lines
-add trailing whitespace, and prints the name of the file and the line
-number of each such occurrence.  Even better, if the change adds
-trailing whitespace, this hook saves the commit comment and prints the
-name of the save file before exiting and telling Mercurial to roll the
-transaction back, so you can use
-\hgcmdargs{commit}{\hgopt{commit}{-l}~\emph{filename}} to reuse the
-saved commit message once you've corrected the problem.
-
-As a final aside, note in figure~\ref{ex:hook:ws.better} the use of
-\command{perl}'s in-place editing feature to get rid of trailing
-whitespace from a file.  This is concise and useful enough that I will
-reproduce it here.
-\begin{codesample2}
-  perl -pi -e 's,[ \textbackslash{}t]+\$,,' filename
-\end{codesample2}
-
-\section{Bundled hooks}
-
-Mercurial ships with several bundled hooks.  You can find them in the
-\dirname{hgext} directory of a Mercurial source tree.  If you are
-using a Mercurial binary package, the hooks will be located in the
-\dirname{hgext} directory of wherever your package installer put
-Mercurial.
-
-\subsection{\hgext{acl}---access control for parts of a repository}
-
-The \hgext{acl} extension lets you control which remote users are
-allowed to push changesets to a networked server.  You can protect any
-portion of a repository (including the entire repo), so that a
-specific remote user can push changes that do not affect the protected
-portion.
-
-This extension implements access control based on the identity of the
-user performing a push, \emph{not} on who committed the changesets
-they're pushing.  It makes sense to use this hook only if you have a
-locked-down server environment that authenticates remote users, and
-you want to be sure that only specific users are allowed to push
-changes to that server.
-
-\subsubsection{Configuring the \hook{acl} hook}
-
-In order to manage incoming changesets, the \hgext{acl} hook must be
-used as a \hook{pretxnchangegroup} hook.  This lets it see which files
-are modified by each incoming changeset, and roll back a group of
-changesets if they modify ``forbidden'' files.  Example:
-\begin{codesample2}
-  [hooks]
-  pretxnchangegroup.acl = python:hgext.acl.hook
-\end{codesample2}
-
-The \hgext{acl} extension is configured using three sections.  
-
-The \rcsection{acl} section has only one entry, \rcitem{acl}{sources},
-which lists the sources of incoming changesets that the hook should
-pay attention to.  You don't normally need to configure this section.
-\begin{itemize}
-\item[\rcitem{acl}{serve}] Control incoming changesets that are arriving
-  from a remote repository over http or ssh.  This is the default
-  value of \rcitem{acl}{sources}, and usually the only setting you'll
-  need for this configuration item.
-\item[\rcitem{acl}{pull}] Control incoming changesets that are
-  arriving via a pull from a local repository.
-\item[\rcitem{acl}{push}] Control incoming changesets that are
-  arriving via a push from a local repository.
-\item[\rcitem{acl}{bundle}] Control incoming changesets that are
-  arriving from another repository via a bundle.
-\end{itemize}
-
-The \rcsection{acl.allow} section controls the users that are allowed to
-add changesets to the repository.  If this section is not present, all
-users that are not explicitly denied are allowed.  If this section is
-present, all users that are not explicitly allowed are denied (so an
-empty section means that all users are denied).
-
-The \rcsection{acl.deny} section determines which users are denied
-from adding changesets to the repository.  If this section is not
-present or is empty, no users are denied.
-
-The syntaxes for the \rcsection{acl.allow} and \rcsection{acl.deny}
-sections are identical.  On the left of each entry is a glob pattern
-that matches files or directories, relative to the root of the
-repository; on the right, a user name.
-
-In the following example, the user \texttt{docwriter} can only push
-changes to the \dirname{docs} subtree of the repository, while
-\texttt{intern} can push changes to any file or directory except
-\dirname{source/sensitive}.
-\begin{codesample2}
-  [acl.allow]
-  docs/** = docwriter
-
-  [acl.deny]
-  source/sensitive/** = intern
-\end{codesample2}
-
-\subsubsection{Testing and troubleshooting}
-
-If you want to test the \hgext{acl} hook, run it with Mercurial's
-debugging output enabled.  Since you'll probably be running it on a
-server where it's not convenient (or sometimes possible) to pass in
-the \hggopt{--debug} option, don't forget that you can enable
-debugging output in your \hgrc:
-\begin{codesample2}
-  [ui]
-  debug = true
-\end{codesample2}
-With this enabled, the \hgext{acl} hook will print enough information
-to let you figure out why it is allowing or forbidding pushes from
-specific users.
-
-\subsection{\hgext{bugzilla}---integration with Bugzilla}
-
-The \hgext{bugzilla} extension adds a comment to a Bugzilla bug
-whenever it finds a reference to that bug ID in a commit comment.  You
-can install this hook on a shared server, so that any time a remote
-user pushes changes to this server, the hook gets run.  
-
-It adds a comment to the bug that looks like this (you can configure
-the contents of the comment---see below):
-\begin{codesample2}
-  Changeset aad8b264143a, made by Joe User <joe.user@domain.com> in
-  the frobnitz repository, refers to this bug.
-
-  For complete details, see
-  http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a
-
-  Changeset description:
-        Fix bug 10483 by guarding against some NULL pointers
-\end{codesample2}
-The value of this hook is that it automates the process of updating a
-bug any time a changeset refers to it.  If you configure the hook
-properly, it makes it easy for people to browse straight from a
-Bugzilla bug to a changeset that refers to that bug.
-
-You can use the code in this hook as a starting point for some more
-exotic Bugzilla integration recipes.  Here are a few possibilities:
-\begin{itemize}
-\item Require that every changeset pushed to the server have a valid
-  bug~ID in its commit comment.  In this case, you'd want to configure
-  the hook as a \hook{pretxncommit} hook.  This would allow the hook
-  to reject changes that didn't contain bug IDs.
-\item Allow incoming changesets to automatically modify the
-  \emph{state} of a bug, as well as simply adding a comment.  For
-  example, the hook could recognise the string ``fixed bug 31337'' as
-  indicating that it should update the state of bug 31337 to
-  ``requires testing''.
-\end{itemize}
-
-\subsubsection{Configuring the \hook{bugzilla} hook}
-\label{sec:hook:bugzilla:config}
-
-You should configure this hook in your server's \hgrc\ as an
-\hook{incoming} hook, for example as follows:
-\begin{codesample2}
-  [hooks]
-  incoming.bugzilla = python:hgext.bugzilla.hook
-\end{codesample2}
-
-Because of the specialised nature of this hook, and because Bugzilla
-was not written with this kind of integration in mind, configuring
-this hook is a somewhat involved process.
-
-Before you begin, you must install the MySQL bindings for Python on
-the host(s) where you'll be running the hook.  If this is not
-available as a binary package for your system, you can download it
-from~\cite{web:mysql-python}.
-
-Configuration information for this hook lives in the
-\rcsection{bugzilla} section of your \hgrc.
-\begin{itemize}
-\item[\rcitem{bugzilla}{version}] The version of Bugzilla installed on
-  the server.  The database schema that Bugzilla uses changes
-  occasionally, so this hook has to know exactly which schema to use.
-  At the moment, the only version supported is \texttt{2.16}.
-\item[\rcitem{bugzilla}{host}] The hostname of the MySQL server that
-  stores your Bugzilla data.  The database must be configured to allow
-  connections from whatever host you are running the \hook{bugzilla}
-  hook on.
-\item[\rcitem{bugzilla}{user}] The username with which to connect to
-  the MySQL server.  The database must be configured to allow this
-  user to connect from whatever host you are running the
-  \hook{bugzilla} hook on.  This user must be able to access and
-  modify Bugzilla tables.  The default value of this item is
-  \texttt{bugs}, which is the standard name of the Bugzilla user in a
-  MySQL database.
-\item[\rcitem{bugzilla}{password}] The MySQL password for the user you
-  configured above.  This is stored as plain text, so you should make
-  sure that unauthorised users cannot read the \hgrc\ file where you
-  store this information.
-\item[\rcitem{bugzilla}{db}] The name of the Bugzilla database on the
-  MySQL server.  The default value of this item is \texttt{bugs},
-  which is the standard name of the MySQL database where Bugzilla
-  stores its data.
-\item[\rcitem{bugzilla}{notify}] If you want Bugzilla to send out a
-  notification email to subscribers after this hook has added a
-  comment to a bug, you will need this hook to run a command whenever
-  it updates the database.  The command to run depends on where you
-  have installed Bugzilla, but it will typically look something like
-  this, if you have Bugzilla installed in
-  \dirname{/var/www/html/bugzilla}:
-  \begin{codesample4}
-    cd /var/www/html/bugzilla && ./processmail %s nobody@nowhere.com
-  \end{codesample4}
-  The Bugzilla \texttt{processmail} program expects to be given a
-  bug~ID (the hook replaces ``\texttt{\%s}'' with the bug~ID) and an
-  email address.  It also expects to be able to write to some files in
-  the directory that it runs in.  If Bugzilla and this hook are not
-  installed on the same machine, you will need to find a way to run
-  \texttt{processmail} on the server where Bugzilla is installed.
-\end{itemize}
-
-\subsubsection{Mapping committer names to Bugzilla user names}
-
-By default, the \hgext{bugzilla} hook tries to use the email address
-of a changeset's committer as the Bugzilla user name with which to
-update a bug.  If this does not suit your needs, you can map committer
-email addresses to Bugzilla user names using a \rcsection{usermap}
-section.
-
-Each item in the \rcsection{usermap} section contains an email address
-on the left, and a Bugzilla user name on the right.
-\begin{codesample2}
-  [usermap]
-  jane.user@example.com = jane
-\end{codesample2}
-You can either keep the \rcsection{usermap} data in a normal \hgrc, or
-tell the \hgext{bugzilla} hook to read the information from an
-external \filename{usermap} file.  In the latter case, you can store
-\filename{usermap} data by itself in (for example) a user-modifiable
-repository.  This makes it possible to let your users maintain their
-own \rcitem{bugzilla}{usermap} entries.  The main \hgrc\ file might
-look like this:
-\begin{codesample2}
-  # regular hgrc file refers to external usermap file
-  [bugzilla]
-  usermap = /home/hg/repos/userdata/bugzilla-usermap.conf
-\end{codesample2}
-While the \filename{usermap} file that it refers to might look like
-this:
-\begin{codesample2}
-  # bugzilla-usermap.conf - inside a hg repository
-  [usermap]
-  stephanie@example.com = steph
-\end{codesample2}
-
-\subsubsection{Configuring the text that gets added to a bug}
-
-You can configure the text that this hook adds as a comment; you
-specify it in the form of a Mercurial template.  Several \hgrc\
-entries (still in the \rcsection{bugzilla} section) control this
-behaviour.
-\begin{itemize}
-\item[\texttt{strip}] The number of leading path elements to strip
-  from a repository's path name to construct a partial path for a URL.
-  For example, if the repositories on your server live under
-  \dirname{/home/hg/repos}, and you have a repository whose path is
-  \dirname{/home/hg/repos/app/tests}, then setting \texttt{strip} to
-  \texttt{4} will give a partial path of \dirname{app/tests}.  The
-  hook will make this partial path available when expanding a
-  template, as \texttt{webroot}.
-\item[\texttt{template}] The text of the template to use.  In addition
-  to the usual changeset-related variables, this template can use
-  \texttt{hgweb} (the value of the \texttt{hgweb} configuration item
-  above) and \texttt{webroot} (the path constructed using
-  \texttt{strip} above).
-\end{itemize}
-
-In addition, you can add a \rcitem{web}{baseurl} item to the
-\rcsection{web} section of your \hgrc.  The \hgext{bugzilla} hook will
-make this available when expanding a template, as the base string to
-use when constructing a URL that will let users browse from a Bugzilla
-comment to view a changeset.  Example:
-\begin{codesample2}
-  [web]
-  baseurl = http://hg.domain.com/
-\end{codesample2}
-
-Here is an example set of \hgext{bugzilla} hook config information.
-\begin{codesample2}
-  [bugzilla]
-  host = bugzilla.example.com
-  password = mypassword
-  version = 2.16
-  # server-side repos live in /home/hg/repos, so strip 4 leading
-  # separators
-  strip = 4
-  hgweb = http://hg.example.com/
-  usermap = /home/hg/repos/notify/bugzilla.conf
-  template = Changeset \{node|short\}, made by \{author\} in the \{webroot\}
-    repo, refers to this bug.\\nFor complete details, see 
-    \{hgweb\}\{webroot\}?cmd=changeset;node=\{node|short\}\\nChangeset
-    description:\\n\\t\{desc|tabindent\}
-\end{codesample2}
-
-\subsubsection{Testing and troubleshooting}
-
-The most common problems with configuring the \hgext{bugzilla} hook
-relate to running Bugzilla's \filename{processmail} script and mapping
-committer names to user names.
-
-Recall from section~\ref{sec:hook:bugzilla:config} above that the user
-that runs the Mercurial process on the server is also the one that
-will run the \filename{processmail} script.  The
-\filename{processmail} script sometimes causes Bugzilla to write to
-files in its configuration directory, and Bugzilla's configuration
-files are usually owned by the user that your web server runs under.
-
-You can cause \filename{processmail} to be run with the suitable
-user's identity using the \command{sudo} command.  Here is an example
-entry for a \filename{sudoers} file.
-\begin{codesample2}
-  hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s
-\end{codesample2}
-This allows the \texttt{hg\_user} user to run a
-\filename{processmail-wrapper} program under the identity of
-\texttt{httpd\_user}.
-
-This indirection through a wrapper script is necessary, because
-\filename{processmail} expects to be run with its current directory
-set to wherever you installed Bugzilla; you can't specify that kind of
-constraint in a \filename{sudoers} file.  The contents of the wrapper
-script are simple:
-\begin{codesample2}
-  #!/bin/sh
-  cd `dirname $0` && ./processmail "$1" nobody@example.com
-\end{codesample2}
-It doesn't seem to matter what email address you pass to
-\filename{processmail}.
-
-If your \rcsection{usermap} is not set up correctly, users will see an
-error message from the \hgext{bugzilla} hook when they push changes
-to the server.  The error message will look like this:
-\begin{codesample2}
-  cannot find bugzilla user id for john.q.public@example.com
-\end{codesample2}
-What this means is that the committer's address,
-\texttt{john.q.public@example.com}, is not a valid Bugzilla user name,
-nor does it have an entry in your \rcsection{usermap} that maps it to
-a valid Bugzilla user name.
-
-\subsection{\hgext{notify}---send email notifications}
-
-Although Mercurial's built-in web server provides RSS feeds of changes
-in every repository, many people prefer to receive change
-notifications via email.  The \hgext{notify} hook lets you send out
-notifications to a set of email addresses whenever changesets arrive
-that those subscribers are interested in.
-
-As with the \hgext{bugzilla} hook, the \hgext{notify} hook is
-template-driven, so you can customise the contents of the notification
-messages that it sends.
-
-By default, the \hgext{notify} hook includes a diff of every changeset
-that it sends out; you can limit the size of the diff, or turn this
-feature off entirely.  It is useful for letting subscribers review
-changes immediately, rather than clicking to follow a URL.
-
-\subsubsection{Configuring the \hgext{notify} hook}
-
-You can set up the \hgext{notify} hook to send one email message per
-incoming changeset, or one per incoming group of changesets (all those
-that arrived in a single pull or push).
-\begin{codesample2}
-  [hooks]
-  # send one email per group of changes
-  changegroup.notify = python:hgext.notify.hook
-  # send one email per change
-  incoming.notify = python:hgext.notify.hook
-\end{codesample2}
-
-Configuration information for this hook lives in the
-\rcsection{notify} section of a \hgrc\ file.
-\begin{itemize}
-\item[\rcitem{notify}{test}] By default, this hook does not send out
-  email at all; instead, it prints the message that it \emph{would}
-  send.  Set this item to \texttt{false} to allow email to be sent.
-  The reason that sending of email is turned off by default is that it
-  takes several tries to configure this extension exactly as you would
-  like, and it would be bad form to spam subscribers with a number of
-  ``broken'' notifications while you debug your configuration.
-\item[\rcitem{notify}{config}] The path to a configuration file that
-  contains subscription information.  This is kept separate from the
-  main \hgrc\ so that you can maintain it in a repository of its own.
-  People can then clone that repository, update their subscriptions,
-  and push the changes back to your server.
-\item[\rcitem{notify}{strip}] The number of leading path separator
-  characters to strip from a repository's path, when deciding whether
-  a repository has subscribers.  For example, if the repositories on
-  your server live in \dirname{/home/hg/repos}, and \hgext{notify} is
-  considering a repository named \dirname{/home/hg/repos/shared/test},
-  setting \rcitem{notify}{strip} to \texttt{4} will cause
-  \hgext{notify} to trim the path it considers down to
-  \dirname{shared/test}, and it will match subscribers against that.
-\item[\rcitem{notify}{template}] The template text to use when sending
-  messages.  This specifies both the contents of the message header
-  and its body.
-\item[\rcitem{notify}{maxdiff}] The maximum number of lines of diff
-  data to append to the end of a message.  If a diff is longer than
-  this, it is truncated.  By default, this is set to 300.  Set this to
-  \texttt{0} to omit diffs from notification emails.
-\item[\rcitem{notify}{sources}] A list of sources of changesets to
-  consider.  This lets you limit \hgext{notify} to only sending out
-  email about changes that remote users pushed into this repository
-  via a server, for example.  See section~\ref{sec:hook:sources} for
-  the sources you can specify here.
-\end{itemize}
-
-If you set the \rcitem{web}{baseurl} item in the \rcsection{web}
-section, you can use it in a template; it will be available as
-\texttt{webroot}.
-
-Here is an example set of \hgext{notify} configuration information.
-\begin{codesample2}
-  [notify]
-  # really send email
-  test = false
-  # subscriber data lives in the notify repo
-  config = /home/hg/repos/notify/notify.conf
-  # repos live in /home/hg/repos on server, so strip 4 "/" chars
-  strip = 4
-  template = X-Hg-Repo: \{webroot\}
-    Subject: \{webroot\}: \{desc|firstline|strip\}
-    From: \{author\}
-
-    changeset \{node|short\} in \{root\}
-    details: \{baseurl\}\{webroot\}?cmd=changeset;node=\{node|short\}
-    description:
-      \{desc|tabindent|strip\}
-
-  [web]
-  baseurl = http://hg.example.com/
-\end{codesample2}
-
-This will produce a message that looks like the following:
-\begin{codesample2}
-  X-Hg-Repo: tests/slave
-  Subject: tests/slave: Handle error case when slave has no buffers
-  Date: Wed,  2 Aug 2006 15:25:46 -0700 (PDT)
-
-  changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave
-  details: http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5
-  description:
-          Handle error case when slave has no buffers
-  diffs (54 lines):
-
-  diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h
-  --- a/include/tests.h      Wed Aug 02 15:19:52 2006 -0700
-  +++ b/include/tests.h      Wed Aug 02 15:25:26 2006 -0700
-  @@ -212,6 +212,15 @@ static __inline__ void test_headers(void *h)
-  [...snip...]
-\end{codesample2}
-
-\subsubsection{Testing and troubleshooting}
-
-Do not forget that by default, the \hgext{notify} extension \emph{will
-  not send any mail} until you explicitly configure it to do so, by
-setting \rcitem{notify}{test} to \texttt{false}.  Until you do that,
-it simply prints the message it \emph{would} send.
-
-\section{Information for writers of hooks}
-\label{sec:hook:ref}
-
-\subsection{In-process hook execution}
-
-An in-process hook is called with arguments of the following form:
-\begin{codesample2}
-  def myhook(ui, repo, **kwargs):
-      pass
-\end{codesample2}
-The \texttt{ui} parameter is a \pymodclass{mercurial.ui}{ui} object.
-The \texttt{repo} parameter is a
-\pymodclass{mercurial.localrepo}{localrepository} object.  The
-names and values of the \texttt{**kwargs} parameters depend on the
-hook being invoked, with the following common features:
-\begin{itemize}
-\item If a parameter is named \texttt{node} or
-  \texttt{parent\emph{N}}, it will contain a hexadecimal changeset ID.
-  The empty string is used to represent ``null changeset ID'' instead
-  of a string of zeroes.
-\item If a parameter is named \texttt{url}, it will contain the URL of
-  a remote repository, if that can be determined.
-\item Boolean-valued parameters are represented as Python
-  \texttt{bool} objects.
-\end{itemize}
-
-An in-process hook is called without a change to the process's working
-directory (unlike external hooks, which are run in the root of the
-repository).  It must not change the process's working directory, or
-it will cause any calls it makes into the Mercurial API to fail.
-
-If a hook returns a boolean ``false'' value, it is considered to have
-succeeded.  If it returns a boolean ``true'' value or raises an
-exception, it is considered to have failed.  A useful way to think of
-the calling convention is ``tell me if you fail''.
-
-Note that changeset IDs are passed into Python hooks as hexadecimal
-strings, not the binary hashes that Mercurial's APIs normally use.  To
-convert a hash from hex to binary, use the
-\pymodfunc{mercurial.node}{bin} function.
-
-\subsection{External hook execution}
-
-An external hook is passed to the shell of the user running Mercurial.
-Features of that shell, such as variable substitution and command
-redirection, are available.  The hook is run in the root directory of
-the repository (unlike in-process hooks, which are run in the same
-directory that Mercurial was run in).
-
-Hook parameters are passed to the hook as environment variables.  Each
-environment variable's name is converted in upper case and prefixed
-with the string ``\texttt{HG\_}''.  For example, if the name of a
-parameter is ``\texttt{node}'', the name of the environment variable
-representing that parameter will be ``\texttt{HG\_NODE}''.
-
-A boolean parameter is represented as the string ``\texttt{1}'' for
-``true'', ``\texttt{0}'' for ``false''.  If an environment variable is
-named \envar{HG\_NODE}, \envar{HG\_PARENT1} or \envar{HG\_PARENT2}, it
-contains a changeset ID represented as a hexadecimal string.  The
-empty string is used to represent ``null changeset ID'' instead of a
-string of zeroes.  If an environment variable is named
-\envar{HG\_URL}, it will contain the URL of a remote repository, if
-that can be determined.
-
-If a hook exits with a status of zero, it is considered to have
-succeeded.  If it exits with a non-zero status, it is considered to
-have failed.
-
-\subsection{Finding out where changesets come from}
-
-A hook that involves the transfer of changesets between a local
-repository and another may be able to find out information about the
-``far side''.  Mercurial knows \emph{how} changes are being
-transferred, and in many cases \emph{where} they are being transferred
-to or from.
-
-\subsubsection{Sources of changesets}
-\label{sec:hook:sources}
-
-Mercurial will tell a hook what means are, or were, used to transfer
-changesets between repositories.  This is provided by Mercurial in a
-Python parameter named \texttt{source}, or an environment variable named
-\envar{HG\_SOURCE}.
-
-\begin{itemize}
-\item[\texttt{serve}] Changesets are transferred to or from a remote
-  repository over http or ssh.
-\item[\texttt{pull}] Changesets are being transferred via a pull from
-  one repository into another.
-\item[\texttt{push}] Changesets are being transferred via a push from
-  one repository into another.
-\item[\texttt{bundle}] Changesets are being transferred to or from a
-  bundle.
-\end{itemize}
-
-\subsubsection{Where changes are going---remote repository URLs}
-\label{sec:hook:url}
-
-When possible, Mercurial will tell a hook the location of the ``far
-side'' of an activity that transfers changeset data between
-repositories.  This is provided by Mercurial in a Python parameter
-named \texttt{url}, or an environment variable named \envar{HG\_URL}.
-
-This information is not always known.  If a hook is invoked in a
-repository that is being served via http or ssh, Mercurial cannot tell
-where the remote repository is, but it may know where the client is
-connecting from.  In such cases, the URL will take one of the
-following forms:
-\begin{itemize}
-\item \texttt{remote:ssh:\emph{ip-address}}---remote ssh client, at
-  the given IP address.
-\item \texttt{remote:http:\emph{ip-address}}---remote http client, at
-  the given IP address.  If the client is using SSL, this will be of
-  the form \texttt{remote:https:\emph{ip-address}}.
-\item Empty---no information could be discovered about the remote
-  client.
-\end{itemize}
-
-\section{Hook reference}
-
-\subsection{\hook{changegroup}---after remote changesets added}
-\label{sec:hook:changegroup}
-
-This hook is run after a group of pre-existing changesets has been
-added to the repository, for example via a \hgcmd{pull} or
-\hgcmd{unbundle}.  This hook is run once per operation that added one
-or more changesets.  This is in contrast to the \hook{incoming} hook,
-which is run once per changeset, regardless of whether the changesets
-arrive in a group.
-
-Some possible uses for this hook include kicking off an automated
-build or test of the added changesets, updating a bug database, or
-notifying subscribers that a repository contains new changes.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{node}] A changeset ID.  The changeset ID of the first
-  changeset in the group that was added.  All changesets between this
-  and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by
-  a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}.
-\item[\texttt{source}] A string.  The source of these changes.  See
-  section~\ref{sec:hook:sources} for details.
-\item[\texttt{url}] A URL.  The location of the remote repository, if
-  known.  See section~\ref{sec:hook:url} for more information.
-\end{itemize}
-
-See also: \hook{incoming} (section~\ref{sec:hook:incoming}),
-\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}),
-\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup})
-
-\subsection{\hook{commit}---after a new changeset is created}
-\label{sec:hook:commit}
-
-This hook is run after a new changeset has been created.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{node}] A changeset ID.  The changeset ID of the newly
-  committed changeset.
-\item[\texttt{parent1}] A changeset ID.  The changeset ID of the first
-  parent of the newly committed changeset.
-\item[\texttt{parent2}] A changeset ID.  The changeset ID of the second
-  parent of the newly committed changeset.
-\end{itemize}
-
-See also: \hook{precommit} (section~\ref{sec:hook:precommit}),
-\hook{pretxncommit} (section~\ref{sec:hook:pretxncommit})
-
-\subsection{\hook{incoming}---after one remote changeset is added}
-\label{sec:hook:incoming}
-
-This hook is run after a pre-existing changeset has been added to the
-repository, for example via a \hgcmd{push}.  If a group of changesets
-was added in a single operation, this hook is called once for each
-added changeset.
-
-You can use this hook for the same purposes as the \hook{changegroup}
-hook (section~\ref{sec:hook:changegroup}); it's simply more convenient
-sometimes to run a hook once per group of changesets, while other
-times it's handier once per changeset.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{node}] A changeset ID.  The ID of the newly added
-  changeset.
-\item[\texttt{source}] A string.  The source of these changes.  See
-  section~\ref{sec:hook:sources} for details.
-\item[\texttt{url}] A URL.  The location of the remote repository, if
-  known.  See section~\ref{sec:hook:url} for more information.
-\end{itemize}
-
-See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}) \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup})
-
-\subsection{\hook{outgoing}---after changesets are propagated}
-\label{sec:hook:outgoing}
-
-This hook is run after a group of changesets has been propagated out
-of this repository, for example by a \hgcmd{push} or \hgcmd{bundle}
-command.
-
-One possible use for this hook is to notify administrators that
-changes have been pulled.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{node}] A changeset ID.  The changeset ID of the first
-  changeset of the group that was sent.
-\item[\texttt{source}] A string.  The source of the of the operation
-  (see section~\ref{sec:hook:sources}).  If a remote client pulled
-  changes from this repository, \texttt{source} will be
-  \texttt{serve}.  If the client that obtained changes from this
-  repository was local, \texttt{source} will be \texttt{bundle},
-  \texttt{pull}, or \texttt{push}, depending on the operation the
-  client performed.
-\item[\texttt{url}] A URL.  The location of the remote repository, if
-  known.  See section~\ref{sec:hook:url} for more information.
-\end{itemize}
-
-See also: \hook{preoutgoing} (section~\ref{sec:hook:preoutgoing})
-
-\subsection{\hook{prechangegroup}---before starting to add remote changesets}
-\label{sec:hook:prechangegroup}
-
-This controlling hook is run before Mercurial begins to add a group of
-changesets from another repository.
-
-This hook does not have any information about the changesets to be
-added, because it is run before transmission of those changesets is
-allowed to begin.  If this hook fails, the changesets will not be
-transmitted.
-
-One use for this hook is to prevent external changes from being added
-to a repository.  For example, you could use this to ``freeze'' a
-server-hosted branch temporarily or permanently so that users cannot
-push to it, while still allowing a local administrator to modify the
-repository.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{source}] A string.  The source of these changes.  See
-  section~\ref{sec:hook:sources} for details.
-\item[\texttt{url}] A URL.  The location of the remote repository, if
-  known.  See section~\ref{sec:hook:url} for more information.
-\end{itemize}
-
-See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}),
-\hook{incoming} (section~\ref{sec:hook:incoming}), ,
-\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup})
-
-\subsection{\hook{precommit}---before starting to commit a changeset}
-\label{sec:hook:precommit}
-
-This hook is run before Mercurial begins to commit a new changeset.
-It is run before Mercurial has any of the metadata for the commit,
-such as the files to be committed, the commit message, or the commit
-date.
-
-One use for this hook is to disable the ability to commit new
-changesets, while still allowing incoming changesets.  Another is to
-run a build or test, and only allow the commit to begin if the build
-or test succeeds.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{parent1}] A changeset ID.  The changeset ID of the first
-  parent of the working directory.
-\item[\texttt{parent2}] A changeset ID.  The changeset ID of the second
-  parent of the working directory.
-\end{itemize}
-If the commit proceeds, the parents of the working directory will
-become the parents of the new changeset.
-
-See also: \hook{commit} (section~\ref{sec:hook:commit}),
-\hook{pretxncommit} (section~\ref{sec:hook:pretxncommit})
-
-\subsection{\hook{preoutgoing}---before starting to propagate changesets}
-\label{sec:hook:preoutgoing}
-
-This hook is invoked before Mercurial knows the identities of the
-changesets to be transmitted.
-
-One use for this hook is to prevent changes from being transmitted to
-another repository.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{source}] A string.  The source of the operation that is
-  attempting to obtain changes from this repository (see
-  section~\ref{sec:hook:sources}).  See the documentation for the
-  \texttt{source} parameter to the \hook{outgoing} hook, in
-  section~\ref{sec:hook:outgoing}, for possible values of this
-  parameter.
-\item[\texttt{url}] A URL.  The location of the remote repository, if
-  known.  See section~\ref{sec:hook:url} for more information.
-\end{itemize}
-
-See also: \hook{outgoing} (section~\ref{sec:hook:outgoing})
-
-\subsection{\hook{pretag}---before tagging a changeset}
-\label{sec:hook:pretag}
-
-This controlling hook is run before a tag is created.  If the hook
-succeeds, creation of the tag proceeds.  If the hook fails, the tag is
-not created.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{local}] A boolean.  Whether the tag is local to this
-  repository instance (i.e.~stored in \sfilename{.hg/localtags}) or
-  managed by Mercurial (stored in \sfilename{.hgtags}).
-\item[\texttt{node}] A changeset ID.  The ID of the changeset to be tagged.
-\item[\texttt{tag}] A string.  The name of the tag to be created.
-\end{itemize}
-
-If the tag to be created is revision-controlled, the \hook{precommit}
-and \hook{pretxncommit} hooks (sections~\ref{sec:hook:commit}
-and~\ref{sec:hook:pretxncommit}) will also be run.
-
-See also: \hook{tag} (section~\ref{sec:hook:tag})
-
-\subsection{\hook{pretxnchangegroup}---before completing addition of
-  remote changesets}
-\label{sec:hook:pretxnchangegroup}
-
-This controlling hook is run before a transaction---that manages the
-addition of a group of new changesets from outside the
-repository---completes.  If the hook succeeds, the transaction
-completes, and all of the changesets become permanent within this
-repository.  If the hook fails, the transaction is rolled back, and
-the data for the changesets is erased.
-
-This hook can access the metadata associated with the almost-added
-changesets, but it should not do anything permanent with this data.
-It must also not modify the working directory.
-
-While this hook is running, if other Mercurial processes access this
-repository, they will be able to see the almost-added changesets as if
-they are permanent.  This may lead to race conditions if you do not
-take steps to avoid them.
-
-This hook can be used to automatically vet a group of changesets.  If
-the hook fails, all of the changesets are ``rejected'' when the
-transaction rolls back.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{node}] A changeset ID.  The changeset ID of the first
-  changeset in the group that was added.  All changesets between this
-  and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by
-  a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}.
-\item[\texttt{source}] A string.  The source of these changes.  See
-  section~\ref{sec:hook:sources} for details.
-\item[\texttt{url}] A URL.  The location of the remote repository, if
-  known.  See section~\ref{sec:hook:url} for more information.
-\end{itemize}
-
-See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}),
-\hook{incoming} (section~\ref{sec:hook:incoming}),
-\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup})
-
-\subsection{\hook{pretxncommit}---before completing commit of new changeset}
-\label{sec:hook:pretxncommit}
-
-This controlling hook is run before a transaction---that manages a new
-commit---completes.  If the hook succeeds, the transaction completes
-and the changeset becomes permanent within this repository.  If the
-hook fails, the transaction is rolled back, and the commit data is
-erased.
-
-This hook can access the metadata associated with the almost-new
-changeset, but it should not do anything permanent with this data.  It
-must also not modify the working directory.
-
-While this hook is running, if other Mercurial processes access this
-repository, they will be able to see the almost-new changeset as if it
-is permanent.  This may lead to race conditions if you do not take
-steps to avoid them.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{node}] A changeset ID.  The changeset ID of the newly
-  committed changeset.
-\item[\texttt{parent1}] A changeset ID.  The changeset ID of the first
-  parent of the newly committed changeset.
-\item[\texttt{parent2}] A changeset ID.  The changeset ID of the second
-  parent of the newly committed changeset.
-\end{itemize}
-
-See also: \hook{precommit} (section~\ref{sec:hook:precommit})
-
-\subsection{\hook{preupdate}---before updating or merging working directory}
-\label{sec:hook:preupdate}
-
-This controlling hook is run before an update or merge of the working
-directory begins.  It is run only if Mercurial's normal pre-update
-checks determine that the update or merge can proceed.  If the hook
-succeeds, the update or merge may proceed; if it fails, the update or
-merge does not start.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{parent1}] A changeset ID.  The ID of the parent that the
-  working directory is to be updated to.  If the working directory is
-  being merged, it will not change this parent.
-\item[\texttt{parent2}] A changeset ID.  Only set if the working
-  directory is being merged.  The ID of the revision that the working
-  directory is being merged with.
-\end{itemize}
-
-See also: \hook{update} (section~\ref{sec:hook:update})
-
-\subsection{\hook{tag}---after tagging a changeset}
-\label{sec:hook:tag}
-
-This hook is run after a tag has been created.
-
-Parameters to this hook:
-\begin{itemize}
-\item[\texttt{local}] A boolean.  Whether the new tag is local to this
-  repository instance (i.e.~stored in \sfilename{.hg/localtags}) or
-  managed by Mercurial (stored in \sfilename{.hgtags}).
-\item[\texttt{node}] A changeset ID.  The ID of the changeset that was
-  tagged.
-\item[\texttt{tag}] A string.  The name of the tag that was created.
-\end{itemize}
-
-If the created tag is revision-controlled, the \hook{commit} hook
-(section~\ref{sec:hook:commit}) is run before this hook.
-
-See also: \hook{pretag} (section~\ref{sec:hook:pretag})
-
-\subsection{\hook{update}---after updating or merging working directory}
-\label{sec:hook:update}
-
-This hook is run after an update or merge of the working directory
-completes.  Since a merge can fail (if the external \command{hgmerge}
-command fails to resolve conflicts in a file), this hook communicates
-whether the update or merge completed cleanly.
-
-\begin{itemize}
-\item[\texttt{error}] A boolean.  Indicates whether the update or
-  merge completed successfully.
-\item[\texttt{parent1}] A changeset ID.  The ID of the parent that the
-  working directory was updated to.  If the working directory was
-  merged, it will not have changed this parent.
-\item[\texttt{parent2}] A changeset ID.  Only set if the working
-  directory was merged.  The ID of the revision that the working
-  directory was merged with.
-\end{itemize}
-
-See also: \hook{preupdate} (section~\ref{sec:hook:preupdate})
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/intro.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,561 +0,0 @@
-\chapter{Introduction}
-\label{chap:intro}
-
-\section{About revision control}
-
-Revision control is the process of managing multiple versions of a
-piece of information.  In its simplest form, this is something that
-many people do by hand: every time you modify a file, save it under a
-new name that contains a number, each one higher than the number of
-the preceding version.
-
-Manually managing multiple versions of even a single file is an
-error-prone task, though, so software tools to help automate this
-process have long been available.  The earliest automated revision
-control tools were intended to help a single user to manage revisions
-of a single file.  Over the past few decades, the scope of revision
-control tools has expanded greatly; they now manage multiple files,
-and help multiple people to work together.  The best modern revision
-control tools have no problem coping with thousands of people working
-together on projects that consist of hundreds of thousands of files.
-
-\subsection{Why use revision control?}
-
-There are a number of reasons why you or your team might want to use
-an automated revision control tool for a project.
-\begin{itemize}
-\item It will track the history and evolution of your project, so you
-  don't have to.  For every change, you'll have a log of \emph{who}
-  made it; \emph{why} they made it; \emph{when} they made it; and
-  \emph{what} the change was.
-\item When you're working with other people, revision control software
-  makes it easier for you to collaborate.  For example, when people
-  more or less simultaneously make potentially incompatible changes,
-  the software will help you to identify and resolve those conflicts.
-\item It can help you to recover from mistakes.  If you make a change
-  that later turns out to be in error, you can revert to an earlier
-  version of one or more files.  In fact, a \emph{really} good
-  revision control tool will even help you to efficiently figure out
-  exactly when a problem was introduced (see
-  section~\ref{sec:undo:bisect} for details).
-\item It will help you to work simultaneously on, and manage the drift
-  between, multiple versions of your project.
-\end{itemize}
-Most of these reasons are equally valid---at least in theory---whether
-you're working on a project by yourself, or with a hundred other
-people.
-
-A key question about the practicality of revision control at these two
-different scales (``lone hacker'' and ``huge team'') is how its
-\emph{benefits} compare to its \emph{costs}.  A revision control tool
-that's difficult to understand or use is going to impose a high cost.
-
-A five-hundred-person project is likely to collapse under its own
-weight almost immediately without a revision control tool and process.
-In this case, the cost of using revision control might hardly seem
-worth considering, since \emph{without} it, failure is almost
-guaranteed.
-
-On the other hand, a one-person ``quick hack'' might seem like a poor
-place to use a revision control tool, because surely the cost of using
-one must be close to the overall cost of the project.  Right?
-
-Mercurial uniquely supports \emph{both} of these scales of
-development.  You can learn the basics in just a few minutes, and due
-to its low overhead, you can apply revision control to the smallest of
-projects with ease.  Its simplicity means you won't have a lot of
-abstruse concepts or command sequences competing for mental space with
-whatever you're \emph{really} trying to do.  At the same time,
-Mercurial's high performance and peer-to-peer nature let you scale
-painlessly to handle large projects.
-
-No revision control tool can rescue a poorly run project, but a good
-choice of tools can make a huge difference to the fluidity with which
-you can work on a project.
-
-\subsection{The many names of revision control}
-
-Revision control is a diverse field, so much so that it doesn't
-actually have a single name or acronym.  Here are a few of the more
-common names and acronyms you'll encounter:
-\begin{itemize}
-\item Revision control (RCS)
-\item Software configuration management (SCM), or configuration management
-\item Source code management
-\item Source code control, or source control
-\item Version control (VCS)
-\end{itemize}
-Some people claim that these terms actually have different meanings,
-but in practice they overlap so much that there's no agreed or even
-useful way to tease them apart.
-
-\section{A short history of revision control}
-
-The best known of the old-time revision control tools is SCCS (Source
-Code Control System), which Marc Rochkind wrote at Bell Labs, in the
-early 1970s.  SCCS operated on individual files, and required every
-person working on a project to have access to a shared workspace on a
-single system.  Only one person could modify a file at any time;
-arbitration for access to files was via locks.  It was common for
-people to lock files, and later forget to unlock them, preventing
-anyone else from modifying those files without the help of an
-administrator.  
-
-Walter Tichy developed a free alternative to SCCS in the early 1980s;
-he called his program RCS (Revison Control System).  Like SCCS, RCS
-required developers to work in a single shared workspace, and to lock
-files to prevent multiple people from modifying them simultaneously.
-
-Later in the 1980s, Dick Grune used RCS as a building block for a set
-of shell scripts he initially called cmt, but then renamed to CVS
-(Concurrent Versions System).  The big innovation of CVS was that it
-let developers work simultaneously and somewhat independently in their
-own personal workspaces.  The personal workspaces prevented developers
-from stepping on each other's toes all the time, as was common with
-SCCS and RCS.  Each developer had a copy of every project file, and
-could modify their copies independently.  They had to merge their
-edits prior to committing changes to the central repository.
-
-Brian Berliner took Grune's original scripts and rewrote them in~C,
-releasing in 1989 the code that has since developed into the modern
-version of CVS.  CVS subsequently acquired the ability to operate over
-a network connection, giving it a client/server architecture.  CVS's
-architecture is centralised; only the server has a copy of the history
-of the project.  Client workspaces just contain copies of recent
-versions of the project's files, and a little metadata to tell them
-where the server is.  CVS has been enormously successful; it is
-probably the world's most widely used revision control system.
-
-In the early 1990s, Sun Microsystems developed an early distributed
-revision control system, called TeamWare.  A TeamWare workspace
-contains a complete copy of the project's history.  TeamWare has no
-notion of a central repository.  (CVS relied upon RCS for its history
-storage; TeamWare used SCCS.)
-
-As the 1990s progressed, awareness grew of a number of problems with
-CVS.  It records simultaneous changes to multiple files individually,
-instead of grouping them together as a single logically atomic
-operation.  It does not manage its file hierarchy well; it is easy to
-make a mess of a repository by renaming files and directories.  Worse,
-its source code is difficult to read and maintain, which made the
-``pain level'' of fixing these architectural problems prohibitive.
-
-In 2001, Jim Blandy and Karl Fogel, two developers who had worked on
-CVS, started a project to replace it with a tool that would have a
-better architecture and cleaner code.  The result, Subversion, does
-not stray from CVS's centralised client/server model, but it adds
-multi-file atomic commits, better namespace management, and a number
-of other features that make it a generally better tool than CVS.
-Since its initial release, it has rapidly grown in popularity.
-
-More or less simultaneously, Graydon Hoare began working on an
-ambitious distributed revision control system that he named Monotone.
-While Monotone addresses many of CVS's design flaws and has a
-peer-to-peer architecture, it goes beyond earlier (and subsequent)
-revision control tools in a number of innovative ways.  It uses
-cryptographic hashes as identifiers, and has an integral notion of
-``trust'' for code from different sources.
-
-Mercurial began life in 2005.  While a few aspects of its design are
-influenced by Monotone, Mercurial focuses on ease of use, high
-performance, and scalability to very large projects.
-
-\section{Trends in revision control}
-
-There has been an unmistakable trend in the development and use of
-revision control tools over the past four decades, as people have
-become familiar with the capabilities of their tools and constrained
-by their limitations.
-
-The first generation began by managing single files on individual
-computers.  Although these tools represented a huge advance over
-ad-hoc manual revision control, their locking model and reliance on a
-single computer limited them to small, tightly-knit teams.
-
-The second generation loosened these constraints by moving to
-network-centered architectures, and managing entire projects at a
-time.  As projects grew larger, they ran into new problems.  With
-clients needing to talk to servers very frequently, server scaling
-became an issue for large projects.  An unreliable network connection
-could prevent remote users from being able to talk to the server at
-all.  As open source projects started making read-only access
-available anonymously to anyone, people without commit privileges
-found that they could not use the tools to interact with a project in
-a natural way, as they could not record their changes.
-
-The current generation of revision control tools is peer-to-peer in
-nature.  All of these systems have dropped the dependency on a single
-central server, and allow people to distribute their revision control
-data to where it's actually needed.  Collaboration over the Internet
-has moved from constrained by technology to a matter of choice and
-consensus.  Modern tools can operate offline indefinitely and
-autonomously, with a network connection only needed when syncing
-changes with another repository.
-
-\section{A few of the advantages of distributed revision control}
-
-Even though distributed revision control tools have for several years
-been as robust and usable as their previous-generation counterparts,
-people using older tools have not yet necessarily woken up to their
-advantages.  There are a number of ways in which distributed tools
-shine relative to centralised ones.
-
-For an individual developer, distributed tools are almost always much
-faster than centralised tools.  This is for a simple reason: a
-centralised tool needs to talk over the network for many common
-operations, because most metadata is stored in a single copy on the
-central server.  A distributed tool stores all of its metadata
-locally.  All else being equal, talking over the network adds overhead
-to a centralised tool.  Don't underestimate the value of a snappy,
-responsive tool: you're going to spend a lot of time interacting with
-your revision control software.
-
-Distributed tools are indifferent to the vagaries of your server
-infrastructure, again because they replicate metadata to so many
-locations.  If you use a centralised system and your server catches
-fire, you'd better hope that your backup media are reliable, and that
-your last backup was recent and actually worked.  With a distributed
-tool, you have many backups available on every contributor's computer.
-
-The reliability of your network will affect distributed tools far less
-than it will centralised tools.  You can't even use a centralised tool
-without a network connection, except for a few highly constrained
-commands.  With a distributed tool, if your network connection goes
-down while you're working, you may not even notice.  The only thing
-you won't be able to do is talk to repositories on other computers,
-something that is relatively rare compared with local operations.  If
-you have a far-flung team of collaborators, this may be significant.
-
-\subsection{Advantages for open source projects}
-
-If you take a shine to an open source project and decide that you
-would like to start hacking on it, and that project uses a distributed
-revision control tool, you are at once a peer with the people who
-consider themselves the ``core'' of that project.  If they publish
-their repositories, you can immediately copy their project history,
-start making changes, and record your work, using the same tools in
-the same ways as insiders.  By contrast, with a centralised tool, you
-must use the software in a ``read only'' mode unless someone grants
-you permission to commit changes to their central server.  Until then,
-you won't be able to record changes, and your local modifications will
-be at risk of corruption any time you try to update your client's view
-of the repository.
-
-\subsubsection{The forking non-problem}
-
-It has been suggested that distributed revision control tools pose
-some sort of risk to open source projects because they make it easy to
-``fork'' the development of a project.  A fork happens when there are
-differences in opinion or attitude between groups of developers that
-cause them to decide that they can't work together any longer.  Each
-side takes a more or less complete copy of the project's source code,
-and goes off in its own direction.
-
-Sometimes the camps in a fork decide to reconcile their differences.
-With a centralised revision control system, the \emph{technical}
-process of reconciliation is painful, and has to be performed largely
-by hand.  You have to decide whose revision history is going to
-``win'', and graft the other team's changes into the tree somehow.
-This usually loses some or all of one side's revision history.
-
-What distributed tools do with respect to forking is they make forking
-the \emph{only} way to develop a project.  Every single change that
-you make is potentially a fork point.  The great strength of this
-approach is that a distributed revision control tool has to be really
-good at \emph{merging} forks, because forks are absolutely
-fundamental: they happen all the time.  
-
-If every piece of work that everybody does, all the time, is framed in
-terms of forking and merging, then what the open source world refers
-to as a ``fork'' becomes \emph{purely} a social issue.  If anything,
-distributed tools \emph{lower} the likelihood of a fork:
-\begin{itemize}
-\item They eliminate the social distinction that centralised tools
-  impose: that between insiders (people with commit access) and
-  outsiders (people without).
-\item They make it easier to reconcile after a social fork, because
-  all that's involved from the perspective of the revision control
-  software is just another merge.
-\end{itemize}
-
-Some people resist distributed tools because they want to retain tight
-control over their projects, and they believe that centralised tools
-give them this control.  However, if you're of this belief, and you
-publish your CVS or Subversion repositories publically, there are
-plenty of tools available that can pull out your entire project's
-history (albeit slowly) and recreate it somewhere that you don't
-control.  So while your control in this case is illusory, you are
-forgoing the ability to fluidly collaborate with whatever people feel
-compelled to mirror and fork your history.
-
-\subsection{Advantages for commercial projects}
-
-Many commercial projects are undertaken by teams that are scattered
-across the globe.  Contributors who are far from a central server will
-see slower command execution and perhaps less reliability.  Commercial
-revision control systems attempt to ameliorate these problems with
-remote-site replication add-ons that are typically expensive to buy
-and cantankerous to administer.  A distributed system doesn't suffer
-from these problems in the first place.  Better yet, you can easily
-set up multiple authoritative servers, say one per site, so that
-there's no redundant communication between repositories over expensive
-long-haul network links.
-
-Centralised revision control systems tend to have relatively low
-scalability.  It's not unusual for an expensive centralised system to
-fall over under the combined load of just a few dozen concurrent
-users.  Once again, the typical response tends to be an expensive and
-clunky replication facility.  Since the load on a central server---if
-you have one at all---is many times lower with a distributed
-tool (because all of the data is replicated everywhere), a single
-cheap server can handle the needs of a much larger team, and
-replication to balance load becomes a simple matter of scripting.
-
-If you have an employee in the field, troubleshooting a problem at a
-customer's site, they'll benefit from distributed revision control.
-The tool will let them generate custom builds, try different fixes in
-isolation from each other, and search efficiently through history for
-the sources of bugs and regressions in the customer's environment, all
-without needing to connect to your company's network.
-
-\section{Why choose Mercurial?}
-
-Mercurial has a unique set of properties that make it a particularly
-good choice as a revision control system.
-\begin{itemize}
-\item It is easy to learn and use.
-\item It is lightweight.
-\item It scales excellently.
-\item It is easy to customise.
-\end{itemize}
-
-If you are at all familiar with revision control systems, you should
-be able to get up and running with Mercurial in less than five
-minutes.  Even if not, it will take no more than a few minutes
-longer.  Mercurial's command and feature sets are generally uniform
-and consistent, so you can keep track of a few general rules instead
-of a host of exceptions.
-
-On a small project, you can start working with Mercurial in moments.
-Creating new changes and branches; transferring changes around
-(whether locally or over a network); and history and status operations
-are all fast.  Mercurial attempts to stay nimble and largely out of
-your way by combining low cognitive overhead with blazingly fast
-operations.
-
-The usefulness of Mercurial is not limited to small projects: it is
-used by projects with hundreds to thousands of contributors, each
-containing tens of thousands of files and hundreds of megabytes of
-source code.
-
-If the core functionality of Mercurial is not enough for you, it's
-easy to build on.  Mercurial is well suited to scripting tasks, and
-its clean internals and implementation in Python make it easy to add
-features in the form of extensions.  There are a number of popular and
-useful extensions already available, ranging from helping to identify
-bugs to improving performance.
-
-\section{Mercurial compared with other tools}
-
-Before you read on, please understand that this section necessarily
-reflects my own experiences, interests, and (dare I say it) biases.  I
-have used every one of the revision control tools listed below, in
-most cases for several years at a time.
-
-
-\subsection{Subversion}
-
-Subversion is a popular revision control tool, developed to replace
-CVS.  It has a centralised client/server architecture.
-
-Subversion and Mercurial have similarly named commands for performing
-the same operations, so if you're familiar with one, it is easy to
-learn to use the other.  Both tools are portable to all popular
-operating systems.
-
-Prior to version 1.5, Subversion had no useful support for merges.
-At the time of writing, its merge tracking capability is new, and known to be
-\href{http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword}{complicated
-  and buggy}.
-
-Mercurial has a substantial performance advantage over Subversion on
-every revision control operation I have benchmarked.  I have measured
-its advantage as ranging from a factor of two to a factor of six when
-compared with Subversion~1.4.3's \emph{ra\_local} file store, which is
-the fastest access method available.  In more realistic deployments
-involving a network-based store, Subversion will be at a substantially
-larger disadvantage.  Because many Subversion commands must talk to
-the server and Subversion does not have useful replication facilities,
-server capacity and network bandwidth become bottlenecks for modestly
-large projects.
-
-Additionally, Subversion incurs substantial storage overhead to avoid
-network transactions for a few common operations, such as finding
-modified files (\texttt{status}) and displaying modifications against
-the current revision (\texttt{diff}).  As a result, a Subversion
-working copy is often the same size as, or larger than, a Mercurial
-repository and working directory, even though the Mercurial repository
-contains a complete history of the project.
-
-Subversion is widely supported by third party tools.  Mercurial
-currently lags considerably in this area.  This gap is closing,
-however, and indeed some of Mercurial's GUI tools now outshine their
-Subversion equivalents.  Like Mercurial, Subversion has an excellent
-user manual.
-
-Because Subversion doesn't store revision history on the client, it is
-well suited to managing projects that deal with lots of large, opaque
-binary files.  If you check in fifty revisions to an incompressible
-10MB file, Subversion's client-side space usage stays constant The
-space used by any distributed SCM will grow rapidly in proportion to
-the number of revisions, because the differences between each revision
-are large.
-
-In addition, it's often difficult or, more usually, impossible to
-merge different versions of a binary file.  Subversion's ability to
-let a user lock a file, so that they temporarily have the exclusive
-right to commit changes to it, can be a significant advantage to a
-project where binary files are widely used.
-
-Mercurial can import revision history from a Subversion repository.
-It can also export revision history to a Subversion repository.  This
-makes it easy to ``test the waters'' and use Mercurial and Subversion
-in parallel before deciding to switch.  History conversion is
-incremental, so you can perform an initial conversion, then small
-additional conversions afterwards to bring in new changes.
-
-
-\subsection{Git}
-
-Git is a distributed revision control tool that was developed for
-managing the Linux kernel source tree.  Like Mercurial, its early
-design was somewhat influenced by Monotone.
-
-Git has a very large command set, with version~1.5.0 providing~139
-individual commands.  It has something of a reputation for being
-difficult to learn.  Compared to Git, Mercurial has a strong focus on
-simplicity.
-
-In terms of performance, Git is extremely fast.  In several cases, it
-is faster than Mercurial, at least on Linux, while Mercurial performs
-better on other operations.  However, on Windows, the performance and
-general level of support that Git provides is, at the time of writing,
-far behind that of Mercurial.
-
-While a Mercurial repository needs no maintenance, a Git repository
-requires frequent manual ``repacks'' of its metadata.  Without these,
-performance degrades, while space usage grows rapidly.  A server that
-contains many Git repositories that are not rigorously and frequently
-repacked will become heavily disk-bound during backups, and there have
-been instances of daily backups taking far longer than~24 hours as a
-result.  A freshly packed Git repository is slightly smaller than a
-Mercurial repository, but an unpacked repository is several orders of
-magnitude larger.
-
-The core of Git is written in C.  Many Git commands are implemented as
-shell or Perl scripts, and the quality of these scripts varies widely.
-I have encountered several instances where scripts charged along
-blindly in the presence of errors that should have been fatal.
-
-Mercurial can import revision history from a Git repository.
-
-
-\subsection{CVS}
-
-CVS is probably the most widely used revision control tool in the
-world.  Due to its age and internal untidiness, it has been only
-lightly maintained for many years.
-
-It has a centralised client/server architecture.  It does not group
-related file changes into atomic commits, making it easy for people to
-``break the build'': one person can successfully commit part of a
-change and then be blocked by the need for a merge, causing other
-people to see only a portion of the work they intended to do.  This
-also affects how you work with project history.  If you want to see
-all of the modifications someone made as part of a task, you will need
-to manually inspect the descriptions and timestamps of the changes
-made to each file involved (if you even know what those files were).
-
-CVS has a muddled notion of tags and branches that I will not attempt
-to even describe.  It does not support renaming of files or
-directories well, making it easy to corrupt a repository.  It has
-almost no internal consistency checking capabilities, so it is usually
-not even possible to tell whether or how a repository is corrupt.  I
-would not recommend CVS for any project, existing or new.
-
-Mercurial can import CVS revision history.  However, there are a few
-caveats that apply; these are true of every other revision control
-tool's CVS importer, too.  Due to CVS's lack of atomic changes and
-unversioned filesystem hierarchy, it is not possible to reconstruct
-CVS history completely accurately; some guesswork is involved, and
-renames will usually not show up.  Because a lot of advanced CVS
-administration has to be done by hand and is hence error-prone, it's
-common for CVS importers to run into multiple problems with corrupted
-repositories (completely bogus revision timestamps and files that have
-remained locked for over a decade are just two of the less interesting
-problems I can recall from personal experience).
-
-Mercurial can import revision history from a CVS repository.
-
-
-\subsection{Commercial tools}
-
-Perforce has a centralised client/server architecture, with no
-client-side caching of any data.  Unlike modern revision control
-tools, Perforce requires that a user run a command to inform the
-server about every file they intend to edit.
-
-The performance of Perforce is quite good for small teams, but it
-falls off rapidly as the number of users grows beyond a few dozen.
-Modestly large Perforce installations require the deployment of
-proxies to cope with the load their users generate.
-
-
-\subsection{Choosing a revision control tool}
-
-With the exception of CVS, all of the tools listed above have unique
-strengths that suit them to particular styles of work.  There is no
-single revision control tool that is best in all situations.
-
-As an example, Subversion is a good choice for working with frequently
-edited binary files, due to its centralised nature and support for
-file locking.
-
-I personally find Mercurial's properties of simplicity, performance,
-and good merge support to be a compelling combination that has served
-me well for several years.
-
-
-\section{Switching from another tool to Mercurial}
-
-Mercurial is bundled with an extension named \hgext{convert}, which
-can incrementally import revision history from several other revision
-control tools.  By ``incremental'', I mean that you can convert all of
-a project's history to date in one go, then rerun the conversion later
-to obtain new changes that happened after the initial conversion.
-
-The revision control tools supported by \hgext{convert} are as
-follows:
-\begin{itemize}
-\item Subversion
-\item CVS
-\item Git
-\item Darcs
-\end{itemize}
-
-In addition, \hgext{convert} can export changes from Mercurial to
-Subversion.  This makes it possible to try Subversion and Mercurial in
-parallel before committing to a switchover, without risking the loss
-of any work.
-
-The \hgxcmd{conver}{convert} command is easy to use.  Simply point it
-at the path or URL of the source repository, optionally give it the
-name of the destination repository, and it will start working.  After
-the initial conversion, just run the same command again to import new
-changes.
-
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/license.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-\chapter{Open Publication License}
-\label{cha:opl}
-
-Version 1.0, 8 June 1999
-
-\section{Requirements on both unmodified and modified versions}
-
-The Open Publication works may be reproduced and distributed in whole
-or in part, in any medium physical or electronic, provided that the
-terms of this license are adhered to, and that this license or an
-incorporation of it by reference (with any options elected by the
-author(s) and/or publisher) is displayed in the reproduction.
-
-Proper form for an incorporation by reference is as follows:
-
-\begin{quote}
-  Copyright (c) \emph{year} by \emph{author's name or designee}. This
-  material may be distributed only subject to the terms and conditions
-  set forth in the Open Publication License, v\emph{x.y} or later (the
-  latest version is presently available at
-  \url{http://www.opencontent.org/openpub/}).
-\end{quote}
-
-The reference must be immediately followed with any options elected by
-the author(s) and/or publisher of the document (see
-section~\ref{sec:opl:options}).
-
-Commercial redistribution of Open Publication-licensed material is
-permitted.
-
-Any publication in standard (paper) book form shall require the
-citation of the original publisher and author. The publisher and
-author's names shall appear on all outer surfaces of the book. On all
-outer surfaces of the book the original publisher's name shall be as
-large as the title of the work and cited as possessive with respect to
-the title.
-
-\section{Copyright}
-
-The copyright to each Open Publication is owned by its author(s) or
-designee.
-
-\section{Scope of license}
-
-The following license terms apply to all Open Publication works,
-unless otherwise explicitly stated in the document.
-
-Mere aggregation of Open Publication works or a portion of an Open
-Publication work with other works or programs on the same media shall
-not cause this license to apply to those other works. The aggregate
-work shall contain a notice specifying the inclusion of the Open
-Publication material and appropriate copyright notice.
-
-\textbf{Severability}. If any part of this license is found to be
-unenforceable in any jurisdiction, the remaining portions of the
-license remain in force.
-
-\textbf{No warranty}. Open Publication works are licensed and provided
-``as is'' without warranty of any kind, express or implied, including,
-but not limited to, the implied warranties of merchantability and
-fitness for a particular purpose or a warranty of non-infringement.
-
-\section{Requirements on modified works}
-
-All modified versions of documents covered by this license, including
-translations, anthologies, compilations and partial documents, must
-meet the following requirements:
-
-\begin{enumerate}
-\item The modified version must be labeled as such.
-\item The person making the modifications must be identified and the
-  modifications dated.
-\item Acknowledgement of the original author and publisher if
-  applicable must be retained according to normal academic citation
-  practices.
-\item The location of the original unmodified document must be
-  identified.
-\item The original author's (or authors') name(s) may not be used to
-  assert or imply endorsement of the resulting document without the
-  original author's (or authors') permission.
-\end{enumerate}
-
-\section{Good-practice recommendations}
-
-In addition to the requirements of this license, it is requested from
-and strongly recommended of redistributors that:
-
-\begin{enumerate}
-\item If you are distributing Open Publication works on hardcopy or
-  CD-ROM, you provide email notification to the authors of your intent
-  to redistribute at least thirty days before your manuscript or media
-  freeze, to give the authors time to provide updated documents. This
-  notification should describe modifications, if any, made to the
-  document.
-\item All substantive modifications (including deletions) be either
-  clearly marked up in the document or else described in an attachment
-  to the document.
-\item Finally, while it is not mandatory under this license, it is
-  considered good form to offer a free copy of any hardcopy and CD-ROM
-  expression of an Open Publication-licensed work to its author(s).
-\end{enumerate}
-
-\section{License options}
-\label{sec:opl:options}
-
-The author(s) and/or publisher of an Open Publication-licensed
-document may elect certain options by appending language to the
-reference to or copy of the license. These options are considered part
-of the license instance and must be included with the license (or its
-incorporation by reference) in derived works.
-
-\begin{enumerate}[A]
-\item To prohibit distribution of substantively modified versions
-  without the explicit permission of the author(s). ``Substantive
-  modification'' is defined as a change to the semantic content of the
-  document, and excludes mere changes in format or typographical
-  corrections.
-
-  To accomplish this, add the phrase ``Distribution of substantively
-  modified versions of this document is prohibited without the
-  explicit permission of the copyright holder.'' to the license
-  reference or copy.
-
-\item To prohibit any publication of this work or derivative works in
-  whole or in part in standard (paper) book form for commercial
-  purposes is prohibited unless prior permission is obtained from the
-  copyright holder.
-
-  To accomplish this, add the phrase ``Distribution of the work or
-  derivative of the work in any standard (paper) book form is
-  prohibited unless prior permission is obtained from the copyright
-  holder.'' to the license reference or copy.
-\end{enumerate}
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/mq-collab.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,393 +0,0 @@
-\chapter{Advanced uses of Mercurial Queues}
-\label{chap:mq-collab}
-
-While it's easy to pick up straightforward uses of Mercurial Queues,
-use of a little discipline and some of MQ's less frequently used
-capabilities makes it possible to work in complicated development
-environments.
-
-In this chapter, I will use as an example a technique I have used to
-manage the development of an Infiniband device driver for the Linux
-kernel.  The driver in question is large (at least as drivers go),
-with 25,000 lines of code spread across 35 source files.  It is
-maintained by a small team of developers.
-
-While much of the material in this chapter is specific to Linux, the
-same principles apply to any code base for which you're not the
-primary owner, and upon which you need to do a lot of development.
-
-\section{The problem of many targets}
-
-The Linux kernel changes rapidly, and has never been internally
-stable; developers frequently make drastic changes between releases.
-This means that a version of the driver that works well with a
-particular released version of the kernel will not even \emph{compile}
-correctly against, typically, any other version.
-
-To maintain a driver, we have to keep a number of distinct versions of
-Linux in mind.
-\begin{itemize}
-\item One target is the main Linux kernel development tree.
-  Maintenance of the code is in this case partly shared by other
-  developers in the kernel community, who make ``drive-by''
-  modifications to the driver as they develop and refine kernel
-  subsystems.
-\item We also maintain a number of ``backports'' to older versions of
-  the Linux kernel, to support the needs of customers who are running
-  older Linux distributions that do not incorporate our drivers.  (To
-  \emph{backport} a piece of code is to modify it to work in an older
-  version of its target environment than the version it was developed
-  for.)
-\item Finally, we make software releases on a schedule that is
-  necessarily not aligned with those used by Linux distributors and
-  kernel developers, so that we can deliver new features to customers
-  without forcing them to upgrade their entire kernels or
-  distributions.
-\end{itemize}
-
-\subsection{Tempting approaches that don't work well}
-
-There are two ``standard'' ways to maintain a piece of software that
-has to target many different environments.
-
-The first is to maintain a number of branches, each intended for a
-single target.  The trouble with this approach is that you must
-maintain iron discipline in the flow of changes between repositories.
-A new feature or bug fix must start life in a ``pristine'' repository,
-then percolate out to every backport repository.  Backport changes are
-more limited in the branches they should propagate to; a backport
-change that is applied to a branch where it doesn't belong will
-probably stop the driver from compiling.
-
-The second is to maintain a single source tree filled with conditional
-statements that turn chunks of code on or off depending on the
-intended target.  Because these ``ifdefs'' are not allowed in the
-Linux kernel tree, a manual or automatic process must be followed to
-strip them out and yield a clean tree.  A code base maintained in this
-fashion rapidly becomes a rat's nest of conditional blocks that are
-difficult to understand and maintain.
-
-Neither of these approaches is well suited to a situation where you
-don't ``own'' the canonical copy of a source tree.  In the case of a
-Linux driver that is distributed with the standard kernel, Linus's
-tree contains the copy of the code that will be treated by the world
-as canonical.  The upstream version of ``my'' driver can be modified
-by people I don't know, without me even finding out about it until
-after the changes show up in Linus's tree.  
-
-These approaches have the added weakness of making it difficult to
-generate well-formed patches to submit upstream.
-
-In principle, Mercurial Queues seems like a good candidate to manage a
-development scenario such as the above.  While this is indeed the
-case, MQ contains a few added features that make the job more
-pleasant.
-
-\section{Conditionally applying patches with 
-  guards}
-
-Perhaps the best way to maintain sanity with so many targets is to be
-able to choose specific patches to apply for a given situation.  MQ
-provides a feature called ``guards'' (which originates with quilt's
-\texttt{guards} command) that does just this.  To start off, let's
-create a simple repository for experimenting in.
-\interaction{mq.guards.init}
-This gives us a tiny repository that contains two patches that don't
-have any dependencies on each other, because they touch different files.
-
-The idea behind conditional application is that you can ``tag'' a
-patch with a \emph{guard}, which is simply a text string of your
-choosing, then tell MQ to select specific guards to use when applying
-patches.  MQ will then either apply, or skip over, a guarded patch,
-depending on the guards that you have selected.
-
-A patch can have an arbitrary number of guards;
-each one is \emph{positive} (``apply this patch if this guard is
-selected'') or \emph{negative} (``skip this patch if this guard is
-selected'').  A patch with no guards is always applied.
-
-\section{Controlling the guards on a patch}
-
-The \hgxcmd{mq}{qguard} command lets you determine which guards should
-apply to a patch, or display the guards that are already in effect.
-Without any arguments, it displays the guards on the current topmost
-patch.
-\interaction{mq.guards.qguard}
-To set a positive guard on a patch, prefix the name of the guard with
-a ``\texttt{+}''.
-\interaction{mq.guards.qguard.pos}
-To set a negative guard on a patch, prefix the name of the guard with
-a ``\texttt{-}''.
-\interaction{mq.guards.qguard.neg}
-
-\begin{note}
-  The \hgxcmd{mq}{qguard} command \emph{sets} the guards on a patch; it
-  doesn't \emph{modify} them.  What this means is that if you run
-  \hgcmdargs{qguard}{+a +b} on a patch, then \hgcmdargs{qguard}{+c} on
-  the same patch, the \emph{only} guard that will be set on it
-  afterwards is \texttt{+c}.
-\end{note}
-
-Mercurial stores guards in the \sfilename{series} file; the form in
-which they are stored is easy both to understand and to edit by hand.
-(In other words, you don't have to use the \hgxcmd{mq}{qguard} command if
-you don't want to; it's okay to simply edit the \sfilename{series}
-file.)
-\interaction{mq.guards.series}
-
-\section{Selecting the guards to use}
-
-The \hgxcmd{mq}{qselect} command determines which guards are active at a
-given time.  The effect of this is to determine which patches MQ will
-apply the next time you run \hgxcmd{mq}{qpush}.  It has no other effect; in
-particular, it doesn't do anything to patches that are already
-applied.
-
-With no arguments, the \hgxcmd{mq}{qselect} command lists the guards
-currently in effect, one per line of output.  Each argument is treated
-as the name of a guard to apply.
-\interaction{mq.guards.qselect.foo}
-In case you're interested, the currently selected guards are stored in
-the \sfilename{guards} file.
-\interaction{mq.guards.qselect.cat}
-We can see the effect the selected guards have when we run
-\hgxcmd{mq}{qpush}.
-\interaction{mq.guards.qselect.qpush}
-
-A guard cannot start with a ``\texttt{+}'' or ``\texttt{-}''
-character.  The name of a guard must not contain white space, but most
-other characters are acceptable.  If you try to use a guard with an
-invalid name, MQ will complain:
-\interaction{mq.guards.qselect.error} 
-Changing the selected guards changes the patches that are applied.
-\interaction{mq.guards.qselect.quux} 
-You can see in the example below that negative guards take precedence
-over positive guards.
-\interaction{mq.guards.qselect.foobar}
-
-\section{MQ's rules for applying patches}
-
-The rules that MQ uses when deciding whether to apply a patch
-are as follows.
-\begin{itemize}
-\item A patch that has no guards is always applied.
-\item If the patch has any negative guard that matches any currently
-  selected guard, the patch is skipped.
-\item If the patch has any positive guard that matches any currently
-  selected guard, the patch is applied.
-\item If the patch has positive or negative guards, but none matches
-  any currently selected guard, the patch is skipped.
-\end{itemize}
-
-\section{Trimming the work environment}
-
-In working on the device driver I mentioned earlier, I don't apply the
-patches to a normal Linux kernel tree.  Instead, I use a repository
-that contains only a snapshot of the source files and headers that are
-relevant to Infiniband development.  This repository is~1\% the size
-of a kernel repository, so it's easier to work with.
-
-I then choose a ``base'' version on top of which the patches are
-applied.  This is a snapshot of the Linux kernel tree as of a revision
-of my choosing.  When I take the snapshot, I record the changeset ID
-from the kernel repository in the commit message.  Since the snapshot
-preserves the ``shape'' and content of the relevant parts of the
-kernel tree, I can apply my patches on top of either my tiny
-repository or a normal kernel tree.
-
-Normally, the base tree atop which the patches apply should be a
-snapshot of a very recent upstream tree.  This best facilitates the
-development of patches that can easily be submitted upstream with few
-or no modifications.
-
-\section{Dividing up the \sfilename{series} file}
-
-I categorise the patches in the \sfilename{series} file into a number
-of logical groups.  Each section of like patches begins with a block
-of comments that describes the purpose of the patches that follow.
-
-The sequence of patch groups that I maintain follows.  The ordering of
-these groups is important; I'll describe why after I introduce the
-groups.
-\begin{itemize}
-\item The ``accepted'' group.  Patches that the development team has
-  submitted to the maintainer of the Infiniband subsystem, and which
-  he has accepted, but which are not present in the snapshot that the
-  tiny repository is based on.  These are ``read only'' patches,
-  present only to transform the tree into a similar state as it is in
-  the upstream maintainer's repository.
-\item The ``rework'' group.  Patches that I have submitted, but that
-  the upstream maintainer has requested modifications to before he
-  will accept them.
-\item The ``pending'' group.  Patches that I have not yet submitted to
-  the upstream maintainer, but which we have finished working on.
-  These will be ``read only'' for a while.  If the upstream maintainer
-  accepts them upon submission, I'll move them to the end of the
-  ``accepted'' group.  If he requests that I modify any, I'll move
-  them to the beginning of the ``rework'' group.
-\item The ``in progress'' group.  Patches that are actively being
-  developed, and should not be submitted anywhere yet.
-\item The ``backport'' group.  Patches that adapt the source tree to
-  older versions of the kernel tree.
-\item The ``do not ship'' group.  Patches that for some reason should
-  never be submitted upstream.  For example, one such patch might
-  change embedded driver identification strings to make it easier to
-  distinguish, in the field, between an out-of-tree version of the
-  driver and a version shipped by a distribution vendor.
-\end{itemize}
-
-Now to return to the reasons for ordering groups of patches in this
-way.  We would like the lowest patches in the stack to be as stable as
-possible, so that we will not need to rework higher patches due to
-changes in context.  Putting patches that will never be changed first
-in the \sfilename{series} file serves this purpose.
-
-We would also like the patches that we know we'll need to modify to be
-applied on top of a source tree that resembles the upstream tree as
-closely as possible.  This is why we keep accepted patches around for
-a while.
-
-The ``backport'' and ``do not ship'' patches float at the end of the
-\sfilename{series} file.  The backport patches must be applied on top
-of all other patches, and the ``do not ship'' patches might as well
-stay out of harm's way.
-
-\section{Maintaining the patch series}
-
-In my work, I use a number of guards to control which patches are to
-be applied.
-
-\begin{itemize}
-\item ``Accepted'' patches are guarded with \texttt{accepted}.  I
-  enable this guard most of the time.  When I'm applying the patches
-  on top of a tree where the patches are already present, I can turn
-  this patch off, and the patches that follow it will apply cleanly.
-\item Patches that are ``finished'', but not yet submitted, have no
-  guards.  If I'm applying the patch stack to a copy of the upstream
-  tree, I don't need to enable any guards in order to get a reasonably
-  safe source tree.
-\item Those patches that need reworking before being resubmitted are
-  guarded with \texttt{rework}.
-\item For those patches that are still under development, I use
-  \texttt{devel}.
-\item A backport patch may have several guards, one for each version
-  of the kernel to which it applies.  For example, a patch that
-  backports a piece of code to~2.6.9 will have a~\texttt{2.6.9} guard.
-\end{itemize}
-This variety of guards gives me considerable flexibility in
-determining what kind of source tree I want to end up with.  For most
-situations, the selection of appropriate guards is automated during
-the build process, but I can manually tune the guards to use for less
-common circumstances.
-
-\subsection{The art of writing backport patches}
-
-Using MQ, writing a backport patch is a simple process.  All such a
-patch has to do is modify a piece of code that uses a kernel feature
-not present in the older version of the kernel, so that the driver
-continues to work correctly under that older version.
-
-A useful goal when writing a good backport patch is to make your code
-look as if it was written for the older version of the kernel you're
-targeting.  The less obtrusive the patch, the easier it will be to
-understand and maintain.  If you're writing a collection of backport
-patches to avoid the ``rat's nest'' effect of lots of
-\texttt{\#ifdef}s (hunks of source code that are only used
-conditionally) in your code, don't introduce version-dependent
-\texttt{\#ifdef}s into the patches.  Instead, write several patches,
-each of which makes unconditional changes, and control their
-application using guards.
-
-There are two reasons to divide backport patches into a distinct
-group, away from the ``regular'' patches whose effects they modify.
-The first is that intermingling the two makes it more difficult to use
-a tool like the \hgext{patchbomb} extension to automate the process of
-submitting the patches to an upstream maintainer.  The second is that
-a backport patch could perturb the context in which a subsequent
-regular patch is applied, making it impossible to apply the regular
-patch cleanly \emph{without} the earlier backport patch already being
-applied.
-
-\section{Useful tips for developing with MQ}
-
-\subsection{Organising patches in directories}
-
-If you're working on a substantial project with MQ, it's not difficult
-to accumulate a large number of patches.  For example, I have one
-patch repository that contains over 250 patches.
-
-If you can group these patches into separate logical categories, you
-can if you like store them in different directories; MQ has no
-problems with patch names that contain path separators.
-
-\subsection{Viewing the history of a patch}
-\label{mq-collab:tips:interdiff}
-
-If you're developing a set of patches over a long time, it's a good
-idea to maintain them in a repository, as discussed in
-section~\ref{sec:mq:repo}.  If you do so, you'll quickly discover that
-using the \hgcmd{diff} command to look at the history of changes to a
-patch is unworkable.  This is in part because you're looking at the
-second derivative of the real code (a diff of a diff), but also
-because MQ adds noise to the process by modifying time stamps and
-directory names when it updates a patch.
-
-However, you can use the \hgext{extdiff} extension, which is bundled
-with Mercurial, to turn a diff of two versions of a patch into
-something readable.  To do this, you will need a third-party package
-called \package{patchutils}~\cite{web:patchutils}.  This provides a
-command named \command{interdiff}, which shows the differences between
-two diffs as a diff.  Used on two versions of the same diff, it
-generates a diff that represents the diff from the first to the second
-version.
-
-You can enable the \hgext{extdiff} extension in the usual way, by
-adding a line to the \rcsection{extensions} section of your \hgrc.
-\begin{codesample2}
-  [extensions]
-  extdiff =
-\end{codesample2}
-The \command{interdiff} command expects to be passed the names of two
-files, but the \hgext{extdiff} extension passes the program it runs a
-pair of directories, each of which can contain an arbitrary number of
-files.  We thus need a small program that will run \command{interdiff}
-on each pair of files in these two directories.  This program is
-available as \sfilename{hg-interdiff} in the \dirname{examples}
-directory of the source code repository that accompanies this book.
-\excode{hg-interdiff}
-
-With the \sfilename{hg-interdiff} program in your shell's search path,
-you can run it as follows, from inside an MQ patch directory:
-\begin{codesample2}
-  hg extdiff -p hg-interdiff -r A:B my-change.patch
-\end{codesample2}
-Since you'll probably want to use this long-winded command a lot, you
-can get \hgext{hgext} to make it available as a normal Mercurial
-command, again by editing your \hgrc.
-\begin{codesample2}
-  [extdiff]
-  cmd.interdiff = hg-interdiff
-\end{codesample2}
-This directs \hgext{hgext} to make an \texttt{interdiff} command
-available, so you can now shorten the previous invocation of
-\hgxcmd{extdiff}{extdiff} to something a little more wieldy.
-\begin{codesample2}
-  hg interdiff -r A:B my-change.patch
-\end{codesample2}
-
-\begin{note}
-  The \command{interdiff} command works well only if the underlying
-  files against which versions of a patch are generated remain the
-  same.  If you create a patch, modify the underlying files, and then
-  regenerate the patch, \command{interdiff} may not produce useful
-  output.
-\end{note}
-
-The \hgext{extdiff} extension is useful for more than merely improving
-the presentation of MQ~patches.  To read more about it, go to
-section~\ref{sec:hgext:extdiff}.
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/mq-ref.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,349 +0,0 @@
-\chapter{Mercurial Queues reference}
-\label{chap:mqref}
-
-\section{MQ command reference}
-\label{sec:mqref:cmdref}
-
-For an overview of the commands provided by MQ, use the command
-\hgcmdargs{help}{mq}.
-
-\subsection{\hgxcmd{mq}{qapplied}---print applied patches}
-
-The \hgxcmd{mq}{qapplied} command prints the current stack of applied
-patches.  Patches are printed in oldest-to-newest order, so the last
-patch in the list is the ``top'' patch.
-
-\subsection{\hgxcmd{mq}{qcommit}---commit changes in the queue repository}
-
-The \hgxcmd{mq}{qcommit} command commits any outstanding changes in the
-\sdirname{.hg/patches} repository.  This command only works if the
-\sdirname{.hg/patches} directory is a repository, i.e.~you created the
-directory using \hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} or ran
-\hgcmd{init} in the directory after running \hgxcmd{mq}{qinit}.
-
-This command is shorthand for \hgcmdargs{commit}{--cwd .hg/patches}.
-
-\subsection{\hgxcmd{mq}{qdelete}---delete a patch from the
-  \sfilename{series} file}
-
-The \hgxcmd{mq}{qdelete} command removes the entry for a patch from the
-\sfilename{series} file in the \sdirname{.hg/patches} directory.  It
-does not pop the patch if the patch is already applied.  By default,
-it does not delete the patch file; use the \hgxopt{mq}{qdel}{-f} option to
-do that.
-
-Options:
-\begin{itemize}
-\item[\hgxopt{mq}{qdel}{-f}] Delete the patch file.
-\end{itemize}
-
-\subsection{\hgxcmd{mq}{qdiff}---print a diff of the topmost applied patch}
-
-The \hgxcmd{mq}{qdiff} command prints a diff of the topmost applied patch.
-It is equivalent to \hgcmdargs{diff}{-r-2:-1}.
-
-\subsection{\hgxcmd{mq}{qfold}---merge (``fold'') several patches into one}
-
-The \hgxcmd{mq}{qfold} command merges multiple patches into the topmost
-applied patch, so that the topmost applied patch makes the union of
-all of the changes in the patches in question.
-
-The patches to fold must not be applied; \hgxcmd{mq}{qfold} will exit with
-an error if any is.  The order in which patches are folded is
-significant; \hgcmdargs{qfold}{a b} means ``apply the current topmost
-patch, followed by \texttt{a}, followed by \texttt{b}''.
-
-The comments from the folded patches are appended to the comments of
-the destination patch, with each block of comments separated by three
-asterisk (``\texttt{*}'') characters.  Use the \hgxopt{mq}{qfold}{-e}
-option to edit the commit message for the combined patch/changeset
-after the folding has completed.
-
-Options:
-\begin{itemize}
-\item[\hgxopt{mq}{qfold}{-e}] Edit the commit message and patch description
-  for the newly folded patch.
-\item[\hgxopt{mq}{qfold}{-l}] Use the contents of the given file as the new
-  commit message and patch description for the folded patch.
-\item[\hgxopt{mq}{qfold}{-m}] Use the given text as the new commit message
-  and patch description for the folded patch.
-\end{itemize}
-
-\subsection{\hgxcmd{mq}{qheader}---display the header/description of a patch}
-
-The \hgxcmd{mq}{qheader} command prints the header, or description, of a
-patch.  By default, it prints the header of the topmost applied patch.
-Given an argument, it prints the header of the named patch.
-
-\subsection{\hgxcmd{mq}{qimport}---import a third-party patch into the queue}
-
-The \hgxcmd{mq}{qimport} command adds an entry for an external patch to the
-\sfilename{series} file, and copies the patch into the
-\sdirname{.hg/patches} directory.  It adds the entry immediately after
-the topmost applied patch, but does not push the patch.
-
-If the \sdirname{.hg/patches} directory is a repository,
-\hgxcmd{mq}{qimport} automatically does an \hgcmd{add} of the imported
-patch.
-
-\subsection{\hgxcmd{mq}{qinit}---prepare a repository to work with MQ}
-
-The \hgxcmd{mq}{qinit} command prepares a repository to work with MQ.  It
-creates a directory called \sdirname{.hg/patches}.
-
-Options:
-\begin{itemize}
-\item[\hgxopt{mq}{qinit}{-c}] Create \sdirname{.hg/patches} as a repository
-  in its own right.  Also creates a \sfilename{.hgignore} file that
-  will ignore the \sfilename{status} file.
-\end{itemize}
-
-When the \sdirname{.hg/patches} directory is a repository, the
-\hgxcmd{mq}{qimport} and \hgxcmd{mq}{qnew} commands automatically \hgcmd{add}
-new patches.
-
-\subsection{\hgxcmd{mq}{qnew}---create a new patch}
-
-The \hgxcmd{mq}{qnew} command creates a new patch.  It takes one mandatory
-argument, the name to use for the patch file.  The newly created patch
-is created empty by default.  It is added to the \sfilename{series}
-file after the current topmost applied patch, and is immediately
-pushed on top of that patch.
-
-If \hgxcmd{mq}{qnew} finds modified files in the working directory, it will
-refuse to create a new patch unless the \hgxopt{mq}{qnew}{-f} option is
-used (see below).  This behaviour allows you to \hgxcmd{mq}{qrefresh} your
-topmost applied patch before you apply a new patch on top of it.
-
-Options:
-\begin{itemize}
-\item[\hgxopt{mq}{qnew}{-f}] Create a new patch if the contents of the
-  working directory are modified.  Any outstanding modifications are
-  added to the newly created patch, so after this command completes,
-  the working directory will no longer be modified.
-\item[\hgxopt{mq}{qnew}{-m}] Use the given text as the commit message.
-  This text will be stored at the beginning of the patch file, before
-  the patch data.
-\end{itemize}
-
-\subsection{\hgxcmd{mq}{qnext}---print the name of the next patch}
-
-The \hgxcmd{mq}{qnext} command prints the name name of the next patch in
-the \sfilename{series} file after the topmost applied patch.  This
-patch will become the topmost applied patch if you run \hgxcmd{mq}{qpush}.
-
-\subsection{\hgxcmd{mq}{qpop}---pop patches off the stack}
-
-The \hgxcmd{mq}{qpop} command removes applied patches from the top of the
-stack of applied patches.  By default, it removes only one patch.
-
-This command removes the changesets that represent the popped patches
-from the repository, and updates the working directory to undo the
-effects of the patches.
-
-This command takes an optional argument, which it uses as the name or
-index of the patch to pop to.  If given a name, it will pop patches
-until the named patch is the topmost applied patch.  If given a
-number, \hgxcmd{mq}{qpop} treats the number as an index into the entries in
-the series file, counting from zero (empty lines and lines containing
-only comments do not count).  It pops patches until the patch
-identified by the given index is the topmost applied patch.
-
-The \hgxcmd{mq}{qpop} command does not read or write patches or the
-\sfilename{series} file.  It is thus safe to \hgxcmd{mq}{qpop} a patch that
-you have removed from the \sfilename{series} file, or a patch that you
-have renamed or deleted entirely.  In the latter two cases, use the
-name of the patch as it was when you applied it.
-
-By default, the \hgxcmd{mq}{qpop} command will not pop any patches if the
-working directory has been modified.  You can override this behaviour
-using the \hgxopt{mq}{qpop}{-f} option, which reverts all modifications in
-the working directory.
-
-Options:
-\begin{itemize}
-\item[\hgxopt{mq}{qpop}{-a}] Pop all applied patches.  This returns the
-  repository to its state before you applied any patches.
-\item[\hgxopt{mq}{qpop}{-f}] Forcibly revert any modifications to the
-  working directory when popping.
-\item[\hgxopt{mq}{qpop}{-n}] Pop a patch from the named queue.
-\end{itemize}
-
-The \hgxcmd{mq}{qpop} command removes one line from the end of the
-\sfilename{status} file for each patch that it pops.
-
-\subsection{\hgxcmd{mq}{qprev}---print the name of the previous patch}
-
-The \hgxcmd{mq}{qprev} command prints the name of the patch in the
-\sfilename{series} file that comes before the topmost applied patch.
-This will become the topmost applied patch if you run \hgxcmd{mq}{qpop}.
-
-\subsection{\hgxcmd{mq}{qpush}---push patches onto the stack}
-\label{sec:mqref:cmd:qpush}
-
-The \hgxcmd{mq}{qpush} command adds patches onto the applied stack.  By
-default, it adds only one patch.
-
-This command creates a new changeset to represent each applied patch,
-and updates the working directory to apply the effects of the patches.
-
-The default data used when creating a changeset are as follows:
-\begin{itemize}
-\item The commit date and time zone are the current date and time
-  zone.  Because these data are used to compute the identity of a
-  changeset, this means that if you \hgxcmd{mq}{qpop} a patch and
-  \hgxcmd{mq}{qpush} it again, the changeset that you push will have a
-  different identity than the changeset you popped.
-\item The author is the same as the default used by the \hgcmd{commit}
-  command.
-\item The commit message is any text from the patch file that comes
-  before the first diff header.  If there is no such text, a default
-  commit message is used that identifies the name of the patch.
-\end{itemize}
-If a patch contains a Mercurial patch header (XXX add link), the
-information in the patch header overrides these defaults.
-
-Options:
-\begin{itemize}
-\item[\hgxopt{mq}{qpush}{-a}] Push all unapplied patches from the
-  \sfilename{series} file until there are none left to push.
-\item[\hgxopt{mq}{qpush}{-l}] Add the name of the patch to the end
-  of the commit message.
-\item[\hgxopt{mq}{qpush}{-m}] If a patch fails to apply cleanly, use the
-  entry for the patch in another saved queue to compute the parameters
-  for a three-way merge, and perform a three-way merge using the
-  normal Mercurial merge machinery.  Use the resolution of the merge
-  as the new patch content.
-\item[\hgxopt{mq}{qpush}{-n}] Use the named queue if merging while pushing.
-\end{itemize}
-
-The \hgxcmd{mq}{qpush} command reads, but does not modify, the
-\sfilename{series} file.  It appends one line to the \hgcmd{status}
-file for each patch that it pushes.
-
-\subsection{\hgxcmd{mq}{qrefresh}---update the topmost applied patch}
-
-The \hgxcmd{mq}{qrefresh} command updates the topmost applied patch.  It
-modifies the patch, removes the old changeset that represented the
-patch, and creates a new changeset to represent the modified patch.
-
-The \hgxcmd{mq}{qrefresh} command looks for the following modifications:
-\begin{itemize}
-\item Changes to the commit message, i.e.~the text before the first
-  diff header in the patch file, are reflected in the new changeset
-  that represents the patch.
-\item Modifications to tracked files in the working directory are
-  added to the patch.
-\item Changes to the files tracked using \hgcmd{add}, \hgcmd{copy},
-  \hgcmd{remove}, or \hgcmd{rename}.  Added files and copy and rename
-  destinations are added to the patch, while removed files and rename
-  sources are removed.
-\end{itemize}
-
-Even if \hgxcmd{mq}{qrefresh} detects no changes, it still recreates the
-changeset that represents the patch.  This causes the identity of the
-changeset to differ from the previous changeset that identified the
-patch.
-
-Options:
-\begin{itemize}
-\item[\hgxopt{mq}{qrefresh}{-e}] Modify the commit and patch description,
-  using the preferred text editor.
-\item[\hgxopt{mq}{qrefresh}{-m}] Modify the commit message and patch
-  description, using the given text.
-\item[\hgxopt{mq}{qrefresh}{-l}] Modify the commit message and patch
-  description, using text from the given file.
-\end{itemize}
-
-\subsection{\hgxcmd{mq}{qrename}---rename a patch}
-
-The \hgxcmd{mq}{qrename} command renames a patch, and changes the entry for
-the patch in the \sfilename{series} file.
-
-With a single argument, \hgxcmd{mq}{qrename} renames the topmost applied
-patch.  With two arguments, it renames its first argument to its
-second.
-
-\subsection{\hgxcmd{mq}{qrestore}---restore saved queue state}
-
-XXX No idea what this does.
-
-\subsection{\hgxcmd{mq}{qsave}---save current queue state}
-
-XXX Likewise.
-
-\subsection{\hgxcmd{mq}{qseries}---print the entire patch series}
-
-The \hgxcmd{mq}{qseries} command prints the entire patch series from the
-\sfilename{series} file.  It prints only patch names, not empty lines
-or comments.  It prints in order from first to be applied to last.
-
-\subsection{\hgxcmd{mq}{qtop}---print the name of the current patch}
-
-The \hgxcmd{mq}{qtop} prints the name of the topmost currently applied
-patch.
-
-\subsection{\hgxcmd{mq}{qunapplied}---print patches not yet applied}
-
-The \hgxcmd{mq}{qunapplied} command prints the names of patches from the
-\sfilename{series} file that are not yet applied.  It prints them in
-order from the next patch that will be pushed to the last.
-
-\subsection{\hgcmd{strip}---remove a revision and descendants}
-
-The \hgcmd{strip} command removes a revision, and all of its
-descendants, from the repository.  It undoes the effects of the
-removed revisions from the repository, and updates the working
-directory to the first parent of the removed revision.
-
-The \hgcmd{strip} command saves a backup of the removed changesets in
-a bundle, so that they can be reapplied if removed in error.
-
-Options:
-\begin{itemize}
-\item[\hgopt{strip}{-b}] Save unrelated changesets that are intermixed
-  with the stripped changesets in the backup bundle.
-\item[\hgopt{strip}{-f}] If a branch has multiple heads, remove all
-  heads. XXX This should be renamed, and use \texttt{-f} to strip revs
-  when there are pending changes.
-\item[\hgopt{strip}{-n}] Do not save a backup bundle.
-\end{itemize}
-
-\section{MQ file reference}
-
-\subsection{The \sfilename{series} file}
-
-The \sfilename{series} file contains a list of the names of all
-patches that MQ can apply.  It is represented as a list of names, with
-one name saved per line.  Leading and trailing white space in each
-line are ignored.
-
-Lines may contain comments.  A comment begins with the ``\texttt{\#}''
-character, and extends to the end of the line.  Empty lines, and lines
-that contain only comments, are ignored.
-
-You will often need to edit the \sfilename{series} file by hand, hence
-the support for comments and empty lines noted above.  For example,
-you can comment out a patch temporarily, and \hgxcmd{mq}{qpush} will skip
-over that patch when applying patches.  You can also change the order
-in which patches are applied by reordering their entries in the
-\sfilename{series} file.
-
-Placing the \sfilename{series} file under revision control is also
-supported; it is a good idea to place all of the patches that it
-refers to under revision control, as well.  If you create a patch
-directory using the \hgxopt{mq}{qinit}{-c} option to \hgxcmd{mq}{qinit}, this
-will be done for you automatically.
-
-\subsection{The \sfilename{status} file}
-
-The \sfilename{status} file contains the names and changeset hashes of
-all patches that MQ currently has applied.  Unlike the
-\sfilename{series} file, this file is not intended for editing.  You
-should not place this file under revision control, or modify it in any
-way.  It is used by MQ strictly for internal book-keeping.
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/mq.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1043 +0,0 @@
-\chapter{Managing change with Mercurial Queues}
-\label{chap:mq}
-
-\section{The patch management problem}
-\label{sec:mq:patch-mgmt}
-
-Here is a common scenario: you need to install a software package from
-source, but you find a bug that you must fix in the source before you
-can start using the package.  You make your changes, forget about the
-package for a while, and a few months later you need to upgrade to a
-newer version of the package.  If the newer version of the package
-still has the bug, you must extract your fix from the older source
-tree and apply it against the newer version.  This is a tedious task,
-and it's easy to make mistakes.
-
-This is a simple case of the ``patch management'' problem.  You have
-an ``upstream'' source tree that you can't change; you need to make
-some local changes on top of the upstream tree; and you'd like to be
-able to keep those changes separate, so that you can apply them to
-newer versions of the upstream source.
-
-The patch management problem arises in many situations.  Probably the
-most visible is that a user of an open source software project will
-contribute a bug fix or new feature to the project's maintainers in the
-form of a patch.
-
-Distributors of operating systems that include open source software
-often need to make changes to the packages they distribute so that
-they will build properly in their environments.
-
-When you have few changes to maintain, it is easy to manage a single
-patch using the standard \command{diff} and \command{patch} programs
-(see section~\ref{sec:mq:patch} for a discussion of these tools).
-Once the number of changes grows, it starts to make sense to maintain
-patches as discrete ``chunks of work,'' so that for example a single
-patch will contain only one bug fix (the patch might modify several
-files, but it's doing ``only one thing''), and you may have a number
-of such patches for different bugs you need fixed and local changes
-you require.  In this situation, if you submit a bug fix patch to the
-upstream maintainers of a package and they include your fix in a
-subsequent release, you can simply drop that single patch when you're
-updating to the newer release.
-
-Maintaining a single patch against an upstream tree is a little
-tedious and error-prone, but not difficult.  However, the complexity
-of the problem grows rapidly as the number of patches you have to
-maintain increases.  With more than a tiny number of patches in hand,
-understanding which ones you have applied and maintaining them moves
-from messy to overwhelming.
-
-Fortunately, Mercurial includes a powerful extension, Mercurial Queues
-(or simply ``MQ''), that massively simplifies the patch management
-problem.
-
-\section{The prehistory of Mercurial Queues}
-\label{sec:mq:history}
-
-During the late 1990s, several Linux kernel developers started to
-maintain ``patch series'' that modified the behaviour of the Linux
-kernel.  Some of these series were focused on stability, some on
-feature coverage, and others were more speculative.
-
-The sizes of these patch series grew rapidly.  In 2002, Andrew Morton
-published some shell scripts he had been using to automate the task of
-managing his patch queues.  Andrew was successfully using these
-scripts to manage hundreds (sometimes thousands) of patches on top of
-the Linux kernel.
-
-\subsection{A patchwork quilt}
-\label{sec:mq:quilt}
-
-In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the
-approach of Andrew's scripts and published a tool called ``patchwork
-quilt''~\cite{web:quilt}, or simply ``quilt''
-(see~\cite{gruenbacher:2005} for a paper describing it).  Because
-quilt substantially automated patch management, it rapidly gained a
-large following among open source software developers.
-
-Quilt manages a \emph{stack of patches} on top of a directory tree.
-To begin, you tell quilt to manage a directory tree, and tell it which
-files you want to manage; it stores away the names and contents of
-those files.  To fix a bug, you create a new patch (using a single
-command), edit the files you need to fix, then ``refresh'' the patch.
-
-The refresh step causes quilt to scan the directory tree; it updates
-the patch with all of the changes you have made.  You can create
-another patch on top of the first, which will track the changes
-required to modify the tree from ``tree with one patch applied'' to
-``tree with two patches applied''.
-
-You can \emph{change} which patches are applied to the tree.  If you
-``pop'' a patch, the changes made by that patch will vanish from the
-directory tree.  Quilt remembers which patches you have popped,
-though, so you can ``push'' a popped patch again, and the directory
-tree will be restored to contain the modifications in the patch.  Most
-importantly, you can run the ``refresh'' command at any time, and the
-topmost applied patch will be updated.  This means that you can, at
-any time, change both which patches are applied and what
-modifications those patches make.
-
-Quilt knows nothing about revision control tools, so it works equally
-well on top of an unpacked tarball or a Subversion working copy.
-
-\subsection{From patchwork quilt to Mercurial Queues}
-\label{sec:mq:quilt-mq}
-
-In mid-2005, Chris Mason took the features of quilt and wrote an
-extension that he called Mercurial Queues, which added quilt-like
-behaviour to Mercurial.
-
-The key difference between quilt and MQ is that quilt knows nothing
-about revision control systems, while MQ is \emph{integrated} into
-Mercurial.  Each patch that you push is represented as a Mercurial
-changeset.  Pop a patch, and the changeset goes away.
-
-Because quilt does not care about revision control tools, it is still
-a tremendously useful piece of software to know about for situations
-where you cannot use Mercurial and MQ.
-
-\section{The huge advantage of MQ}
-
-I cannot overstate the value that MQ offers through the unification of
-patches and revision control.
-
-A major reason that patches have persisted in the free software and
-open source world---in spite of the availability of increasingly
-capable revision control tools over the years---is the \emph{agility}
-they offer.  
-
-Traditional revision control tools make a permanent, irreversible
-record of everything that you do.  While this has great value, it's
-also somewhat stifling.  If you want to perform a wild-eyed
-experiment, you have to be careful in how you go about it, or you risk
-leaving unneeded---or worse, misleading or destabilising---traces of
-your missteps and errors in the permanent revision record.
-
-By contrast, MQ's marriage of distributed revision control with
-patches makes it much easier to isolate your work.  Your patches live
-on top of normal revision history, and you can make them disappear or
-reappear at will.  If you don't like a patch, you can drop it.  If a
-patch isn't quite as you want it to be, simply fix it---as many times
-as you need to, until you have refined it into the form you desire.
-
-As an example, the integration of patches with revision control makes
-understanding patches and debugging their effects---and their
-interplay with the code they're based on---\emph{enormously} easier.
-Since every applied patch has an associated changeset, you can use
-\hgcmdargs{log}{\emph{filename}} to see which changesets and patches
-affected a file.  You can use the \hgext{bisect} command to
-binary-search through all changesets and applied patches to see where
-a bug got introduced or fixed.  You can use the \hgcmd{annotate}
-command to see which changeset or patch modified a particular line of
-a source file.  And so on.
-
-\section{Understanding patches}
-\label{sec:mq:patch}
-
-Because MQ doesn't hide its patch-oriented nature, it is helpful to
-understand what patches are, and a little about the tools that work
-with them.
-
-The traditional Unix \command{diff} command compares two files, and
-prints a list of differences between them. The \command{patch} command
-understands these differences as \emph{modifications} to make to a
-file.  Take a look at figure~\ref{ex:mq:diff} for a simple example of
-these commands in action.
-
-\begin{figure}[ht]
-  \interaction{mq.dodiff.diff}
-  \caption{Simple uses of the \command{diff} and \command{patch} commands}
-  \label{ex:mq:diff}
-\end{figure}
-
-The type of file that \command{diff} generates (and \command{patch}
-takes as input) is called a ``patch'' or a ``diff''; there is no
-difference between a patch and a diff.  (We'll use the term ``patch'',
-since it's more commonly used.)
-
-A patch file can start with arbitrary text; the \command{patch}
-command ignores this text, but MQ uses it as the commit message when
-creating changesets.  To find the beginning of the patch content,
-\command{patch} searches for the first line that starts with the
-string ``\texttt{diff~-}''.
-
-MQ works with \emph{unified} diffs (\command{patch} can accept several
-other diff formats, but MQ doesn't).  A unified diff contains two
-kinds of header.  The \emph{file header} describes the file being
-modified; it contains the name of the file to modify.  When
-\command{patch} sees a new file header, it looks for a file with that
-name to start modifying.
-
-After the file header comes a series of \emph{hunks}.  Each hunk
-starts with a header; this identifies the range of line numbers within
-the file that the hunk should modify.  Following the header, a hunk
-starts and ends with a few (usually three) lines of text from the
-unmodified file; these are called the \emph{context} for the hunk.  If
-there's only a small amount of context between successive hunks,
-\command{diff} doesn't print a new hunk header; it just runs the hunks
-together, with a few lines of context between modifications.
-
-Each line of context begins with a space character.  Within the hunk,
-a line that begins with ``\texttt{-}'' means ``remove this line,''
-while a line that begins with ``\texttt{+}'' means ``insert this
-line.''  For example, a line that is modified is represented by one
-deletion and one insertion.
-
-We will return to some of the more subtle aspects of patches later (in
-section~\ref{sec:mq:adv-patch}), but you should have enough information
-now to use MQ.
-
-\section{Getting started with Mercurial Queues}
-\label{sec:mq:start}
-
-Because MQ is implemented as an extension, you must explicitly enable
-before you can use it.  (You don't need to download anything; MQ ships
-with the standard Mercurial distribution.)  To enable MQ, edit your
-\tildefile{.hgrc} file, and add the lines in figure~\ref{ex:mq:config}.
-
-\begin{figure}[ht]
-  \begin{codesample4}
-    [extensions]
-    hgext.mq =
-  \end{codesample4}
-  \label{ex:mq:config}
-  \caption{Contents to add to \tildefile{.hgrc} to enable the MQ extension}
-\end{figure}
-
-Once the extension is enabled, it will make a number of new commands
-available.  To verify that the extension is working, you can use
-\hgcmd{help} to see if the \hgxcmd{mq}{qinit} command is now available; see
-the example in figure~\ref{ex:mq:enabled}.
-
-\begin{figure}[ht]
-  \interaction{mq.qinit-help.help}
-  \caption{How to verify that MQ is enabled}
-  \label{ex:mq:enabled}
-\end{figure}
-
-You can use MQ with \emph{any} Mercurial repository, and its commands
-only operate within that repository.  To get started, simply prepare
-the repository using the \hgxcmd{mq}{qinit} command (see
-figure~\ref{ex:mq:qinit}).  This command creates an empty directory
-called \sdirname{.hg/patches}, where MQ will keep its metadata.  As
-with many Mercurial commands, the \hgxcmd{mq}{qinit} command prints nothing
-if it succeeds.
-
-\begin{figure}[ht]
-  \interaction{mq.tutorial.qinit}
-  \caption{Preparing a repository for use with MQ}
-  \label{ex:mq:qinit}
-\end{figure}
-
-\begin{figure}[ht]
-  \interaction{mq.tutorial.qnew}
-  \caption{Creating a new patch}
-  \label{ex:mq:qnew}
-\end{figure}
-
-\subsection{Creating a new patch}
-
-To begin work on a new patch, use the \hgxcmd{mq}{qnew} command.  This
-command takes one argument, the name of the patch to create.  MQ will
-use this as the name of an actual file in the \sdirname{.hg/patches}
-directory, as you can see in figure~\ref{ex:mq:qnew}.
-
-Also newly present in the \sdirname{.hg/patches} directory are two
-other files, \sfilename{series} and \sfilename{status}.  The
-\sfilename{series} file lists all of the patches that MQ knows about
-for this repository, with one patch per line.  Mercurial uses the
-\sfilename{status} file for internal book-keeping; it tracks all of the
-patches that MQ has \emph{applied} in this repository.
-
-\begin{note}
-  You may sometimes want to edit the \sfilename{series} file by hand;
-  for example, to change the sequence in which some patches are
-  applied.  However, manually editing the \sfilename{status} file is
-  almost always a bad idea, as it's easy to corrupt MQ's idea of what
-  is happening.
-\end{note}
-
-Once you have created your new patch, you can edit files in the
-working directory as you usually would.  All of the normal Mercurial
-commands, such as \hgcmd{diff} and \hgcmd{annotate}, work exactly as
-they did before.
-
-\subsection{Refreshing a patch}
-
-When you reach a point where you want to save your work, use the
-\hgxcmd{mq}{qrefresh} command (figure~\ref{ex:mq:qnew}) to update the patch
-you are working on.  This command folds the changes you have made in
-the working directory into your patch, and updates its corresponding
-changeset to contain those changes.
-
-\begin{figure}[ht]
-  \interaction{mq.tutorial.qrefresh}
-  \caption{Refreshing a patch}
-  \label{ex:mq:qrefresh}
-\end{figure}
-
-You can run \hgxcmd{mq}{qrefresh} as often as you like, so it's a good way
-to ``checkpoint'' your work.  Refresh your patch at an opportune
-time; try an experiment; and if the experiment doesn't work out,
-\hgcmd{revert} your modifications back to the last time you refreshed.
-
-\begin{figure}[ht]
-  \interaction{mq.tutorial.qrefresh2}
-  \caption{Refresh a patch many times to accumulate changes}
-  \label{ex:mq:qrefresh2}
-\end{figure}
-
-\subsection{Stacking and tracking patches}
-
-Once you have finished working on a patch, or need to work on another,
-you can use the \hgxcmd{mq}{qnew} command again to create a new patch.
-Mercurial will apply this patch on top of your existing patch.  See
-figure~\ref{ex:mq:qnew2} for an example.  Notice that the patch
-contains the changes in our prior patch as part of its context (you
-can see this more clearly in the output of \hgcmd{annotate}).
-
-\begin{figure}[ht]
-  \interaction{mq.tutorial.qnew2}
-  \caption{Stacking a second patch on top of the first}
-  \label{ex:mq:qnew2}
-\end{figure}
-
-So far, with the exception of \hgxcmd{mq}{qnew} and \hgxcmd{mq}{qrefresh}, we've
-been careful to only use regular Mercurial commands.  However, MQ
-provides many commands that are easier to use when you are thinking
-about patches, as illustrated in figure~\ref{ex:mq:qseries}:
-
-\begin{itemize}
-\item The \hgxcmd{mq}{qseries} command lists every patch that MQ knows
-  about in this repository, from oldest to newest (most recently
-  \emph{created}).
-\item The \hgxcmd{mq}{qapplied} command lists every patch that MQ has
-  \emph{applied} in this repository, again from oldest to newest (most
-  recently applied).
-\end{itemize}
-
-\begin{figure}[ht]
-  \interaction{mq.tutorial.qseries}
-  \caption{Understanding the patch stack with \hgxcmd{mq}{qseries} and
-    \hgxcmd{mq}{qapplied}}
-  \label{ex:mq:qseries}
-\end{figure}
-
-\subsection{Manipulating the patch stack}
-
-The previous discussion implied that there must be a difference
-between ``known'' and ``applied'' patches, and there is.  MQ can
-manage a patch without it being applied in the repository.
-
-An \emph{applied} patch has a corresponding changeset in the
-repository, and the effects of the patch and changeset are visible in
-the working directory.  You can undo the application of a patch using
-the \hgxcmd{mq}{qpop} command.  MQ still \emph{knows about}, or manages, a
-popped patch, but the patch no longer has a corresponding changeset in
-the repository, and the working directory does not contain the changes
-made by the patch.  Figure~\ref{fig:mq:stack} illustrates the
-difference between applied and tracked patches.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{mq-stack}
-  \caption{Applied and unapplied patches in the MQ patch stack}
-  \label{fig:mq:stack}
-\end{figure}
-
-You can reapply an unapplied, or popped, patch using the \hgxcmd{mq}{qpush}
-command.  This creates a new changeset to correspond to the patch, and
-the patch's changes once again become present in the working
-directory.  See figure~\ref{ex:mq:qpop} for examples of \hgxcmd{mq}{qpop}
-and \hgxcmd{mq}{qpush} in action.  Notice that once we have popped a patch
-or two patches, the output of \hgxcmd{mq}{qseries} remains the same, while
-that of \hgxcmd{mq}{qapplied} has changed.
-
-\begin{figure}[ht]
-  \interaction{mq.tutorial.qpop}
-  \caption{Modifying the stack of applied patches}
-  \label{ex:mq:qpop}
-\end{figure}
-
-\subsection{Pushing and popping many patches}
-
-While \hgxcmd{mq}{qpush} and \hgxcmd{mq}{qpop} each operate on a single patch at
-a time by default, you can push and pop many patches in one go.  The
-\hgxopt{mq}{qpush}{-a} option to \hgxcmd{mq}{qpush} causes it to push all
-unapplied patches, while the \hgxopt{mq}{qpop}{-a} option to \hgxcmd{mq}{qpop}
-causes it to pop all applied patches.  (For some more ways to push and
-pop many patches, see section~\ref{sec:mq:perf} below.)
-
-\begin{figure}[ht]
-  \interaction{mq.tutorial.qpush-a}
-  \caption{Pushing all unapplied patches}
-  \label{ex:mq:qpush-a}
-\end{figure}
-
-\subsection{Safety checks, and overriding them}
-
-Several MQ commands check the working directory before they do
-anything, and fail if they find any modifications.  They do this to
-ensure that you won't lose any changes that you have made, but not yet
-incorporated into a patch.  Figure~\ref{ex:mq:add} illustrates this;
-the \hgxcmd{mq}{qnew} command will not create a new patch if there are
-outstanding changes, caused in this case by the \hgcmd{add} of
-\filename{file3}.
-
-\begin{figure}[ht]
-  \interaction{mq.tutorial.add}
-  \caption{Forcibly creating a patch}
-  \label{ex:mq:add}
-\end{figure}
-
-Commands that check the working directory all take an ``I know what
-I'm doing'' option, which is always named \option{-f}.  The exact
-meaning of \option{-f} depends on the command.  For example,
-\hgcmdargs{qnew}{\hgxopt{mq}{qnew}{-f}} will incorporate any outstanding
-changes into the new patch it creates, but
-\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-f}} will revert modifications to any
-files affected by the patch that it is popping.  Be sure to read the
-documentation for a command's \option{-f} option before you use it!
-
-\subsection{Working on several patches at once}
-
-The \hgxcmd{mq}{qrefresh} command always refreshes the \emph{topmost}
-applied patch.  This means that you can suspend work on one patch (by
-refreshing it), pop or push to make a different patch the top, and
-work on \emph{that} patch for a while.
-
-Here's an example that illustrates how you can use this ability.
-Let's say you're developing a new feature as two patches.  The first
-is a change to the core of your software, and the second---layered on
-top of the first---changes the user interface to use the code you just
-added to the core.  If you notice a bug in the core while you're
-working on the UI patch, it's easy to fix the core.  Simply
-\hgxcmd{mq}{qrefresh} the UI patch to save your in-progress changes, and
-\hgxcmd{mq}{qpop} down to the core patch.  Fix the core bug,
-\hgxcmd{mq}{qrefresh} the core patch, and \hgxcmd{mq}{qpush} back to the UI
-patch to continue where you left off.
-
-\section{More about patches}
-\label{sec:mq:adv-patch}
-
-MQ uses the GNU \command{patch} command to apply patches, so it's
-helpful to know a few more detailed aspects of how \command{patch}
-works, and about patches themselves.
-
-\subsection{The strip count}
-
-If you look at the file headers in a patch, you will notice that the
-pathnames usually have an extra component on the front that isn't
-present in the actual path name.  This is a holdover from the way that
-people used to generate patches (people still do this, but it's
-somewhat rare with modern revision control tools).  
-
-Alice would unpack a tarball, edit her files, then decide that she
-wanted to create a patch.  So she'd rename her working directory,
-unpack the tarball again (hence the need for the rename), and use the
-\cmdopt{diff}{-r} and \cmdopt{diff}{-N} options to \command{diff} to
-recursively generate a patch between the unmodified directory and the
-modified one.  The result would be that the name of the unmodified
-directory would be at the front of the left-hand path in every file
-header, and the name of the modified directory would be at the front
-of the right-hand path.
-
-Since someone receiving a patch from the Alices of the net would be
-unlikely to have unmodified and modified directories with exactly the
-same names, the \command{patch} command has a \cmdopt{patch}{-p}
-option that indicates the number of leading path name components to
-strip when trying to apply a patch.  This number is called the
-\emph{strip count}.
-
-An option of ``\texttt{-p1}'' means ``use a strip count of one''.  If
-\command{patch} sees a file name \filename{foo/bar/baz} in a file
-header, it will strip \filename{foo} and try to patch a file named
-\filename{bar/baz}.  (Strictly speaking, the strip count refers to the
-number of \emph{path separators} (and the components that go with them
-) to strip.  A strip count of one will turn \filename{foo/bar} into
-\filename{bar}, but \filename{/foo/bar} (notice the extra leading
-slash) into \filename{foo/bar}.)
-
-The ``standard'' strip count for patches is one; almost all patches
-contain one leading path name component that needs to be stripped.
-Mercurial's \hgcmd{diff} command generates path names in this form,
-and the \hgcmd{import} command and MQ expect patches to have a strip
-count of one.
-
-If you receive a patch from someone that you want to add to your patch
-queue, and the patch needs a strip count other than one, you cannot
-just \hgxcmd{mq}{qimport} the patch, because \hgxcmd{mq}{qimport} does not yet
-have a \texttt{-p} option (see~\bug{311}).  Your best bet is to
-\hgxcmd{mq}{qnew} a patch of your own, then use \cmdargs{patch}{-p\emph{N}}
-to apply their patch, followed by \hgcmd{addremove} to pick up any
-files added or removed by the patch, followed by \hgxcmd{mq}{qrefresh}.
-This complexity may become unnecessary; see~\bug{311} for details.
-\subsection{Strategies for applying a patch}
-
-When \command{patch} applies a hunk, it tries a handful of
-successively less accurate strategies to try to make the hunk apply.
-This falling-back technique often makes it possible to take a patch
-that was generated against an old version of a file, and apply it
-against a newer version of that file.
-
-First, \command{patch} tries an exact match, where the line numbers,
-the context, and the text to be modified must apply exactly.  If it
-cannot make an exact match, it tries to find an exact match for the
-context, without honouring the line numbering information.  If this
-succeeds, it prints a line of output saying that the hunk was applied,
-but at some \emph{offset} from the original line number.
-
-If a context-only match fails, \command{patch} removes the first and
-last lines of the context, and tries a \emph{reduced} context-only
-match.  If the hunk with reduced context succeeds, it prints a message
-saying that it applied the hunk with a \emph{fuzz factor} (the number
-after the fuzz factor indicates how many lines of context
-\command{patch} had to trim before the patch applied).
-
-When neither of these techniques works, \command{patch} prints a
-message saying that the hunk in question was rejected.  It saves
-rejected hunks (also simply called ``rejects'') to a file with the
-same name, and an added \sfilename{.rej} extension.  It also saves an
-unmodified copy of the file with a \sfilename{.orig} extension; the
-copy of the file without any extensions will contain any changes made
-by hunks that \emph{did} apply cleanly.  If you have a patch that
-modifies \filename{foo} with six hunks, and one of them fails to
-apply, you will have: an unmodified \filename{foo.orig}, a
-\filename{foo.rej} containing one hunk, and \filename{foo}, containing
-the changes made by the five successful hunks.
-
-\subsection{Some quirks of patch representation}
-
-There are a few useful things to know about how \command{patch} works
-with files.
-\begin{itemize}
-\item This should already be obvious, but \command{patch} cannot
-  handle binary files.
-\item Neither does it care about the executable bit; it creates new
-  files as readable, but not executable.
-\item \command{patch} treats the removal of a file as a diff between
-  the file to be removed and the empty file.  So your idea of ``I
-  deleted this file'' looks like ``every line of this file was
-  deleted'' in a patch.
-\item It treats the addition of a file as a diff between the empty
-  file and the file to be added.  So in a patch, your idea of ``I
-  added this file'' looks like ``every line of this file was added''.
-\item It treats a renamed file as the removal of the old name, and the
-  addition of the new name.  This means that renamed files have a big
-  footprint in patches.  (Note also that Mercurial does not currently
-  try to infer when files have been renamed or copied in a patch.)
-\item \command{patch} cannot represent empty files, so you cannot use
-  a patch to represent the notion ``I added this empty file to the
-  tree''.
-\end{itemize}
-\subsection{Beware the fuzz}
-
-While applying a hunk at an offset, or with a fuzz factor, will often
-be completely successful, these inexact techniques naturally leave
-open the possibility of corrupting the patched file.  The most common
-cases typically involve applying a patch twice, or at an incorrect
-location in the file.  If \command{patch} or \hgxcmd{mq}{qpush} ever
-mentions an offset or fuzz factor, you should make sure that the
-modified files are correct afterwards.  
-
-It's often a good idea to refresh a patch that has applied with an
-offset or fuzz factor; refreshing the patch generates new context
-information that will make it apply cleanly.  I say ``often,'' not
-``always,'' because sometimes refreshing a patch will make it fail to
-apply against a different revision of the underlying files.  In some
-cases, such as when you're maintaining a patch that must sit on top of
-multiple versions of a source tree, it's acceptable to have a patch
-apply with some fuzz, provided you've verified the results of the
-patching process in such cases.
-
-\subsection{Handling rejection}
-
-If \hgxcmd{mq}{qpush} fails to apply a patch, it will print an error
-message and exit.  If it has left \sfilename{.rej} files behind, it is
-usually best to fix up the rejected hunks before you push more patches
-or do any further work.
-
-If your patch \emph{used to} apply cleanly, and no longer does because
-you've changed the underlying code that your patches are based on,
-Mercurial Queues can help; see section~\ref{sec:mq:merge} for details.
-
-Unfortunately, there aren't any great techniques for dealing with
-rejected hunks.  Most often, you'll need to view the \sfilename{.rej}
-file and edit the target file, applying the rejected hunks by hand.
-
-If you're feeling adventurous, Neil Brown, a Linux kernel hacker,
-wrote a tool called \command{wiggle}~\cite{web:wiggle}, which is more
-vigorous than \command{patch} in its attempts to make a patch apply.
-
-Another Linux kernel hacker, Chris Mason (the author of Mercurial
-Queues), wrote a similar tool called
-\command{mpatch}~\cite{web:mpatch}, which takes a simple approach to
-automating the application of hunks rejected by \command{patch}.  The
-\command{mpatch} command can help with four common reasons that a hunk
-may be rejected:
-
-\begin{itemize}
-\item The context in the middle of a hunk has changed.
-\item A hunk is missing some context at the beginning or end.
-\item A large hunk might apply better---either entirely or in
-  part---if it was broken up into smaller hunks.
-\item A hunk removes lines with slightly different content than those
-  currently present in the file.
-\end{itemize}
-
-If you use \command{wiggle} or \command{mpatch}, you should be doubly
-careful to check your results when you're done.  In fact,
-\command{mpatch} enforces this method of double-checking the tool's
-output, by automatically dropping you into a merge program when it has
-done its job, so that you can verify its work and finish off any
-remaining merges.
-
-\section{Getting the best performance out of MQ}
-\label{sec:mq:perf}
-
-MQ is very efficient at handling a large number of patches.  I ran
-some performance experiments in mid-2006 for a talk that I gave at the
-2006 EuroPython conference~\cite{web:europython}.  I used as my data
-set the Linux 2.6.17-mm1 patch series, which consists of 1,738
-patches.  I applied these on top of a Linux kernel repository
-containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux
-2.6.17.
-
-On my old, slow laptop, I was able to
-\hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} all 1,738 patches in 3.5 minutes,
-and \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} them all in 30 seconds.  (On a
-newer laptop, the time to push all patches dropped to two minutes.)  I
-could \hgxcmd{mq}{qrefresh} one of the biggest patches (which made 22,779
-lines of changes to 287 files) in 6.6 seconds.
-
-Clearly, MQ is well suited to working in large trees, but there are a
-few tricks you can use to get the best performance of it.
-
-First of all, try to ``batch'' operations together.  Every time you
-run \hgxcmd{mq}{qpush} or \hgxcmd{mq}{qpop}, these commands scan the working
-directory once to make sure you haven't made some changes and then
-forgotten to run \hgxcmd{mq}{qrefresh}.  On a small tree, the time that
-this scan takes is unnoticeable.  However, on a medium-sized tree
-(containing tens of thousands of files), it can take a second or more.
-
-The \hgxcmd{mq}{qpush} and \hgxcmd{mq}{qpop} commands allow you to push and pop
-multiple patches at a time.  You can identify the ``destination
-patch'' that you want to end up at.  When you \hgxcmd{mq}{qpush} with a
-destination specified, it will push patches until that patch is at the
-top of the applied stack.  When you \hgxcmd{mq}{qpop} to a destination, MQ
-will pop patches until the destination patch is at the top.
-
-You can identify a destination patch using either the name of the
-patch, or by number.  If you use numeric addressing, patches are
-counted from zero; this means that the first patch is zero, the second
-is one, and so on.
-
-\section{Updating your patches when the underlying code changes}
-\label{sec:mq:merge}
-
-It's common to have a stack of patches on top of an underlying
-repository that you don't modify directly.  If you're working on
-changes to third-party code, or on a feature that is taking longer to
-develop than the rate of change of the code beneath, you will often
-need to sync up with the underlying code, and fix up any hunks in your
-patches that no longer apply.  This is called \emph{rebasing} your
-patch series.
-
-The simplest way to do this is to \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}}
-your patches, then \hgcmd{pull} changes into the underlying
-repository, and finally \hgcmdargs{qpush}{\hgxopt{mq}{qpop}{-a}} your
-patches again.  MQ will stop pushing any time it runs across a patch
-that fails to apply during conflicts, allowing you to fix your
-conflicts, \hgxcmd{mq}{qrefresh} the affected patch, and continue pushing
-until you have fixed your entire stack.
-
-This approach is easy to use and works well if you don't expect
-changes to the underlying code to affect how well your patches apply.
-If your patch stack touches code that is modified frequently or
-invasively in the underlying repository, however, fixing up rejected
-hunks by hand quickly becomes tiresome.
-
-It's possible to partially automate the rebasing process.  If your
-patches apply cleanly against some revision of the underlying repo, MQ
-can use this information to help you to resolve conflicts between your
-patches and a different revision.
-
-The process is a little involved.
-\begin{enumerate}
-\item To begin, \hgcmdargs{qpush}{-a} all of your patches on top of
-  the revision where you know that they apply cleanly.
-\item Save a backup copy of your patch directory using
-  \hgcmdargs{qsave}{\hgxopt{mq}{qsave}{-e} \hgxopt{mq}{qsave}{-c}}.  This prints
-  the name of the directory that it has saved the patches in.  It will
-  save the patches to a directory called
-  \sdirname{.hg/patches.\emph{N}}, where \texttt{\emph{N}} is a small
-  integer.  It also commits a ``save changeset'' on top of your
-  applied patches; this is for internal book-keeping, and records the
-  states of the \sfilename{series} and \sfilename{status} files.
-\item Use \hgcmd{pull} to bring new changes into the underlying
-  repository.  (Don't run \hgcmdargs{pull}{-u}; see below for why.)
-\item Update to the new tip revision, using
-  \hgcmdargs{update}{\hgopt{update}{-C}} to override the patches you
-  have pushed.
-\item Merge all patches using \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}
-    \hgxopt{mq}{qpush}{-a}}.  The \hgxopt{mq}{qpush}{-m} option to \hgxcmd{mq}{qpush}
-  tells MQ to perform a three-way merge if the patch fails to apply.
-\end{enumerate}
-
-During the \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}}, each patch in the
-\sfilename{series} file is applied normally.  If a patch applies with
-fuzz or rejects, MQ looks at the queue you \hgxcmd{mq}{qsave}d, and
-performs a three-way merge with the corresponding changeset.  This
-merge uses Mercurial's normal merge machinery, so it may pop up a GUI
-merge tool to help you to resolve problems.
-
-When you finish resolving the effects of a patch, MQ refreshes your
-patch based on the result of the merge.
-
-At the end of this process, your repository will have one extra head
-from the old patch queue, and a copy of the old patch queue will be in
-\sdirname{.hg/patches.\emph{N}}. You can remove the extra head using
-\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a} \hgxopt{mq}{qpop}{-n} patches.\emph{N}}
-or \hgcmd{strip}.  You can delete \sdirname{.hg/patches.\emph{N}} once
-you are sure that you no longer need it as a backup.
-
-\section{Identifying patches}
-
-MQ commands that work with patches let you refer to a patch either by
-using its name or by a number.  By name is obvious enough; pass the
-name \filename{foo.patch} to \hgxcmd{mq}{qpush}, for example, and it will
-push patches until \filename{foo.patch} is applied.  
-
-As a shortcut, you can refer to a patch using both a name and a
-numeric offset; \texttt{foo.patch-2} means ``two patches before
-\texttt{foo.patch}'', while \texttt{bar.patch+4} means ``four patches
-after \texttt{bar.patch}''.
-
-Referring to a patch by index isn't much different.  The first patch
-printed in the output of \hgxcmd{mq}{qseries} is patch zero (yes, it's one
-of those start-at-zero counting systems); the second is patch one; and
-so on.
-
-MQ also makes it easy to work with patches when you are using normal
-Mercurial commands.  Every command that accepts a changeset ID will
-also accept the name of an applied patch.  MQ augments the tags
-normally in the repository with an eponymous one for each applied
-patch.  In addition, the special tags \index{tags!special tag
-  names!\texttt{qbase}}\texttt{qbase} and \index{tags!special tag
-  names!\texttt{qtip}}\texttt{qtip} identify the ``bottom-most'' and
-topmost applied patches, respectively.
-
-These additions to Mercurial's normal tagging capabilities make
-dealing with patches even more of a breeze.
-\begin{itemize}
-\item Want to patchbomb a mailing list with your latest series of
-  changes?
-  \begin{codesample4}
-    hg email qbase:qtip
-  \end{codesample4}
-  (Don't know what ``patchbombing'' is?  See
-  section~\ref{sec:hgext:patchbomb}.)
-\item Need to see all of the patches since \texttt{foo.patch} that
-  have touched files in a subdirectory of your tree?
-  \begin{codesample4}
-    hg log -r foo.patch:qtip \emph{subdir}
-  \end{codesample4}
-\end{itemize}
-
-Because MQ makes the names of patches available to the rest of
-Mercurial through its normal internal tag machinery, you don't need to
-type in the entire name of a patch when you want to identify it by
-name.
-
-\begin{figure}[ht]
-  \interaction{mq.id.output}
-  \caption{Using MQ's tag features to work with patches}
-  \label{ex:mq:id}
-\end{figure}
-
-Another nice consequence of representing patch names as tags is that
-when you run the \hgcmd{log} command, it will display a patch's name
-as a tag, simply as part of its normal output.  This makes it easy to
-visually distinguish applied patches from underlying ``normal''
-revisions.  Figure~\ref{ex:mq:id} shows a few normal Mercurial
-commands in use with applied patches.
-
-\section{Useful things to know about}
-
-There are a number of aspects of MQ usage that don't fit tidily into
-sections of their own, but that are good to know.  Here they are, in
-one place.
-
-\begin{itemize}
-\item Normally, when you \hgxcmd{mq}{qpop} a patch and \hgxcmd{mq}{qpush} it
-  again, the changeset that represents the patch after the pop/push
-  will have a \emph{different identity} than the changeset that
-  represented the hash beforehand.  See
-  section~\ref{sec:mqref:cmd:qpush} for information as to why this is.
-\item It's not a good idea to \hgcmd{merge} changes from another
-  branch with a patch changeset, at least if you want to maintain the
-  ``patchiness'' of that changeset and changesets below it on the
-  patch stack.  If you try to do this, it will appear to succeed, but
-  MQ will become confused.
-\end{itemize}
-
-\section{Managing patches in a repository}
-\label{sec:mq:repo}
-
-Because MQ's \sdirname{.hg/patches} directory resides outside a
-Mercurial repository's working directory, the ``underlying'' Mercurial
-repository knows nothing about the management or presence of patches.
-
-This presents the interesting possibility of managing the contents of
-the patch directory as a Mercurial repository in its own right.  This
-can be a useful way to work.  For example, you can work on a patch for
-a while, \hgxcmd{mq}{qrefresh} it, then \hgcmd{commit} the current state of
-the patch.  This lets you ``roll back'' to that version of the patch
-later on.
-
-You can then share different versions of the same patch stack among
-multiple underlying repositories.  I use this when I am developing a
-Linux kernel feature.  I have a pristine copy of my kernel sources for
-each of several CPU architectures, and a cloned repository under each
-that contains the patches I am working on.  When I want to test a
-change on a different architecture, I push my current patches to the
-patch repository associated with that kernel tree, pop and push all of
-my patches, and build and test that kernel.
-
-Managing patches in a repository makes it possible for multiple
-developers to work on the same patch series without colliding with
-each other, all on top of an underlying source base that they may or
-may not control.
-
-\subsection{MQ support for patch repositories}
-
-MQ helps you to work with the \sdirname{.hg/patches} directory as a
-repository; when you prepare a repository for working with patches
-using \hgxcmd{mq}{qinit}, you can pass the \hgxopt{mq}{qinit}{-c} option to
-create the \sdirname{.hg/patches} directory as a Mercurial repository.
-
-\begin{note}
-  If you forget to use the \hgxopt{mq}{qinit}{-c} option, you can simply go
-  into the \sdirname{.hg/patches} directory at any time and run
-  \hgcmd{init}.  Don't forget to add an entry for the
-  \sfilename{status} file to the \sfilename{.hgignore} file, though
-
-  (\hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} does this for you
-  automatically); you \emph{really} don't want to manage the
-  \sfilename{status} file.
-\end{note}
-
-As a convenience, if MQ notices that the \dirname{.hg/patches}
-directory is a repository, it will automatically \hgcmd{add} every
-patch that you create and import.
-
-MQ provides a shortcut command, \hgxcmd{mq}{qcommit}, that runs
-\hgcmd{commit} in the \sdirname{.hg/patches} directory.  This saves
-some bothersome typing.
-
-Finally, as a convenience to manage the patch directory, you can
-define the alias \command{mq} on Unix systems. For example, on Linux
-systems using the \command{bash} shell, you can include the following
-snippet in your \tildefile{.bashrc}.
-
-\begin{codesample2}
-  alias mq=`hg -R \$(hg root)/.hg/patches'
-\end{codesample2}
-
-You can then issue commands of the form \cmdargs{mq}{pull} from
-the main repository.
-
-\subsection{A few things to watch out for}
-
-MQ's support for working with a repository full of patches is limited
-in a few small respects.
-
-MQ cannot automatically detect changes that you make to the patch
-directory.  If you \hgcmd{pull}, manually edit, or \hgcmd{update}
-changes to patches or the \sfilename{series} file, you will have to
-\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} and then
-\hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} in the underlying repository to
-see those changes show up there.  If you forget to do this, you can
-confuse MQ's idea of which patches are applied.
-
-\section{Third party tools for working with patches}
-\label{sec:mq:tools}
-
-Once you've been working with patches for a while, you'll find
-yourself hungry for tools that will help you to understand and
-manipulate the patches you're dealing with.
-
-The \command{diffstat} command~\cite{web:diffstat} generates a
-histogram of the modifications made to each file in a patch.  It
-provides a good way to ``get a sense of'' a patch---which files it
-affects, and how much change it introduces to each file and as a
-whole.  (I find that it's a good idea to use \command{diffstat}'s
-\cmdopt{diffstat}{-p} option as a matter of course, as otherwise it
-will try to do clever things with prefixes of file names that
-inevitably confuse at least me.)
-
-\begin{figure}[ht]
-  \interaction{mq.tools.tools}
-  \caption{The \command{diffstat}, \command{filterdiff}, and \command{lsdiff} commands}
-  \label{ex:mq:tools}
-\end{figure}
-
-The \package{patchutils} package~\cite{web:patchutils} is invaluable.
-It provides a set of small utilities that follow the ``Unix
-philosophy;'' each does one useful thing with a patch.  The
-\package{patchutils} command I use most is \command{filterdiff}, which
-extracts subsets from a patch file.  For example, given a patch that
-modifies hundreds of files across dozens of directories, a single
-invocation of \command{filterdiff} can generate a smaller patch that
-only touches files whose names match a particular glob pattern.  See
-section~\ref{mq-collab:tips:interdiff} for another example.
-
-\section{Good ways to work with patches}
-
-Whether you are working on a patch series to submit to a free software
-or open source project, or a series that you intend to treat as a
-sequence of regular changesets when you're done, you can use some
-simple techniques to keep your work well organised.
-
-Give your patches descriptive names.  A good name for a patch might be
-\filename{rework-device-alloc.patch}, because it will immediately give
-you a hint what the purpose of the patch is.  Long names shouldn't be
-a problem; you won't be typing the names often, but you \emph{will} be
-running commands like \hgxcmd{mq}{qapplied} and \hgxcmd{mq}{qtop} over and over.
-Good naming becomes especially important when you have a number of
-patches to work with, or if you are juggling a number of different
-tasks and your patches only get a fraction of your attention.
-
-Be aware of what patch you're working on.  Use the \hgxcmd{mq}{qtop}
-command and skim over the text of your patches frequently---for
-example, using \hgcmdargs{tip}{\hgopt{tip}{-p}})---to be sure of where
-you stand.  I have several times worked on and \hgxcmd{mq}{qrefresh}ed a
-patch other than the one I intended, and it's often tricky to migrate
-changes into the right patch after making them in the wrong one.
-
-For this reason, it is very much worth investing a little time to
-learn how to use some of the third-party tools I described in
-section~\ref{sec:mq:tools}, particularly \command{diffstat} and
-\command{filterdiff}.  The former will give you a quick idea of what
-changes your patch is making, while the latter makes it easy to splice
-hunks selectively out of one patch and into another.
-
-\section{MQ cookbook}
-
-\subsection{Manage ``trivial'' patches}
-
-Because the overhead of dropping files into a new Mercurial repository
-is so low, it makes a lot of sense to manage patches this way even if
-you simply want to make a few changes to a source tarball that you
-downloaded.
-
-Begin by downloading and unpacking the source tarball,
-and turning it into a Mercurial repository.
-\interaction{mq.tarball.download}
-
-Continue by creating a patch stack and making your changes.
-\interaction{mq.tarball.qinit}
-
-Let's say a few weeks or months pass, and your package author releases
-a new version.  First, bring their changes into the repository.
-\interaction{mq.tarball.newsource}
-The pipeline starting with \hgcmd{locate} above deletes all files in
-the working directory, so that \hgcmd{commit}'s
-\hgopt{commit}{--addremove} option can actually tell which files have
-really been removed in the newer version of the source.
-
-Finally, you can apply your patches on top of the new tree.
-\interaction{mq.tarball.repush}
-
-\subsection{Combining entire patches}
-\label{sec:mq:combine}
-
-MQ provides a command, \hgxcmd{mq}{qfold} that lets you combine entire
-patches.  This ``folds'' the patches you name, in the order you name
-them, into the topmost applied patch, and concatenates their
-descriptions onto the end of its description.  The patches that you
-fold must be unapplied before you fold them.
-
-The order in which you fold patches matters.  If your topmost applied
-patch is \texttt{foo}, and you \hgxcmd{mq}{qfold} \texttt{bar} and
-\texttt{quux} into it, you will end up with a patch that has the same
-effect as if you applied first \texttt{foo}, then \texttt{bar},
-followed by \texttt{quux}.
-
-\subsection{Merging part of one patch into another}
-
-Merging \emph{part} of one patch into another is more difficult than
-combining entire patches.
-
-If you want to move changes to entire files, you can use
-\command{filterdiff}'s \cmdopt{filterdiff}{-i} and
-\cmdopt{filterdiff}{-x} options to choose the modifications to snip
-out of one patch, concatenating its output onto the end of the patch
-you want to merge into.  You usually won't need to modify the patch
-you've merged the changes from.  Instead, MQ will report some rejected
-hunks when you \hgxcmd{mq}{qpush} it (from the hunks you moved into the
-other patch), and you can simply \hgxcmd{mq}{qrefresh} the patch to drop
-the duplicate hunks.
-
-If you have a patch that has multiple hunks modifying a file, and you
-only want to move a few of those hunks, the job becomes more messy,
-but you can still partly automate it.  Use \cmdargs{lsdiff}{-nvv} to
-print some metadata about the patch.
-\interaction{mq.tools.lsdiff}
-
-This command prints three different kinds of number:
-\begin{itemize}
-\item (in the first column) a \emph{file number} to identify each file
-  modified in the patch;
-\item (on the next line, indented) the line number within a modified
-  file where a hunk starts; and
-\item (on the same line) a \emph{hunk number} to identify that hunk.
-\end{itemize}
-
-You'll have to use some visual inspection, and reading of the patch,
-to identify the file and hunk numbers you'll want, but you can then
-pass them to to \command{filterdiff}'s \cmdopt{filterdiff}{--files}
-and \cmdopt{filterdiff}{--hunks} options, to select exactly the file
-and hunk you want to extract.
-
-Once you have this hunk, you can concatenate it onto the end of your
-destination patch and continue with the remainder of
-section~\ref{sec:mq:combine}.
-
-\section{Differences between quilt and MQ}
-
-If you are already familiar with quilt, MQ provides a similar command
-set.  There are a few differences in the way that it works.
-
-You will already have noticed that most quilt commands have MQ
-counterparts that simply begin with a ``\texttt{q}''.  The exceptions
-are quilt's \texttt{add} and \texttt{remove} commands, the
-counterparts for which are the normal Mercurial \hgcmd{add} and
-\hgcmd{remove} commands.  There is no MQ equivalent of the quilt
-\texttt{edit} command.
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/preface.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-\chapter*{Preface}
-\addcontentsline{toc}{chapter}{Preface}
-\label{chap:preface}
-
-Distributed revision control is a relatively new territory, and has
-thus far grown due to people's willingness to strike out into
-ill-charted territory.
-
-I am writing a book about distributed revision control because I
-believe that it is an important subject that deserves a field guide.
-I chose to write about Mercurial because it is the easiest tool to
-learn the terrain with, and yet it scales to the demands of real,
-challenging environments where many other revision control tools fail.
-
-\section{This book is a work in progress}
-
-I am releasing this book while I am still writing it, in the hope that
-it will prove useful to others.  I also hope that readers will
-contribute as they see fit.
-
-\section{About the examples in this book}
-
-This book takes an unusual approach to code samples.  Every example is
-``live''---each one is actually the result of a shell script that
-executes the Mercurial commands you see.  Every time an image of the
-book is built from its sources, all the example scripts are
-automatically run, and their current results compared against their
-expected results.
-
-The advantage of this approach is that the examples are always
-accurate; they describe \emph{exactly} the behaviour of the version of
-Mercurial that's mentioned at the front of the book.  If I update the
-version of Mercurial that I'm documenting, and the output of some
-command changes, the build fails.
-
-There is a small disadvantage to this approach, which is that the
-dates and times you'll see in examples tend to be ``squashed''
-together in a way that they wouldn't be if the same commands were
-being typed by a human.  Where a human can issue no more than one
-command every few seconds, with any resulting timestamps
-correspondingly spread out, my automated example scripts run many
-commands in one second.
-
-As an instance of this, several consecutive commits in an example can
-show up as having occurred during the same second.  You can see this
-occur in the \hgext{bisect} example in section~\ref{sec:undo:bisect},
-for instance.
-
-So when you're reading examples, don't place too much weight on the
-dates or times you see in the output of commands.  But \emph{do} be
-confident that the behaviour you're seeing is consistent and
-reproducible.
-
-\section{Colophon---this book is Free}
-
-This book is licensed under the Open Publication License, and is
-produced entirely using Free Software tools.  It is typeset with
-\LaTeX{}; illustrations are drawn and rendered with
-\href{http://www.inkscape.org/}{Inkscape}.
-
-The complete source code for this book is published as a Mercurial
-repository, at \url{http://hg.serpentine.com/mercurial/book}.
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/srcinstall.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-\chapter{Installing Mercurial from source}
-\label{chap:srcinstall}
-
-\section{On a Unix-like system}
-\label{sec:srcinstall:unixlike}
-
-If you are using a Unix-like system that has a sufficiently recent
-version of Python (2.3~or newer) available, it is easy to install
-Mercurial from source.
-\begin{enumerate}
-\item Download a recent source tarball from
-  \url{http://www.selenic.com/mercurial/download}.
-\item Unpack the tarball:
-  \begin{codesample4}
-    gzip -dc mercurial-\emph{version}.tar.gz | tar xf -
-  \end{codesample4}
-\item Go into the source directory and run the installer script.  This
-  will build Mercurial and install it in your home directory.
-  \begin{codesample4}
-    cd mercurial-\emph{version}
-    python setup.py install --force --home=\$HOME
-  \end{codesample4}
-\end{enumerate}
-Once the install finishes, Mercurial will be in the \texttt{bin}
-subdirectory of your home directory.  Don't forget to make sure that
-this directory is present in your shell's search path.
-
-You will probably need to set the \envar{PYTHONPATH} environment
-variable so that the Mercurial executable can find the rest of the
-Mercurial packages.  For example, on my laptop, I have set it to
-\texttt{/home/bos/lib/python}.  The exact path that you will need to
-use depends on how Python was built for your system, but should be
-easy to figure out.  If you're uncertain, look through the output of
-the installer script above, and see where the contents of the
-\texttt{mercurial} directory were installed to.
-
-\section{On Windows}
-
-Building and installing Mercurial on Windows requires a variety of
-tools, a fair amount of technical knowledge, and considerable
-patience.  I very much \emph{do not recommend} this route if you are a
-``casual user''.  Unless you intend to hack on Mercurial, I strongly
-suggest that you use a binary package instead.
-
-If you are intent on building Mercurial from source on Windows, follow
-the ``hard way'' directions on the Mercurial wiki at
-\url{http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall},
-and expect the process to involve a lot of fiddly work.
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/template.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,475 +0,0 @@
-\chapter{Customising the output of Mercurial}
-\label{chap:template}
-
-Mercurial provides a powerful mechanism to let you control how it
-displays information.  The mechanism is based on templates.  You can
-use templates to generate specific output for a single command, or to
-customise the entire appearance of the built-in web interface.
-
-\section{Using precanned output styles}
-\label{sec:style}
-
-Packaged with Mercurial are some output styles that you can use
-immediately.  A style is simply a precanned template that someone
-wrote and installed somewhere that Mercurial can find.
-
-Before we take a look at Mercurial's bundled styles, let's review its
-normal output.
-
-\interaction{template.simple.normal}
-
-This is somewhat informative, but it takes up a lot of space---five
-lines of output per changeset.  The \texttt{compact} style reduces
-this to three lines, presented in a sparse manner.
-
-\interaction{template.simple.compact}
-
-The \texttt{changelog} style hints at the expressive power of
-Mercurial's templating engine.  This style attempts to follow the GNU
-Project's changelog guidelines\cite{web:changelog}.
-
-\interaction{template.simple.changelog}
-
-You will not be shocked to learn that Mercurial's default output style
-is named \texttt{default}.
-
-\subsection{Setting a default style}
-
-You can modify the output style that Mercurial will use for every
-command by editing your \hgrc\ file, naming the style you would
-prefer to use.
-
-\begin{codesample2}
-  [ui]
-  style = compact
-\end{codesample2}
-
-If you write a style of your own, you can use it by either providing
-the path to your style file, or copying your style file into a
-location where Mercurial can find it (typically the \texttt{templates}
-subdirectory of your Mercurial install directory).
-
-\section{Commands that support styles and templates}
-
-All of Mercurial's ``\texttt{log}-like'' commands let you use styles
-and templates: \hgcmd{incoming}, \hgcmd{log}, \hgcmd{outgoing}, and
-\hgcmd{tip}.
-
-As I write this manual, these are so far the only commands that
-support styles and templates.  Since these are the most important
-commands that need customisable output, there has been little pressure
-from the Mercurial user community to add style and template support to
-other commands.
-
-\section{The basics of templating}
-
-At its simplest, a Mercurial template is a piece of text.  Some of the
-text never changes, while other parts are \emph{expanded}, or replaced
-with new text, when necessary.
-
-Before we continue, let's look again at a simple example of
-Mercurial's normal output.
-
-\interaction{template.simple.normal}
-
-Now, let's run the same command, but using a template to change its
-output.
-
-\interaction{template.simple.simplest}
-
-The example above illustrates the simplest possible template; it's
-just a piece of static text, printed once for each changeset.  The
-\hgopt{log}{--template} option to the \hgcmd{log} command tells
-Mercurial to use the given text as the template when printing each
-changeset.
-
-Notice that the template string above ends with the text
-``\Verb+\n+''.  This is an \emph{escape sequence}, telling Mercurial
-to print a newline at the end of each template item.  If you omit this
-newline, Mercurial will run each piece of output together.  See
-section~\ref{sec:template:escape} for more details of escape sequences.
-
-A template that prints a fixed string of text all the time isn't very
-useful; let's try something a bit more complex.
-
-\interaction{template.simple.simplesub}
-
-As you can see, the string ``\Verb+{desc}+'' in the template has been
-replaced in the output with the description of each changeset.  Every
-time Mercurial finds text enclosed in curly braces (``\texttt{\{}''
-and ``\texttt{\}}''), it will try to replace the braces and text with
-the expansion of whatever is inside.  To print a literal curly brace,
-you must escape it, as described in section~\ref{sec:template:escape}.
-
-\section{Common template keywords}
-\label{sec:template:keyword}
-
-You can start writing simple templates immediately using the keywords
-below.
-
-\begin{itemize}
-\item[\tplkword{author}] String.  The unmodified author of the changeset.
-\item[\tplkword{branches}] String.  The name of the branch on which
-  the changeset was committed.  Will be empty if the branch name was
-  \texttt{default}.
-\item[\tplkword{date}] Date information.  The date when the changeset
-  was committed.  This is \emph{not} human-readable; you must pass it
-  through a filter that will render it appropriately.  See
-  section~\ref{sec:template:filter} for more information on filters.
-  The date is expressed as a pair of numbers.  The first number is a
-  Unix UTC timestamp (seconds since January 1, 1970); the second is
-  the offset of the committer's timezone from UTC, in seconds.
-\item[\tplkword{desc}] String.  The text of the changeset description.
-\item[\tplkword{files}] List of strings.  All files modified, added, or
-  removed by this changeset.
-\item[\tplkword{file\_adds}] List of strings.  Files added by this
-  changeset.
-\item[\tplkword{file\_dels}] List of strings.  Files removed by this
-  changeset.
-\item[\tplkword{node}] String.  The changeset identification hash, as a
-  40-character hexadecimal string.
-\item[\tplkword{parents}] List of strings.  The parents of the
-  changeset.
-\item[\tplkword{rev}] Integer.  The repository-local changeset revision
-  number.
-\item[\tplkword{tags}] List of strings.  Any tags associated with the
-  changeset.
-\end{itemize}
-
-A few simple experiments will show us what to expect when we use these
-keywords; you can see the results in
-figure~\ref{fig:template:keywords}.
-
-\begin{figure}
-  \interaction{template.simple.keywords}
-  \caption{Template keywords in use}
-  \label{fig:template:keywords}
-\end{figure}
-
-As we noted above, the date keyword does not produce human-readable
-output, so we must treat it specially.  This involves using a
-\emph{filter}, about which more in section~\ref{sec:template:filter}.
-
-\interaction{template.simple.datekeyword}
-
-\section{Escape sequences}
-\label{sec:template:escape}
-
-Mercurial's templating engine recognises the most commonly used escape
-sequences in strings.  When it sees a backslash (``\Verb+\+'')
-character, it looks at the following character and substitutes the two
-characters with a single replacement, as described below.
-
-\begin{itemize}
-\item[\Verb+\textbackslash\textbackslash+] Backslash, ``\Verb+\+'',
-  ASCII~134.
-\item[\Verb+\textbackslash n+] Newline, ASCII~12.
-\item[\Verb+\textbackslash r+] Carriage return, ASCII~15.
-\item[\Verb+\textbackslash t+] Tab, ASCII~11.
-\item[\Verb+\textbackslash v+] Vertical tab, ASCII~13.
-\item[\Verb+\textbackslash \{+] Open curly brace, ``\Verb+{+'', ASCII~173.
-\item[\Verb+\textbackslash \}+] Close curly brace, ``\Verb+}+'', ASCII~175.
-\end{itemize}
-
-As indicated above, if you want the expansion of a template to contain
-a literal ``\Verb+\+'', ``\Verb+{+'', or ``\Verb+{+'' character, you
-must escape it.
-
-\section{Filtering keywords to change their results}
-\label{sec:template:filter}
-
-Some of the results of template expansion are not immediately easy to
-use.  Mercurial lets you specify an optional chain of \emph{filters}
-to modify the result of expanding a keyword.  You have already seen a
-common filter, \tplkwfilt{date}{isodate}, in action above, to make a
-date readable.
-
-Below is a list of the most commonly used filters that Mercurial
-supports.  While some filters can be applied to any text, others can
-only be used in specific circumstances.  The name of each filter is
-followed first by an indication of where it can be used, then a
-description of its effect.
-
-\begin{itemize}
-\item[\tplfilter{addbreaks}] Any text. Add an XHTML ``\Verb+<br/>+''
-  tag before the end of every line except the last.  For example,
-  ``\Verb+foo\nbar+'' becomes ``\Verb+foo<br/>\nbar+''.
-\item[\tplkwfilt{date}{age}] \tplkword{date} keyword.  Render the
-  age of the date, relative to the current time.  Yields a string like
-  ``\Verb+10 minutes+''.
-\item[\tplfilter{basename}] Any text, but most useful for the
-  \tplkword{files} keyword and its relatives.  Treat the text as a
-  path, and return the basename. For example, ``\Verb+foo/bar/baz+''
-  becomes ``\Verb+baz+''.
-\item[\tplkwfilt{date}{date}] \tplkword{date} keyword.  Render a date
-  in a similar format to the Unix \tplkword{date} command, but with
-  timezone included.  Yields a string like
-  ``\Verb+Mon Sep 04 15:13:13 2006 -0700+''.
-\item[\tplkwfilt{author}{domain}] Any text, but most useful for the
-  \tplkword{author} keyword.  Finds the first string that looks like
-  an email address, and extract just the domain component.  For
-  example, ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes
-  ``\Verb+serpentine.com+''.
-\item[\tplkwfilt{author}{email}] Any text, but most useful for the
-  \tplkword{author} keyword.  Extract the first string that looks like
-  an email address.  For example,
-  ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes
-  ``\Verb+bos@serpentine.com+''.
-\item[\tplfilter{escape}] Any text.  Replace the special XML/XHTML
-  characters ``\Verb+&+'', ``\Verb+<+'' and ``\Verb+>+'' with
-  XML entities.
-\item[\tplfilter{fill68}] Any text.  Wrap the text to fit in 68
-  columns.  This is useful before you pass text through the
-  \tplfilter{tabindent} filter, and still want it to fit in an
-  80-column fixed-font window.
-\item[\tplfilter{fill76}] Any text.  Wrap the text to fit in 76
-  columns.
-\item[\tplfilter{firstline}] Any text.  Yield the first line of text,
-  without any trailing newlines.
-\item[\tplkwfilt{date}{hgdate}] \tplkword{date} keyword.  Render the
-  date as a pair of readable numbers.  Yields a string like
-  ``\Verb+1157407993 25200+''.
-\item[\tplkwfilt{date}{isodate}] \tplkword{date} keyword.  Render the
-  date as a text string in ISO~8601 format.  Yields a string like
-  ``\Verb+2006-09-04 15:13:13 -0700+''.
-\item[\tplfilter{obfuscate}] Any text, but most useful for the
-  \tplkword{author} keyword.  Yield the input text rendered as a
-  sequence of XML entities.  This helps to defeat some particularly
-  stupid screen-scraping email harvesting spambots.
-\item[\tplkwfilt{author}{person}] Any text, but most useful for the
-  \tplkword{author} keyword.  Yield the text before an email address.
-  For example, ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+''
-  becomes ``\Verb+Bryan O'Sullivan+''.
-\item[\tplkwfilt{date}{rfc822date}] \tplkword{date} keyword.  Render a
-  date using the same format used in email headers.  Yields a string
-  like ``\Verb+Mon, 04 Sep 2006 15:13:13 -0700+''.
-\item[\tplkwfilt{node}{short}] Changeset hash.  Yield the short form
-  of a changeset hash, i.e.~a 12-character hexadecimal string.
-\item[\tplkwfilt{date}{shortdate}] \tplkword{date} keyword.  Render
-  the year, month, and day of the date.  Yields a string like
-  ``\Verb+2006-09-04+''.
-\item[\tplfilter{strip}] Any text.  Strip all leading and trailing
-  whitespace from the string.
-\item[\tplfilter{tabindent}] Any text.  Yield the text, with every line
-  except the first starting with a tab character.
-\item[\tplfilter{urlescape}] Any text.  Escape all characters that are
-  considered ``special'' by URL parsers.  For example, \Verb+foo bar+
-  becomes \Verb+foo%20bar+.
-\item[\tplkwfilt{author}{user}] Any text, but most useful for the
-  \tplkword{author} keyword.  Return the ``user'' portion of an email
-  address.  For example,
-  ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes
-  ``\Verb+bos+''.
-\end{itemize}
-
-\begin{figure}
-  \interaction{template.simple.manyfilters}
-  \caption{Template filters in action}
-  \label{fig:template:filters}
-\end{figure}
-
-\begin{note}
-  If you try to apply a filter to a piece of data that it cannot
-  process, Mercurial will fail and print a Python exception.  For
-  example, trying to run the output of the \tplkword{desc} keyword
-  into the \tplkwfilt{date}{isodate} filter is not a good idea.
-\end{note}
-
-\subsection{Combining filters}
-
-It is easy to combine filters to yield output in the form you would
-like.  The following chain of filters tidies up a description, then
-makes sure that it fits cleanly into 68 columns, then indents it by a
-further 8~characters (at least on Unix-like systems, where a tab is
-conventionally 8~characters wide).
-
-\interaction{template.simple.combine}
-
-Note the use of ``\Verb+\t+'' (a tab character) in the template to
-force the first line to be indented; this is necessary since
-\tplkword{tabindent} indents all lines \emph{except} the first.
-
-Keep in mind that the order of filters in a chain is significant.  The
-first filter is applied to the result of the keyword; the second to
-the result of the first filter; and so on.  For example, using
-\Verb+fill68|tabindent+ gives very different results from
-\Verb+tabindent|fill68+.
-
-
-\section{From templates to styles}
-
-A command line template provides a quick and simple way to format some
-output.  Templates can become verbose, though, and it's useful to be
-able to give a template a name.  A style file is a template with a
-name, stored in a file.
-
-More than that, using a style file unlocks the power of Mercurial's
-templating engine in ways that are not possible using the command line
-\hgopt{log}{--template} option.
-
-\subsection{The simplest of style files}
-
-Our simple style file contains just one line:
-
-\interaction{template.simple.rev}
-
-This tells Mercurial, ``if you're printing a changeset, use the text
-on the right as the template''.
-
-\subsection{Style file syntax}
-
-The syntax rules for a style file are simple.
-
-\begin{itemize}
-\item The file is processed one line at a time.
-
-\item Leading and trailing white space are ignored.
-
-\item Empty lines are skipped.
-
-\item If a line starts with either of the characters ``\texttt{\#}'' or
-  ``\texttt{;}'', the entire line is treated as a comment, and skipped
-  as if empty.
-
-\item A line starts with a keyword.  This must start with an
-  alphabetic character or underscore, and can subsequently contain any
-  alphanumeric character or underscore.  (In regexp notation, a
-  keyword must match \Verb+[A-Za-z_][A-Za-z0-9_]*+.)
-
-\item The next element must be an ``\texttt{=}'' character, which can
-  be preceded or followed by an arbitrary amount of white space.
-
-\item If the rest of the line starts and ends with matching quote
-  characters (either single or double quote), it is treated as a
-  template body.
-
-\item If the rest of the line \emph{does not} start with a quote
-  character, it is treated as the name of a file; the contents of this
-  file will be read and used as a template body.
-\end{itemize}
-
-\section{Style files by example}
-
-To illustrate how to write a style file, we will construct a few by
-example.  Rather than provide a complete style file and walk through
-it, we'll mirror the usual process of developing a style file by
-starting with something very simple, and walking through a series of
-successively more complete examples.
-
-\subsection{Identifying mistakes in style files}
-
-If Mercurial encounters a problem in a style file you are working on,
-it prints a terse error message that, once you figure out what it
-means, is actually quite useful.
-
-\interaction{template.svnstyle.syntax.input}
-
-Notice that \filename{broken.style} attempts to define a
-\texttt{changeset} keyword, but forgets to give any content for it.
-When instructed to use this style file, Mercurial promptly complains.
-
-\interaction{template.svnstyle.syntax.error}
-
-This error message looks intimidating, but it is not too hard to
-follow.
-
-\begin{itemize}
-\item The first component is simply Mercurial's way of saying ``I am
-  giving up''.
-  \begin{codesample4}
-    \textbf{abort:} broken.style:1: parse error
-  \end{codesample4}
-
-\item Next comes the name of the style file that contains the error.
-  \begin{codesample4}
-    abort: \textbf{broken.style}:1: parse error
-  \end{codesample4}
-
-\item Following the file name is the line number where the error was
-  encountered.
-  \begin{codesample4}
-    abort: broken.style:\textbf{1}: parse error
-  \end{codesample4}
-
-\item Finally, a description of what went wrong.
-  \begin{codesample4}
-    abort: broken.style:1: \textbf{parse error}
-  \end{codesample4}
-  The description of the problem is not always clear (as in this
-  case), but even when it is cryptic, it is almost always trivial to
-  visually inspect the offending line in the style file and see what
-  is wrong.
-\end{itemize}
-
-\subsection{Uniquely identifying a repository}
-
-If you would like to be able to identify a Mercurial repository
-``fairly uniquely'' using a short string as an identifier, you can
-use the first revision in the repository.
-\interaction{template.svnstyle.id} 
-This is not guaranteed to be unique, but it is nevertheless useful in
-many cases.
-\begin{itemize}
-\item It will not work in a completely empty repository, because such
-  a repository does not have a revision~zero.
-\item Neither will it work in the (extremely rare) case where a
-  repository is a merge of two or more formerly independent
-  repositories, and you still have those repositories around.
-\end{itemize}
-Here are some uses to which you could put this identifier:
-\begin{itemize}
-\item As a key into a table for a database that manages repositories
-  on a server.
-\item As half of a \{\emph{repository~ID}, \emph{revision~ID}\} tuple.
-  Save this information away when you run an automated build or other
-  activity, so that you can ``replay'' the build later if necessary.
-\end{itemize}
-
-\subsection{Mimicking Subversion's output}
-
-Let's try to emulate the default output format used by another
-revision control tool, Subversion.
-\interaction{template.svnstyle.short}
-
-Since Subversion's output style is fairly simple, it is easy to
-copy-and-paste a hunk of its output into a file, and replace the text
-produced above by Subversion with the template values we'd like to see
-expanded.
-\interaction{template.svnstyle.template}
-
-There are a few small ways in which this template deviates from the
-output produced by Subversion.
-\begin{itemize}
-\item Subversion prints a ``readable'' date (the ``\texttt{Wed, 27 Sep
-    2006}'' in the example output above) in parentheses.  Mercurial's
-  templating engine does not provide a way to display a date in this
-  format without also printing the time and time zone.
-\item We emulate Subversion's printing of ``separator'' lines full of
-  ``\texttt{-}'' characters by ending the template with such a line.
-  We use the templating engine's \tplkword{header} keyword to print a
-  separator line as the first line of output (see below), thus
-  achieving similar output to Subversion.
-\item Subversion's output includes a count in the header of the number
-  of lines in the commit message.  We cannot replicate this in
-  Mercurial; the templating engine does not currently provide a filter
-  that counts the number of lines the template generates.
-\end{itemize}
-It took me no more than a minute or two of work to replace literal
-text from an example of Subversion's output with some keywords and
-filters to give the template above.  The style file simply refers to
-the template.
-\interaction{template.svnstyle.style}
-
-We could have included the text of the template file directly in the
-style file by enclosing it in quotes and replacing the newlines with
-``\verb!\n!'' sequences, but it would have made the style file too
-difficult to read.  Readability is a good guide when you're trying to
-decide whether some text belongs in a style file, or in a template
-file that the style file points to.  If the style file will look too
-big or cluttered if you insert a literal piece of text, drop it into a
-template instead.
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/tour-basic.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,624 +0,0 @@
-\chapter{A tour of Mercurial: the basics}
-\label{chap:tour-basic}
-
-\section{Installing Mercurial on your system}
-\label{sec:tour:install}
-
-Prebuilt binary packages of Mercurial are available for every popular
-operating system.  These make it easy to start using Mercurial on your
-computer immediately.
-
-\subsection{Linux}
-
-Because each Linux distribution has its own packaging tools, policies,
-and rate of development, it's difficult to give a comprehensive set of
-instructions on how to install Mercurial binaries.  The version of
-Mercurial that you will end up with can vary depending on how active
-the person is who maintains the package for your distribution.
-
-To keep things simple, I will focus on installing Mercurial from the
-command line under the most popular Linux distributions.  Most of
-these distributions provide graphical package managers that will let
-you install Mercurial with a single click; the package name to look
-for is \texttt{mercurial}.
-
-\begin{itemize}
-\item[Debian]
-  \begin{codesample4}
-    apt-get install mercurial
-  \end{codesample4}
-
-\item[Fedora Core]
-  \begin{codesample4}
-    yum install mercurial
-  \end{codesample4}
-
-\item[Gentoo]
-  \begin{codesample4}
-    emerge mercurial
-  \end{codesample4}
-
-\item[OpenSUSE]
-  \begin{codesample4}
-    yum install mercurial
-  \end{codesample4}
-
-\item[Ubuntu] Ubuntu's Mercurial package is based on Debian's.  To
-  install it, run the following command.
-  \begin{codesample4}
-    apt-get install mercurial
-  \end{codesample4}
-  The Ubuntu package for Mercurial tends to lag behind the Debian
-  version by a considerable time margin (at the time of writing, seven
-  months), which in some cases will mean that on Ubuntu, you may run
-  into problems that have since been fixed in the Debian package.
-\end{itemize}
-
-\subsection{Solaris}
-
-SunFreeWare, at \url{http://www.sunfreeware.com}, is a good source for a
-large number of pre-built Solaris packages for 32 and 64 bit Intel and
-Sparc architectures, including current versions of Mercurial.
-
-\subsection{Mac OS X}
-
-Lee Cantey publishes an installer of Mercurial for Mac OS~X at
-\url{http://mercurial.berkwood.com}.  This package works on both
-Intel-~and Power-based Macs.  Before you can use it, you must install
-a compatible version of Universal MacPython~\cite{web:macpython}.  This
-is easy to do; simply follow the instructions on Lee's site.
-
-It's also possible to install Mercurial using Fink or MacPorts,
-two popular free package managers for Mac OS X.  If you have Fink,
-use \command{sudo apt-get install mercurial-py25}.  If MacPorts,
-\command{sudo port install mercurial}.
-
-\subsection{Windows}
-
-Lee Cantey publishes an installer of Mercurial for Windows at
-\url{http://mercurial.berkwood.com}.  This package has no external
-dependencies; it ``just works''.
-
-\begin{note}
-  The Windows version of Mercurial does not automatically convert line
-  endings between Windows and Unix styles.  If you want to share work
-  with Unix users, you must do a little additional configuration
-  work. XXX Flesh this out.
-\end{note}
-
-\section{Getting started}
-
-To begin, we'll use the \hgcmd{version} command to find out whether
-Mercurial is actually installed properly.  The actual version
-information that it prints isn't so important; it's whether it prints
-anything at all that we care about.
-\interaction{tour.version}
-
-\subsection{Built-in help}
-
-Mercurial provides a built-in help system.  This is invaluable for those
-times when you find yourself stuck trying to remember how to run a
-command.  If you are completely stuck, simply run \hgcmd{help}; it
-will print a brief list of commands, along with a description of what
-each does.  If you ask for help on a specific command (as below), it
-prints more detailed information.
-\interaction{tour.help}
-For a more impressive level of detail (which you won't usually need)
-run \hgcmdargs{help}{\hggopt{-v}}.  The \hggopt{-v} option is short
-for \hggopt{--verbose}, and tells Mercurial to print more information
-than it usually would.
-
-\section{Working with a repository}
-
-In Mercurial, everything happens inside a \emph{repository}.  The
-repository for a project contains all of the files that ``belong to''
-that project, along with a historical record of the project's files.
-
-There's nothing particularly magical about a repository; it is simply
-a directory tree in your filesystem that Mercurial treats as special.
-You can rename or delete a repository any time you like, using either the
-command line or your file browser.
-
-\subsection{Making a local copy of a repository}
-
-\emph{Copying} a repository is just a little bit special.  While you
-could use a normal file copying command to make a copy of a
-repository, it's best to use a built-in command that Mercurial
-provides.  This command is called \hgcmd{clone}, because it creates an
-identical copy of an existing repository.
-\interaction{tour.clone}
-If our clone succeeded, we should now have a local directory called
-\dirname{hello}.  This directory will contain some files.
-\interaction{tour.ls}
-These files have the same contents and history in our repository as
-they do in the repository we cloned.
-
-Every Mercurial repository is complete, self-contained, and
-independent.  It contains its own private copy of a project's files
-and history.  A cloned repository remembers the location of the
-repository it was cloned from, but it does not communicate with that
-repository, or any other, unless you tell it to.
-
-What this means for now is that we're free to experiment with our
-repository, safe in the knowledge that it's a private ``sandbox'' that
-won't affect anyone else.
-
-\subsection{What's in a repository?}
-
-When we take a more detailed look inside a repository, we can see that
-it contains a directory named \dirname{.hg}.  This is where Mercurial
-keeps all of its metadata for the repository.
-\interaction{tour.ls-a}
-
-The contents of the \dirname{.hg} directory and its subdirectories are
-private to Mercurial.  Every other file and directory in the
-repository is yours to do with as you please.
-
-To introduce a little terminology, the \dirname{.hg} directory is the
-``real'' repository, and all of the files and directories that coexist
-with it are said to live in the \emph{working directory}.  An easy way
-to remember the distinction is that the \emph{repository} contains the
-\emph{history} of your project, while the \emph{working directory}
-contains a \emph{snapshot} of your project at a particular point in
-history.
-
-\section{A tour through history}
-
-One of the first things we might want to do with a new, unfamiliar
-repository is understand its history.  The \hgcmd{log} command gives
-us a view of history.
-\interaction{tour.log}
-By default, this command prints a brief paragraph of output for each
-change to the project that was recorded.  In Mercurial terminology, we
-call each of these recorded events a \emph{changeset}, because it can
-contain a record of changes to several files.
-
-The fields in a record of output from \hgcmd{log} are as follows.
-\begin{itemize}
-\item[\texttt{changeset}] This field has the format of a number,
-  followed by a colon, followed by a hexadecimal string.  These are
-  \emph{identifiers} for the changeset.  There are two identifiers
-  because the number is shorter and easier to type than the hex
-  string.
-\item[\texttt{user}] The identity of the person who created the
-  changeset.  This is a free-form field, but it most often contains a
-  person's name and email address.
-\item[\texttt{date}] The date and time on which the changeset was
-  created, and the timezone in which it was created.  (The date and
-  time are local to that timezone; they display what time and date it
-  was for the person who created the changeset.)
-\item[\texttt{summary}] The first line of the text message that the
-  creator of the changeset entered to describe the changeset.
-\end{itemize}
-The default output printed by \hgcmd{log} is purely a summary; it is
-missing a lot of detail.
-
-Figure~\ref{fig:tour-basic:history} provides a graphical representation of
-the history of the \dirname{hello} repository, to make it a little
-easier to see which direction history is ``flowing'' in.  We'll be
-returning to this figure several times in this chapter and the chapter
-that follows.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{tour-history}
-  \caption{Graphical history of the \dirname{hello} repository}
-  \label{fig:tour-basic:history}
-\end{figure}
-
-\subsection{Changesets, revisions, and talking to other 
-  people}
-
-As English is a notoriously sloppy language, and computer science has
-a hallowed history of terminological confusion (why use one term when
-four will do?), revision control has a variety of words and phrases
-that mean the same thing.  If you are talking about Mercurial history
-with other people, you will find that the word ``changeset'' is often
-compressed to ``change'' or (when written) ``cset'', and sometimes a
-changeset is referred to as a ``revision'' or a ``rev''.
-
-While it doesn't matter what \emph{word} you use to refer to the
-concept of ``a~changeset'', the \emph{identifier} that you use to
-refer to ``a~\emph{specific} changeset'' is of great importance.
-Recall that the \texttt{changeset} field in the output from
-\hgcmd{log} identifies a changeset using both a number and a
-hexadecimal string.
-\begin{itemize}
-\item The revision number is \emph{only valid in that repository},
-\item while the hex string is the \emph{permanent, unchanging
-    identifier} that will always identify that exact changeset in
-  \emph{every} copy of the repository.
-\end{itemize}
-This distinction is important.  If you send someone an email talking
-about ``revision~33'', there's a high likelihood that their
-revision~33 will \emph{not be the same} as yours.  The reason for this
-is that a revision number depends on the order in which changes
-arrived in a repository, and there is no guarantee that the same
-changes will happen in the same order in different repositories.
-Three changes $a,b,c$ can easily appear in one repository as $0,1,2$,
-while in another as $1,0,2$.
-
-Mercurial uses revision numbers purely as a convenient shorthand.  If
-you need to discuss a changeset with someone, or make a record of a
-changeset for some other reason (for example, in a bug report), use
-the hexadecimal identifier.
-
-\subsection{Viewing specific revisions}
-
-To narrow the output of \hgcmd{log} down to a single revision, use the
-\hgopt{log}{-r} (or \hgopt{log}{--rev}) option.  You can use either a
-revision number or a long-form changeset identifier, and you can
-provide as many revisions as you want.  \interaction{tour.log-r}
-
-If you want to see the history of several revisions without having to
-list each one, you can use \emph{range notation}; this lets you
-express the idea ``I want all revisions between $a$ and $b$,
-inclusive''.
-\interaction{tour.log.range}
-Mercurial also honours the order in which you specify revisions, so
-\hgcmdargs{log}{-r 2:4} prints $2,3,4$ while \hgcmdargs{log}{-r 4:2}
-prints $4,3,2$.
-
-\subsection{More detailed information}
-
-While the summary information printed by \hgcmd{log} is useful if you
-already know what you're looking for, you may need to see a complete
-description of the change, or a list of the files changed, if you're
-trying to decide whether a changeset is the one you're looking for.
-The \hgcmd{log} command's \hggopt{-v} (or \hggopt{--verbose})
-option gives you this extra detail.
-\interaction{tour.log-v}
-
-If you want to see both the description and content of a change, add
-the \hgopt{log}{-p} (or \hgopt{log}{--patch}) option.  This displays
-the content of a change as a \emph{unified diff} (if you've never seen
-a unified diff before, see section~\ref{sec:mq:patch} for an overview).
-\interaction{tour.log-vp}
-
-\section{All about command options}
-
-Let's take a brief break from exploring Mercurial commands to discuss
-a pattern in the way that they work; you may find this useful to keep
-in mind as we continue our tour.
-
-Mercurial has a consistent and straightforward approach to dealing
-with the options that you can pass to commands.  It follows the
-conventions for options that are common to modern Linux and Unix
-systems.
-\begin{itemize}
-\item Every option has a long name.  For example, as we've already
-  seen, the \hgcmd{log} command accepts a \hgopt{log}{--rev} option.
-\item Most options have short names, too.  Instead of
-  \hgopt{log}{--rev}, we can use \hgopt{log}{-r}.  (The reason that
-  some options don't have short names is that the options in question
-  are rarely used.)
-\item Long options start with two dashes (e.g.~\hgopt{log}{--rev}),
-  while short options start with one (e.g.~\hgopt{log}{-r}).
-\item Option naming and usage is consistent across commands.  For
-  example, every command that lets you specify a changeset~ID or
-  revision number accepts both \hgopt{log}{-r} and \hgopt{log}{--rev}
-  arguments.
-\end{itemize}
-In the examples throughout this book, I use short options instead of
-long.  This just reflects my own preference, so don't read anything
-significant into it.
-
-Most commands that print output of some kind will print more output
-when passed a \hggopt{-v} (or \hggopt{--verbose}) option, and less
-when passed \hggopt{-q} (or \hggopt{--quiet}).
-
-\section{Making and reviewing changes}
-
-Now that we have a grasp of viewing history in Mercurial, let's take a
-look at making some changes and examining them.
-
-The first thing we'll do is isolate our experiment in a repository of
-its own.  We use the \hgcmd{clone} command, but we don't need to
-clone a copy of the remote repository.  Since we already have a copy
-of it locally, we can just clone that instead.  This is much faster
-than cloning over the network, and cloning a local repository uses
-less disk space in most cases, too.
-\interaction{tour.reclone}
-As an aside, it's often good practice to keep a ``pristine'' copy of a
-remote repository around, which you can then make temporary clones of
-to create sandboxes for each task you want to work on.  This lets you
-work on multiple tasks in parallel, each isolated from the others
-until it's complete and you're ready to integrate it back.  Because
-local clones are so cheap, there's almost no overhead to cloning and
-destroying repositories whenever you want.
-
-In our \dirname{my-hello} repository, we have a file
-\filename{hello.c} that contains the classic ``hello, world'' program.
-Let's use the ancient and venerable \command{sed} command to edit this
-file so that it prints a second line of output.  (I'm only using
-\command{sed} to do this because it's easy to write a scripted example
-this way.  Since you're not under the same constraint, you probably
-won't want to use \command{sed}; simply use your preferred text editor to
-do the same thing.)
-\interaction{tour.sed}
-
-Mercurial's \hgcmd{status} command will tell us what Mercurial knows
-about the files in the repository.
-\interaction{tour.status}
-The \hgcmd{status} command prints no output for some files, but a line
-starting with ``\texttt{M}'' for \filename{hello.c}.  Unless you tell
-it to, \hgcmd{status} will not print any output for files that have
-not been modified.  
-
-The ``\texttt{M}'' indicates that Mercurial has noticed that we
-modified \filename{hello.c}.  We didn't need to \emph{inform}
-Mercurial that we were going to modify the file before we started, or
-that we had modified the file after we were done; it was able to
-figure this out itself.
-
-It's a little bit helpful to know that we've modified
-\filename{hello.c}, but we might prefer to know exactly \emph{what}
-changes we've made to it.  To do this, we use the \hgcmd{diff}
-command.
-\interaction{tour.diff}
-
-\section{Recording changes in a new changeset}
-
-We can modify files, build and test our changes, and use
-\hgcmd{status} and \hgcmd{diff} to review our changes, until we're
-satisfied with what we've done and arrive at a natural stopping point
-where we want to record our work in a new changeset.
-
-The \hgcmd{commit} command lets us create a new changeset; we'll
-usually refer to this as ``making a commit'' or ``committing''.  
-
-\subsection{Setting up a username}
-
-When you try to run \hgcmd{commit} for the first time, it is not
-guaranteed to succeed.  Mercurial records your name and address with
-each change that you commit, so that you and others will later be able
-to tell who made each change.  Mercurial tries to automatically figure
-out a sensible username to commit the change with.  It will attempt
-each of the following methods, in order:
-\begin{enumerate}
-\item If you specify a \hgopt{commit}{-u} option to the \hgcmd{commit}
-  command on the command line, followed by a username, this is always
-  given the highest precedence.
-\item If you have set the \envar{HGUSER} environment variable, this is
-  checked next.
-\item If you create a file in your home directory called
-  \sfilename{.hgrc}, with a \rcitem{ui}{username} entry, that will be
-  used next.  To see what the contents of this file should look like,
-  refer to section~\ref{sec:tour-basic:username} below.
-\item If you have set the \envar{EMAIL} environment variable, this
-  will be used next.
-\item Mercurial will query your system to find out your local user
-  name and host name, and construct a username from these components.
-  Since this often results in a username that is not very useful, it
-  will print a warning if it has to do this.
-\end{enumerate}
-If all of these mechanisms fail, Mercurial will fail, printing an
-error message.  In this case, it will not let you commit until you set
-up a username.
-
-You should think of the \envar{HGUSER} environment variable and the
-\hgopt{commit}{-u} option to the \hgcmd{commit} command as ways to
-\emph{override} Mercurial's default selection of username.  For normal
-use, the simplest and most robust way to set a username for yourself
-is by creating a \sfilename{.hgrc} file; see below for details.
-
-\subsubsection{Creating a Mercurial configuration file}
-\label{sec:tour-basic:username}
-
-To set a user name, use your favourite editor to create a file called
-\sfilename{.hgrc} in your home directory.  Mercurial will use this
-file to look up your personalised configuration settings.  The initial
-contents of your \sfilename{.hgrc} should look like this.
-\begin{codesample2}
-  # This is a Mercurial configuration file.
-  [ui]
-  username = Firstname Lastname <email.address@domain.net>
-\end{codesample2}
-The ``\texttt{[ui]}'' line begins a \emph{section} of the config file,
-so you can read the ``\texttt{username = ...}'' line as meaning ``set
-the value of the \texttt{username} item in the \texttt{ui} section''.
-A section continues until a new section begins, or the end of the
-file.  Mercurial ignores empty lines and treats any text from
-``\texttt{\#}'' to the end of a line as a comment.
-
-\subsubsection{Choosing a user name}
-
-You can use any text you like as the value of the \texttt{username}
-config item, since this information is for reading by other people,
-but for interpreting by Mercurial.  The convention that most people
-follow is to use their name and email address, as in the example
-above.
-
-\begin{note}
-  Mercurial's built-in web server obfuscates email addresses, to make
-  it more difficult for the email harvesting tools that spammers use.
-  This reduces the likelihood that you'll start receiving more junk
-  email if you publish a Mercurial repository on the web.
-\end{note}
-
-\subsection{Writing a commit message}
-
-When we commit a change, Mercurial drops us into a text editor, to
-enter a message that will describe the modifications we've made in
-this changeset.  This is called the \emph{commit message}.  It will be
-a record for readers of what we did and why, and it will be printed by
-\hgcmd{log} after we've finished committing.
-\interaction{tour.commit}
-
-The editor that the \hgcmd{commit} command drops us into will contain
-an empty line, followed by a number of lines starting with
-``\texttt{HG:}''.
-\begin{codesample2}
-  \emph{empty line}
-  HG: changed hello.c
-\end{codesample2}
-Mercurial ignores the lines that start with ``\texttt{HG:}''; it uses
-them only to tell us which files it's recording changes to.  Modifying
-or deleting these lines has no effect.
-
-\subsection{Writing a good commit message}
-
-Since \hgcmd{log} only prints the first line of a commit message by
-default, it's best to write a commit message whose first line stands
-alone.  Here's a real example of a commit message that \emph{doesn't}
-follow this guideline, and hence has a summary that is not readable.
-\begin{codesample2}
-  changeset:   73:584af0e231be
-  user:        Censored Person <censored.person@example.org>
-  date:        Tue Sep 26 21:37:07 2006 -0700
-  summary:     include buildmeister/commondefs.   Add an exports and install
-\end{codesample2}
-
-As far as the remainder of the contents of the commit message are
-concerned, there are no hard-and-fast rules.  Mercurial itself doesn't
-interpret or care about the contents of the commit message, though
-your project may have policies that dictate a certain kind of
-formatting.
-
-My personal preference is for short, but informative, commit messages
-that tell me something that I can't figure out with a quick glance at
-the output of \hgcmdargs{log}{--patch}.
-
-\subsection{Aborting a commit}
-
-If you decide that you don't want to commit while in the middle of
-editing a commit message, simply exit from your editor without saving
-the file that it's editing.  This will cause nothing to happen to
-either the repository or the working directory.
-
-If we run the \hgcmd{commit} command without any arguments, it records
-all of the changes we've made, as reported by \hgcmd{status} and
-\hgcmd{diff}.
-
-\subsection{Admiring our new handiwork}
-
-Once we've finished the commit, we can use the \hgcmd{tip} command to
-display the changeset we just created.  This command produces output
-that is identical to \hgcmd{log}, but it only displays the newest
-revision in the repository.
-\interaction{tour.tip}
-We refer to the newest revision in the repository as the tip revision,
-or simply the tip.
-
-\section{Sharing changes}
-
-We mentioned earlier that repositories in Mercurial are
-self-contained.  This means that the changeset we just created exists
-only in our \dirname{my-hello} repository.  Let's look at a few ways
-that we can propagate this change into other repositories.
-
-\subsection{Pulling changes from another repository}
-\label{sec:tour:pull}
-
-To get started, let's clone our original \dirname{hello} repository,
-which does not contain the change we just committed.  We'll call our
-temporary repository \dirname{hello-pull}.
-\interaction{tour.clone-pull}
-
-We'll use the \hgcmd{pull} command to bring changes from
-\dirname{my-hello} into \dirname{hello-pull}.  However, blindly
-pulling unknown changes into a repository is a somewhat scary
-prospect.  Mercurial provides the \hgcmd{incoming} command to tell us
-what changes the \hgcmd{pull} command \emph{would} pull into the
-repository, without actually pulling the changes in.
-\interaction{tour.incoming}
-(Of course, someone could cause more changesets to appear in the
-repository that we ran \hgcmd{incoming} in, before we get a chance to
-\hgcmd{pull} the changes, so that we could end up pulling changes that we
-didn't expect.)
-
-Bringing changes into a repository is a simple matter of running the
-\hgcmd{pull} command, and telling it which repository to pull from.
-\interaction{tour.pull}
-As you can see from the before-and-after output of \hgcmd{tip}, we
-have successfully pulled changes into our repository.  There remains
-one step before we can see these changes in the working directory.
-
-\subsection{Updating the working directory}
-
-We have so far glossed over the relationship between a repository and
-its working directory.  The \hgcmd{pull} command that we ran in
-section~\ref{sec:tour:pull} brought changes into the repository, but
-if we check, there's no sign of those changes in the working
-directory.  This is because \hgcmd{pull} does not (by default) touch
-the working directory.  Instead, we use the \hgcmd{update} command to
-do this.
-\interaction{tour.update}
-
-It might seem a bit strange that \hgcmd{pull} doesn't update the
-working directory automatically.  There's actually a good reason for
-this: you can use \hgcmd{update} to update the working directory to
-the state it was in at \emph{any revision} in the history of the
-repository.  If you had the working directory updated to an old
-revision---to hunt down the origin of a bug, say---and ran a
-\hgcmd{pull} which automatically updated the working directory to a
-new revision, you might not be terribly happy.
-
-However, since pull-then-update is such a common thing to do,
-Mercurial lets you combine the two by passing the \hgopt{pull}{-u}
-option to \hgcmd{pull}.
-\begin{codesample2}
-  hg pull -u
-\end{codesample2}
-If you look back at the output of \hgcmd{pull} in
-section~\ref{sec:tour:pull} when we ran it without \hgopt{pull}{-u},
-you can see that it printed a helpful reminder that we'd have to take
-an explicit step to update the working directory:
-\begin{codesample2}
-  (run 'hg update' to get a working copy)
-\end{codesample2}
-
-To find out what revision the working directory is at, use the
-\hgcmd{parents} command.
-\interaction{tour.parents}
-If you look back at figure~\ref{fig:tour-basic:history}, you'll see
-arrows connecting each changeset.  The node that the arrow leads
-\emph{from} in each case is a parent, and the node that the arrow
-leads \emph{to} is its child.  The working directory has a parent in
-just the same way; this is the changeset that the working directory
-currently contains.
-
-To update the working directory to a particular revision, give a
-revision number or changeset~ID to the \hgcmd{update} command.
-\interaction{tour.older}
-If you omit an explicit revision, \hgcmd{update} will update to the
-tip revision, as shown by the second call to \hgcmd{update} in the
-example above.
-
-\subsection{Pushing changes to another repository}
-
-Mercurial lets us push changes to another repository, from the
-repository we're currently visiting.  As with the example of
-\hgcmd{pull} above, we'll create a temporary repository to push our
-changes into.
-\interaction{tour.clone-push}
-The \hgcmd{outgoing} command tells us what changes would be pushed
-into another repository.
-\interaction{tour.outgoing}
-And the \hgcmd{push} command does the actual push.
-\interaction{tour.push}
-As with \hgcmd{pull}, the \hgcmd{push} command does not update the
-working directory in the repository that it's pushing changes into.
-(Unlike \hgcmd{pull}, \hgcmd{push} does not provide a \texttt{-u}
-option that updates the other repository's working directory.)
-
-What happens if we try to pull or push changes and the receiving
-repository already has those changes?  Nothing too exciting.
-\interaction{tour.push.nothing}
-
-\subsection{Sharing changes over a network}
-
-The commands we have covered in the previous few sections are not
-limited to working with local repositories.  Each works in exactly the
-same fashion over a network connection; simply pass in a URL instead
-of a local path.
-\interaction{tour.outgoing.net}
-In this example, we can see what changes we could push to the remote
-repository, but the repository is understandably not set up to let
-anonymous users push to it.
-\interaction{tour.push.net}
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/tour-merge.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,283 +0,0 @@
-\chapter{A tour of Mercurial: merging work}
-\label{chap:tour-merge}
-
-We've now covered cloning a repository, making changes in a
-repository, and pulling or pushing changes from one repository into
-another.  Our next step is \emph{merging} changes from separate
-repositories.
-
-\section{Merging streams of work}
-
-Merging is a fundamental part of working with a distributed revision
-control tool.
-\begin{itemize}
-\item Alice and Bob each have a personal copy of a repository for a
-  project they're collaborating on.  Alice fixes a bug in her
-  repository; Bob adds a new feature in his.  They want the shared
-  repository to contain both the bug fix and the new feature.
-\item I frequently work on several different tasks for a single
-  project at once, each safely isolated in its own repository.
-  Working this way means that I often need to merge one piece of my
-  own work with another.
-\end{itemize}
-
-Because merging is such a common thing to need to do, Mercurial makes
-it easy.  Let's walk through the process.  We'll begin by cloning yet
-another repository (see how often they spring up?) and making a change
-in it.
-\interaction{tour.merge.clone}
-We should now have two copies of \filename{hello.c} with different
-contents.  The histories of the two repositories have also diverged,
-as illustrated in figure~\ref{fig:tour-merge:sep-repos}.
-\interaction{tour.merge.cat}
-
-\begin{figure}[ht]
-  \centering
-  \grafix{tour-merge-sep-repos}
-  \caption{Divergent recent histories of the \dirname{my-hello} and
-    \dirname{my-new-hello} repositories}
-  \label{fig:tour-merge:sep-repos}
-\end{figure}
-
-We already know that pulling changes from our \dirname{my-hello}
-repository will have no effect on the working directory.
-\interaction{tour.merge.pull}
-However, the \hgcmd{pull} command says something about ``heads''.  
-
-\subsection{Head changesets}
-
-A head is a change that has no descendants, or children, as they're
-also known.  The tip revision is thus a head, because the newest
-revision in a repository doesn't have any children, but a repository
-can contain more than one head.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{tour-merge-pull}
-  \caption{Repository contents after pulling from \dirname{my-hello} into
-    \dirname{my-new-hello}}
-  \label{fig:tour-merge:pull}
-\end{figure}
-
-In figure~\ref{fig:tour-merge:pull}, you can see the effect of the
-pull from \dirname{my-hello} into \dirname{my-new-hello}.  The history
-that was already present in \dirname{my-new-hello} is untouched, but a
-new revision has been added.  By referring to
-figure~\ref{fig:tour-merge:sep-repos}, we can see that the
-\emph{changeset ID} remains the same in the new repository, but the
-\emph{revision number} has changed.  (This, incidentally, is a fine
-example of why it's not safe to use revision numbers when discussing
-changesets.)  We can view the heads in a repository using the
-\hgcmd{heads} command.
-\interaction{tour.merge.heads}
-
-\subsection{Performing the merge}
-
-What happens if we try to use the normal \hgcmd{update} command to
-update to the new tip?
-\interaction{tour.merge.update}
-Mercurial is telling us that the \hgcmd{update} command won't do a
-merge; it won't update the working directory when it thinks we might
-be wanting to do a merge, unless we force it to do so.  Instead, we
-use the \hgcmd{merge} command to merge the two heads.
-\interaction{tour.merge.merge}
-
-\begin{figure}[ht]
-  \centering
-  \grafix{tour-merge-merge}
-  \caption{Working directory and repository during merge, and
-    following commit}
-  \label{fig:tour-merge:merge}
-\end{figure}
-
-This updates the working directory so that it contains changes from
-\emph{both} heads, which is reflected in both the output of
-\hgcmd{parents} and the contents of \filename{hello.c}.
-\interaction{tour.merge.parents}
-
-\subsection{Committing the results of the merge}
-
-Whenever we've done a merge, \hgcmd{parents} will display two parents
-until we \hgcmd{commit} the results of the merge.
-\interaction{tour.merge.commit}
-We now have a new tip revision; notice that it has \emph{both} of
-our former heads as its parents.  These are the same revisions that
-were previously displayed by \hgcmd{parents}.
-\interaction{tour.merge.tip}
-In figure~\ref{fig:tour-merge:merge}, you can see a representation of
-what happens to the working directory during the merge, and how this
-affects the repository when the commit happens.  During the merge, the
-working directory has two parent changesets, and these become the
-parents of the new changeset.
-
-\section{Merging conflicting changes}
-
-Most merges are simple affairs, but sometimes you'll find yourself
-merging changes where each modifies the same portions of the same
-files.  Unless both modifications are identical, this results in a
-\emph{conflict}, where you have to decide how to reconcile the
-different changes into something coherent.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{tour-merge-conflict}
-  \caption{Conflicting changes to a document}
-  \label{fig:tour-merge:conflict}
-\end{figure}
-
-Figure~\ref{fig:tour-merge:conflict} illustrates an instance of two
-conflicting changes to a document.  We started with a single version
-of the file; then we made some changes; while someone else made
-different changes to the same text.  Our task in resolving the
-conflicting changes is to decide what the file should look like.
-
-Mercurial doesn't have a built-in facility for handling conflicts.
-Instead, it runs an external program called \command{hgmerge}.  This
-is a shell script that is bundled with Mercurial; you can change it to
-behave however you please.  What it does by default is try to find one
-of several different merging tools that are likely to be installed on
-your system.  It first tries a few fully automatic merging tools; if
-these don't succeed (because the resolution process requires human
-guidance) or aren't present, the script tries a few different
-graphical merging tools.
-
-It's also possible to get Mercurial to run another program or script
-instead of \command{hgmerge}, by setting the \envar{HGMERGE}
-environment variable to the name of your preferred program.
-
-\subsection{Using a graphical merge tool}
-
-My preferred graphical merge tool is \command{kdiff3}, which I'll use
-to describe the features that are common to graphical file merging
-tools.  You can see a screenshot of \command{kdiff3} in action in
-figure~\ref{fig:tour-merge:kdiff3}.  The kind of merge it is
-performing is called a \emph{three-way merge}, because there are three
-different versions of the file of interest to us.  The tool thus
-splits the upper portion of the window into three panes:
-\begin{itemize}
-\item At the left is the \emph{base} version of the file, i.e.~the
-  most recent version from which the two versions we're trying to
-  merge are descended.
-\item In the middle is ``our'' version of the file, with the contents
-  that we modified.
-\item On the right is ``their'' version of the file, the one that
-  from the changeset that we're trying to merge with.
-\end{itemize}
-In the pane below these is the current \emph{result} of the merge.
-Our task is to replace all of the red text, which indicates unresolved
-conflicts, with some sensible merger of the ``ours'' and ``theirs''
-versions of the file.
-
-All four of these panes are \emph{locked together}; if we scroll
-vertically or horizontally in any of them, the others are updated to
-display the corresponding sections of their respective files.
-
-\begin{figure}[ht]
-  \centering
-  \grafix{kdiff3}
-  \caption{Using \command{kdiff3} to merge versions of a file}
-  \label{fig:tour-merge:kdiff3}
-\end{figure}
-
-For each conflicting portion of the file, we can choose to resolve
-the conflict using some combination of text from the base version,
-ours, or theirs.  We can also manually edit the merged file at any
-time, in case we need to make further modifications.
-
-There are \emph{many} file merging tools available, too many to cover
-here.  They vary in which platforms they are available for, and in
-their particular strengths and weaknesses.  Most are tuned for merging
-files containing plain text, while a few are aimed at specialised file
-formats (generally XML).
-
-\subsection{A worked example}
-
-In this example, we will reproduce the file modification history of
-figure~\ref{fig:tour-merge:conflict} above.  Let's begin by creating a
-repository with a base version of our document.
-\interaction{tour-merge-conflict.wife}
-We'll clone the repository and make a change to the file.
-\interaction{tour-merge-conflict.cousin}
-And another clone, to simulate someone else making a change to the
-file.  (This hints at the idea that it's not all that unusual to merge
-with yourself when you isolate tasks in separate repositories, and
-indeed to find and resolve conflicts while doing so.)
-\interaction{tour-merge-conflict.son}
-Having created two different versions of the file, we'll set up an
-environment suitable for running our merge.
-\interaction{tour-merge-conflict.pull}
-
-In this example, I won't use Mercurial's normal \command{hgmerge}
-program to do the merge, because it would drop my nice automated
-example-running tool into a graphical user interface.  Instead, I'll
-set \envar{HGMERGE} to tell Mercurial to use the non-interactive
-\command{merge} command.  This is bundled with many Unix-like systems.
-If you're following this example on your computer, don't bother
-setting \envar{HGMERGE}.
-\interaction{tour-merge-conflict.merge}
-Because \command{merge} can't resolve the conflicting changes, it
-leaves \emph{merge markers} inside the file that has conflicts,
-indicating which lines have conflicts, and whether they came from our
-version of the file or theirs.
-
-Mercurial can tell from the way \command{merge} exits that it wasn't
-able to merge successfully, so it tells us what commands we'll need to
-run if we want to redo the merging operation.  This could be useful
-if, for example, we were running a graphical merge tool and quit
-because we were confused or realised we had made a mistake.
-
-If automatic or manual merges fail, there's nothing to prevent us from
-``fixing up'' the affected files ourselves, and committing the results
-of our merge:
-\interaction{tour-merge-conflict.commit}
-
-\section{Simplifying the pull-merge-commit sequence}
-\label{sec:tour-merge:fetch}
-
-The process of merging changes as outlined above is straightforward,
-but requires running three commands in sequence.
-\begin{codesample2}
-  hg pull
-  hg merge
-  hg commit -m 'Merged remote changes'
-\end{codesample2}
-In the case of the final commit, you also need to enter a commit
-message, which is almost always going to be a piece of uninteresting
-``boilerplate'' text.
-
-It would be nice to reduce the number of steps needed, if this were
-possible.  Indeed, Mercurial is distributed with an extension called
-\hgext{fetch} that does just this.
-
-Mercurial provides a flexible extension mechanism that lets people
-extend its functionality, while keeping the core of Mercurial small
-and easy to deal with.  Some extensions add new commands that you can
-use from the command line, while others work ``behind the scenes,''
-for example adding capabilities to the server.
-
-The \hgext{fetch} extension adds a new command called, not
-surprisingly, \hgcmd{fetch}.  This extension acts as a combination of
-\hgcmd{pull}, \hgcmd{update} and \hgcmd{merge}.  It begins by pulling
-changes from another repository into the current repository.  If it
-finds that the changes added a new head to the repository, it begins a
-merge, then commits the result of the merge with an
-automatically-generated commit message.  If no new heads were added,
-it updates the working directory to the new tip changeset.
-
-Enabling the \hgext{fetch} extension is easy.  Edit your
-\sfilename{.hgrc}, and either go to the \rcsection{extensions} section
-or create an \rcsection{extensions} section.  Then add a line that
-simply reads ``\Verb+fetch +''.
-\begin{codesample2}
-  [extensions]
-  fetch =
-\end{codesample2}
-(Normally, on the right-hand side of the ``\texttt{=}'' would appear
-the location of the extension, but since the \hgext{fetch} extension
-is in the standard distribution, Mercurial knows where to search for
-it.)
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- a/en/undo.tex	Wed Jan 21 14:16:38 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,766 +0,0 @@
-\chapter{Finding and fixing your mistakes}
-\label{chap:undo}
-
-To err might be human, but to really handle the consequences well
-takes a top-notch revision control system.  In this chapter, we'll
-discuss some of the techniques you can use when you find that a
-problem has crept into your project.  Mercurial has some highly
-capable features that will help you to isolate the sources of
-problems, and to handle them appropriately.
-
-\section{Erasing local history}
-
-\subsection{The accidental commit}
-
-I have the occasional but persistent problem of typing rather more
-quickly than I can think, which sometimes results in me committing a
-changeset that is either incomplete or plain wrong.  In my case, the
-usual kind of incomplete changeset is one in which I've created a new
-source file, but forgotten to \hgcmd{add} it.  A ``plain wrong''
-changeset is not as common, but no less annoying.
-
-\subsection{Rolling back a transaction}
-\label{sec:undo:rollback}
-
-In section~\ref{sec:concepts:txn}, I mentioned that Mercurial treats
-each modification of a repository as a \emph{transaction}.  Every time
-you commit a changeset or pull changes from another repository,
-Mercurial remembers what you did.  You can undo, or \emph{roll back},
-exactly one of these actions using the \hgcmd{rollback} command.  (See
-section~\ref{sec:undo:rollback-after-push} for an important caveat
-about the use of this command.)
-
-Here's a mistake that I often find myself making: committing a change
-in which I've created a new file, but forgotten to \hgcmd{add} it.
-\interaction{rollback.commit}
-Looking at the output of \hgcmd{status} after the commit immediately
-confirms the error.
-\interaction{rollback.status}
-The commit captured the changes to the file \filename{a}, but not the
-new file \filename{b}.  If I were to push this changeset to a
-repository that I shared with a colleague, the chances are high that
-something in \filename{a} would refer to \filename{b}, which would not
-be present in their repository when they pulled my changes.  I would
-thus become the object of some indignation.
-
-However, luck is with me---I've caught my error before I pushed the
-changeset.  I use the \hgcmd{rollback} command, and Mercurial makes
-that last changeset vanish.
-\interaction{rollback.rollback}
-Notice that the changeset is no longer present in the repository's
-history, and the working directory once again thinks that the file
-\filename{a} is modified.  The commit and rollback have left the
-working directory exactly as it was prior to the commit; the changeset
-has been completely erased.  I can now safely \hgcmd{add} the file
-\filename{b}, and rerun my commit.
-\interaction{rollback.add}
-
-\subsection{The erroneous pull}
-
-It's common practice with Mercurial to maintain separate development
-branches of a project in different repositories.  Your development
-team might have one shared repository for your project's ``0.9''
-release, and another, containing different changes, for the ``1.0''
-release.
-
-Given this, you can imagine that the consequences could be messy if
-you had a local ``0.9'' repository, and accidentally pulled changes
-from the shared ``1.0'' repository into it.  At worst, you could be
-paying insufficient attention, and push those changes into the shared
-``0.9'' tree, confusing your entire team (but don't worry, we'll
-return to this horror scenario later).  However, it's more likely that
-you'll notice immediately, because Mercurial will display the URL it's
-pulling from, or you will see it pull a suspiciously large number of
-changes into the repository.
-
-The \hgcmd{rollback} command will work nicely to expunge all of the
-changesets that you just pulled.  Mercurial groups all changes from
-one \hgcmd{pull} into a single transaction, so one \hgcmd{rollback} is
-all you need to undo this mistake.
-
-\subsection{Rolling back is useless once you've pushed}
-\label{sec:undo:rollback-after-push}
-
-The value of the \hgcmd{rollback} command drops to zero once you've
-pushed your changes to another repository.  Rolling back a change
-makes it disappear entirely, but \emph{only} in the repository in
-which you perform the \hgcmd{rollback}.  Because a rollback eliminates
-history, there's no way for the disappearance of a change to propagate
-between repositories.
-
-If you've pushed a change to another repository---particularly if it's
-a shared repository---it has essentially ``escaped into the wild,''
-and you'll have to recover from your mistake in a different way.  What
-will happen if you push a changeset somewhere, then roll it back, then
-pull from the repository you pushed to, is that the changeset will
-reappear in your repository.
-
-(If you absolutely know for sure that the change you want to roll back
-is the most recent change in the repository that you pushed to,
-\emph{and} you know that nobody else could have pulled it from that
-repository, you can roll back the changeset there, too, but you really
-should really not rely on this working reliably.  If you do this,
-sooner or later a change really will make it into a repository that
-you don't directly control (or have forgotten about), and come back to
-bite you.)
-
-\subsection{You can only roll back once}
-
-Mercurial stores exactly one transaction in its transaction log; that
-transaction is the most recent one that occurred in the repository.
-This means that you can only roll back one transaction.  If you expect
-to be able to roll back one transaction, then its predecessor, this is
-not the behaviour you will get.
-\interaction{rollback.twice}
-Once you've rolled back one transaction in a repository, you can't
-roll back again in that repository until you perform another commit or
-pull.
-
-\section{Reverting the mistaken change}
-
-If you make a modification to a file, and decide that you really
-didn't want to change the file at all, and you haven't yet committed
-your changes, the \hgcmd{revert} command is the one you'll need.  It
-looks at the changeset that's the parent of the working directory, and
-restores the contents of the file to their state as of that changeset.
-(That's a long-winded way of saying that, in the normal case, it
-undoes your modifications.)
-
-Let's illustrate how the \hgcmd{revert} command works with yet another
-small example.  We'll begin by modifying a file that Mercurial is
-already tracking.
-\interaction{daily.revert.modify}
-If we don't want that change, we can simply \hgcmd{revert} the file.
-\interaction{daily.revert.unmodify}
-The \hgcmd{revert} command provides us with an extra degree of safety
-by saving our modified file with a \filename{.orig} extension.
-\interaction{daily.revert.status}
-
-Here is a summary of the cases that the \hgcmd{revert} command can
-deal with.  We will describe each of these in more detail in the
-section that follows.
-\begin{itemize}
-\item If you modify a file, it will restore the file to its unmodified
-  state.
-\item If you \hgcmd{add} a file, it will undo the ``added'' state of
-  the file, but leave the file itself untouched.
-\item If you delete a file without telling Mercurial, it will restore
-  the file to its unmodified contents.
-\item If you use the \hgcmd{remove} command to remove a file, it will
-  undo the ``removed'' state of the file, and restore the file to its
-  unmodified contents.
-\end{itemize}
-
-\subsection{File management errors}
-\label{sec:undo:mgmt}
-
-The \hgcmd{revert} command is useful for more than just modified
-files.  It lets you reverse the results of all of Mercurial's file
-management commands---\hgcmd{add}, \hgcmd{remove}, and so on.
-
-If you \hgcmd{add} a file, then decide that in fact you don't want
-Mercurial to track it, use \hgcmd{revert} to undo the add.  Don't
-worry; Mercurial will not modify the file in any way.  It will just
-``unmark'' the file.
-\interaction{daily.revert.add}
-
-Similarly, if you ask Mercurial to \hgcmd{remove} a file, you can use
-\hgcmd{revert} to restore it to the contents it had as of the parent
-of the working directory.
-\interaction{daily.revert.remove}
-This works just as well for a file that you deleted by hand, without
-telling Mercurial (recall that in Mercurial terminology, this kind of
-file is called ``missing'').
-\interaction{daily.revert.missing}
-
-If you revert a \hgcmd{copy}, the copied-to file remains in your
-working directory afterwards, untracked.  Since a copy doesn't affect
-the copied-from file in any way, Mercurial doesn't do anything with
-the copied-from file.
-\interaction{daily.revert.copy}
-
-\subsubsection{A slightly special case: reverting a rename}
-
-If you \hgcmd{rename} a file, there is one small detail that
-you should remember.  When you \hgcmd{revert} a rename, it's not
-enough to provide the name of the renamed-to file, as you can see
-here.
-\interaction{daily.revert.rename}
-As you can see from the output of \hgcmd{status}, the renamed-to file
-is no longer identified as added, but the renamed-\emph{from} file is
-still removed!  This is counter-intuitive (at least to me), but at
-least it's easy to deal with.
-\interaction{daily.revert.rename-orig}
-So remember, to revert a \hgcmd{rename}, you must provide \emph{both}
-the source and destination names.  
-
-% TODO: the output doesn't look like it will be removed!
-
-(By the way, if you rename a file, then modify the renamed-to file,
-then revert both components of the rename, when Mercurial restores the
-file that was removed as part of the rename, it will be unmodified.
-If you need the modifications in the renamed-to file to show up in the
-renamed-from file, don't forget to copy them over.)
-
-These fiddly aspects of reverting a rename arguably constitute a small
-bug in Mercurial.
-
-\section{Dealing with committed changes}
-
-Consider a case where you have committed a change $a$, and another
-change $b$ on top of it; you then realise that change $a$ was
-incorrect.  Mercurial lets you ``back out'' an entire changeset
-automatically, and building blocks that let you reverse part of a
-changeset by hand.
-
-Before you read this section, here's something to keep in mind: the
-\hgcmd{backout} command undoes changes by \emph{adding} history, not
-by modifying or erasing it.  It's the right tool to use if you're
-fixing bugs, but not if you're trying to undo some change that has
-catastrophic consequences.  To deal with those, see
-section~\ref{sec:undo:aaaiiieee}.
-
-\subsection{Backing out a changeset}
-
-The \hgcmd{backout} command lets you ``undo'' the effects of an entire
-changeset in an automated fashion.  Because Mercurial's history is
-immutable, this command \emph{does not} get rid of the changeset you
-want to undo.  Instead, it creates a new changeset that
-\emph{reverses} the effect of the to-be-undone changeset.
-
-The operation of the \hgcmd{backout} command is a little intricate, so
-let's illustrate it with some examples.  First, we'll create a
-repository with some simple changes.
-\interaction{backout.init}
-
-The \hgcmd{backout} command takes a single changeset ID as its
-argument; this is the changeset to back out.  Normally,
-\hgcmd{backout} will drop you into a text editor to write a commit
-message, so you can record why you're backing the change out.  In this
-example, we provide a commit message on the command line using the
-\hgopt{backout}{-m} option.
-
-\subsection{Backing out the tip changeset}
-
-We're going to start by backing out the last changeset we committed.
-\interaction{backout.simple}
-You can see that the second line from \filename{myfile} is no longer
-present.  Taking a look at the output of \hgcmd{log} gives us an idea
-of what the \hgcmd{backout} command has done.
-\interaction{backout.simple.log}
-Notice that the new changeset that \hgcmd{backout} has created is a
-child of the changeset we backed out.  It's easier to see this in
-figure~\ref{fig:undo:backout}, which presents a graphical view of the
-change history.  As you can see, the history is nice and linear.
-
-\begin{figure}[htb]
-  \centering
-  \grafix{undo-simple}
-  \caption{Backing out a change using the \hgcmd{backout} command}
-  \label{fig:undo:backout}
-\end{figure}
-
-\subsection{Backing out a non-tip change}
-
-If you want to back out a change other than the last one you
-committed, pass the \hgopt{backout}{--merge} option to the
-\hgcmd{backout} command.
-\interaction{backout.non-tip.clone}
-This makes backing out any changeset a ``one-shot'' operation that's
-usually simple and fast.
-\interaction{backout.non-tip.backout}
-
-If you take a look at the contents of \filename{myfile} after the
-backout finishes, you'll see that the first and third changes are
-present, but not the second.
-\interaction{backout.non-tip.cat}
-
-As the graphical history in figure~\ref{fig:undo:backout-non-tip}
-illustrates, Mercurial actually commits \emph{two} changes in this
-kind of situation (the box-shaped nodes are the ones that Mercurial
-commits automatically).  Before Mercurial begins the backout process,
-it first remembers what the current parent of the working directory
-is.  It then backs out the target changeset, and commits that as a
-changeset.  Finally, it merges back to the previous parent of the
-working directory, and commits the result of the merge.
-
-% TODO: to me it looks like mercurial doesn't commit the second merge automatically!
-
-\begin{figure}[htb]
-  \centering
-  \grafix{undo-non-tip}
-  \caption{Automated backout of a non-tip change using the \hgcmd{backout} command}
-  \label{fig:undo:backout-non-tip}
-\end{figure}
-
-The result is that you end up ``back where you were'', only with some
-extra history that undoes the effect of the changeset you wanted to
-back out.
-
-\subsubsection{Always use the \hgopt{backout}{--merge} option}
-
-In fact, since the \hgopt{backout}{--merge} option will do the ``right
-thing'' whether or not the changeset you're backing out is the tip
-(i.e.~it won't try to merge if it's backing out the tip, since there's
-no need), you should \emph{always} use this option when you run the
-\hgcmd{backout} command.
-
-\subsection{Gaining more control of the backout process}
-
-While I've recommended that you always use the
-\hgopt{backout}{--merge} option when backing out a change, the
-\hgcmd{backout} command lets you decide how to merge a backout
-changeset.  Taking control of the backout process by hand is something
-you will rarely need to do, but it can be useful to understand what
-the \hgcmd{backout} command is doing for you automatically.  To
-illustrate this, let's clone our first repository, but omit the
-backout change that it contains.
-
-\interaction{backout.manual.clone}
-As with our earlier example, We'll commit a third changeset, then back
-out its parent, and see what happens.
-\interaction{backout.manual.backout} 
-Our new changeset is again a descendant of the changeset we backout
-out; it's thus a new head, \emph{not} a descendant of the changeset
-that was the tip.  The \hgcmd{backout} command was quite explicit in
-telling us this.
-\interaction{backout.manual.log}
-
-Again, it's easier to see what has happened by looking at a graph of
-the revision history, in figure~\ref{fig:undo:backout-manual}.  This
-makes it clear that when we use \hgcmd{backout} to back out a change
-other than the tip, Mercurial adds a new head to the repository (the
-change it committed is box-shaped).
-
-\begin{figure}[htb]
-  \centering
-  \grafix{undo-manual}
-  \caption{Backing out a change using the \hgcmd{backout} command}
-  \label{fig:undo:backout-manual}
-\end{figure}
-
-After the \hgcmd{backout} command has completed, it leaves the new
-``backout'' changeset as the parent of the working directory.
-\interaction{backout.manual.parents}
-Now we have two isolated sets of changes.
-\interaction{backout.manual.heads}
-
-Let's think about what we expect to see as the contents of
-\filename{myfile} now.  The first change should be present, because
-we've never backed it out.  The second change should be missing, as
-that's the change we backed out.  Since the history graph shows the
-third change as a separate head, we \emph{don't} expect to see the
-third change present in \filename{myfile}.
-\interaction{backout.manual.cat}
-To get the third change back into the file, we just do a normal merge
-of our two heads.
-\interaction{backout.manual.merge}
-Afterwards, the graphical history of our repository looks like
-figure~\ref{fig:undo:backout-manual-merge}.
-
-\begin{figure}[htb]
-  \centering
-  \grafix{undo-manual-merge}
-  \caption{Manually merging a backout change}
-  \label{fig:undo:backout-manual-merge}
-\end{figure}
-
-\subsection{Why \hgcmd{backout} works as it does}
-
-Here's a brief description of how the \hgcmd{backout} command works.
-\begin{enumerate}
-\item It ensures that the working directory is ``clean'', i.e.~that
-  the output of \hgcmd{status} would be empty.
-\item It remembers the current parent of the working directory.  Let's
-  call this changeset \texttt{orig}
-\item It does the equivalent of a \hgcmd{update} to sync the working
-  directory to the changeset you want to back out.  Let's call this
-  changeset \texttt{backout}
-\item It finds the parent of that changeset.  Let's call that
-  changeset \texttt{parent}.
-\item For each file that the \texttt{backout} changeset affected, it
-  does the equivalent of a \hgcmdargs{revert}{-r parent} on that file,
-  to restore it to the contents it had before that changeset was
-  committed.
-\item It commits the result as a new changeset.  This changeset has
-  \texttt{backout} as its parent.
-\item If you specify \hgopt{backout}{--merge} on the command line, it
-  merges with \texttt{orig}, and commits the result of the merge.
-\end{enumerate}
-
-An alternative way to implement the \hgcmd{backout} command would be
-to \hgcmd{export} the to-be-backed-out changeset as a diff, then use
-the \cmdopt{patch}{--reverse} option to the \command{patch} command to
-reverse the effect of the change without fiddling with the working
-directory.  This sounds much simpler, but it would not work nearly as
-well.
-
-The reason that \hgcmd{backout} does an update, a commit, a merge, and
-another commit is to give the merge machinery the best chance to do a
-good job when dealing with all the changes \emph{between} the change
-you're backing out and the current tip.  
-
-If you're backing out a changeset that's~100 revisions back in your
-project's history, the chances that the \command{patch} command will
-be able to apply a reverse diff cleanly are not good, because
-intervening changes are likely to have ``broken the context'' that
-\command{patch} uses to determine whether it can apply a patch (if
-this sounds like gibberish, see \ref{sec:mq:patch} for a
-discussion of the \command{patch} command).  Also, Mercurial's merge
-machinery will handle files and directories being renamed, permission
-changes, and modifications to binary files, none of which
-\command{patch} can deal with.
-
-\section{Changes that should never have been}
-\label{sec:undo:aaaiiieee}
-
-Most of the time, the \hgcmd{backout} command is exactly what you need
-if you want to undo the effects of a change.  It leaves a permanent
-record of exactly what you did, both when committing the original
-changeset and when you cleaned up after it.
-
-On rare occasions, though, you may find that you've committed a change
-that really should not be present in the repository at all.  For
-example, it would be very unusual, and usually considered a mistake,
-to commit a software project's object files as well as its source
-files.  Object files have almost no intrinsic value, and they're
-\emph{big}, so they increase the size of the repository and the amount
-of time it takes to clone or pull changes.
-
-Before I discuss the options that you have if you commit a ``brown
-paper bag'' change (the kind that's so bad that you want to pull a
-brown paper bag over your head), let me first discuss some approaches
-that probably won't work.
-
-Since Mercurial treats history as accumulative---every change builds
-on top of all changes that preceded it---you generally can't just make
-disastrous changes disappear.  The one exception is when you've just
-committed a change, and it hasn't been pushed or pulled into another
-repository.  That's when you can safely use the \hgcmd{rollback}
-command, as I detailed in section~\ref{sec:undo:rollback}.
-
-After you've pushed a bad change to another repository, you
-\emph{could} still use \hgcmd{rollback} to make your local copy of the
-change disappear, but it won't have the consequences you want.  The
-change will still be present in the remote repository, so it will
-reappear in your local repository the next time you pull.
-
-If a situation like this arises, and you know which repositories your
-bad change has propagated into, you can \emph{try} to get rid of the
-changeefrom \emph{every} one of those repositories.  This is, of
-course, not a satisfactory solution: if you miss even a single
-repository while you're expunging, the change is still ``in the
-wild'', and could propagate further.
-
-If you've committed one or more changes \emph{after} the change that
-you'd like to see disappear, your options are further reduced.
-Mercurial doesn't provide a way to ``punch a hole'' in history,
-leaving changesets intact.
-
-XXX This needs filling out.  The \texttt{hg-replay} script in the
-\texttt{examples} directory works, but doesn't handle merge
-changesets.  Kind of an important omission.
-
-\subsection{Protect yourself from ``escaped'' changes}
-
-If you've committed some changes to your local repository and they've
-been pushed or pulled somewhere else, this isn't necessarily a
-disaster.  You can protect yourself ahead of time against some classes
-of bad changeset.  This is particularly easy if your team usually
-pulls changes from a central repository.
-
-By configuring some hooks on that repository to validate incoming
-changesets (see chapter~\ref{chap:hook}), you can automatically
-prevent some kinds of bad changeset from being pushed to the central
-repository at all.  With such a configuration in place, some kinds of
-bad changeset will naturally tend to ``die out'' because they can't
-propagate into the central repository.  Better yet, this happens
-without any need for explicit intervention.
-
-For instance, an incoming change hook that verifies that a changeset
-will actually compile can prevent people from inadvertantly ``breaking
-the build''.
-
-\section{Finding the source of a bug}
-\label{sec:undo:bisect}
-
-While it's all very well to be able to back out a changeset that
-introduced a bug, this requires that you know which changeset to back
-out.  Mercurial provides an invaluable command, called
-\hgcmd{bisect}, that helps you to automate this process and accomplish
-it very efficiently.
-
-The idea behind the \hgcmd{bisect} command is that a changeset has
-introduced some change of behaviour that you can identify with a
-simple binary test.  You don't know which piece of code introduced the
-change, but you know how to test for the presence of the bug.  The
-\hgcmd{bisect} command uses your test to direct its search for the
-changeset that introduced the code that caused the bug.
-
-Here are a few scenarios to help you understand how you might apply
-this command.
-\begin{itemize}
-\item The most recent version of your software has a bug that you
-  remember wasn't present a few weeks ago, but you don't know when it
-  was introduced.  Here, your binary test checks for the presence of
-  that bug.
-\item You fixed a bug in a rush, and now it's time to close the entry
-  in your team's bug database.  The bug database requires a changeset
-  ID when you close an entry, but you don't remember which changeset
-  you fixed the bug in.  Once again, your binary test checks for the
-  presence of the bug.
-\item Your software works correctly, but runs~15\% slower than the
-  last time you measured it.  You want to know which changeset
-  introduced the performance regression.  In this case, your binary
-  test measures the performance of your software, to see whether it's
-  ``fast'' or ``slow''.
-\item The sizes of the components of your project that you ship
-  exploded recently, and you suspect that something changed in the way
-  you build your project.
-\end{itemize}
-
-From these examples, it should be clear that the \hgcmd{bisect}
-command is not useful only for finding the sources of bugs.  You can
-use it to find any ``emergent property'' of a repository (anything
-that you can't find from a simple text search of the files in the
-tree) for which you can write a binary test.
-
-We'll introduce a little bit of terminology here, just to make it
-clear which parts of the search process are your responsibility, and
-which are Mercurial's.  A \emph{test} is something that \emph{you} run
-when \hgcmd{bisect} chooses a changeset.  A \emph{probe} is what
-\hgcmd{bisect} runs to tell whether a revision is good.  Finally,
-we'll use the word ``bisect'', as both a noun and a verb, to stand in
-for the phrase ``search using the \hgcmd{bisect} command.
-
-One simple way to automate the searching process would be simply to
-probe every changeset.  However, this scales poorly.  If it took ten
-minutes to test a single changeset, and you had 10,000 changesets in
-your repository, the exhaustive approach would take on average~35
-\emph{days} to find the changeset that introduced a bug.  Even if you
-knew that the bug was introduced by one of the last 500 changesets,
-and limited your search to those, you'd still be looking at over 40
-hours to find the changeset that introduced your bug.
-
-What the \hgcmd{bisect} command does is use its knowledge of the
-``shape'' of your project's revision history to perform a search in
-time proportional to the \emph{logarithm} of the number of changesets
-to check (the kind of search it performs is called a dichotomic
-search).  With this approach, searching through 10,000 changesets will
-take less than three hours, even at ten minutes per test (the search
-will require about 14 tests).  Limit your search to the last hundred
-changesets, and it will take only about an hour (roughly seven tests).
-
-The \hgcmd{bisect} command is aware of the ``branchy'' nature of a
-Mercurial project's revision history, so it has no problems dealing
-with branches, merges, or multiple heads in a repoository.  It can
-prune entire branches of history with a single probe, which is how it
-operates so efficiently.
-
-\subsection{Using the \hgcmd{bisect} command}
-
-Here's an example of \hgcmd{bisect} in action.
-
-\begin{note}
-  In versions 0.9.5 and earlier of Mercurial, \hgcmd{bisect} was not a
-  core command: it was distributed with Mercurial as an extension.
-  This section describes the built-in command, not the old extension.
-\end{note}
-
-Now let's create a repository, so that we can try out the
-\hgcmd{bisect} command in isolation.
-We'll simulate a project that has a bug in it in a simple-minded way:
-create trivial changes in a loop, and nominate one specific change
-that will have the ``bug''.  This loop creates 35 changesets, each
-adding a single file to the repository.  We'll represent our ``bug''
-with a file that contains the text ``i have a gub''.
-\interaction{bisect.commits}
-
-The next thing that we'd like to do is figure out how to use the
-\hgcmd{bisect} command.  We can use Mercurial's normal built-in help
-mechanism for this.
-\interaction{bisect.help}
-
-The \hgcmd{bisect} command works in steps.  Each step proceeds as follows.
-\begin{enumerate}
-\item You run your binary test.
-  \begin{itemize}
-  \item If the test succeeded, you tell \hgcmd{bisect} by running the
-    \hgcmdargs{bisect}{good} command.
-  \item If it failed, run the \hgcmdargs{bisect}{--bad} command.
-  \end{itemize}
-\item The command uses your information to decide which changeset to
-  test next.
-\item It updates the working directory to that changeset, and the
-  process begins again.
-\end{enumerate}
-The process ends when \hgcmd{bisect} identifies a unique changeset
-that marks the point where your test transitioned from ``succeeding''
-to ``failing''.
-
-To start the search, we must run the \hgcmdargs{bisect}{--reset} command.
-\interaction{bisect.search.init}
-
-In our case, the binary test we use is simple: we check to see if any
-file in the repository contains the string ``i have a gub''.  If it
-does, this changeset contains the change that ``caused the bug''.  By
-convention, a changeset that has the property we're searching for is
-``bad'', while one that doesn't is ``good''.
-
-Most of the time, the revision to which the working directory is
-synced (usually the tip) already exhibits the problem introduced by
-the buggy change, so we'll mark it as ``bad''.
-\interaction{bisect.search.bad-init}
-
-Our next task is to nominate a changeset that we know \emph{doesn't}
-have the bug; the \hgcmd{bisect} command will ``bracket'' its search
-between the first pair of good and bad changesets.  In our case, we
-know that revision~10 didn't have the bug.  (I'll have more words
-about choosing the first ``good'' changeset later.)
-\interaction{bisect.search.good-init}
-
-Notice that this command printed some output.
-\begin{itemize}
-\item It told us how many changesets it must consider before it can
-  identify the one that introduced the bug, and how many tests that
-  will require.
-\item It updated the working directory to the next changeset to test,
-  and told us which changeset it's testing.
-\end{itemize}
-
-We now run our test in the working directory.  We use the
-\command{grep} command to see if our ``bad'' file is present in the
-working directory.  If it is, this revision is bad; if not, this
-revision is good.
-\interaction{bisect.search.step1}
-
-This test looks like a perfect candidate for automation, so let's turn
-it into a shell function.
-\interaction{bisect.search.mytest}
-We can now run an entire test step with a single command,
-\texttt{mytest}.
-\interaction{bisect.search.step2}
-A few more invocations of our canned test step command, and we're
-done.
-\interaction{bisect.search.rest}
-
-Even though we had~40 changesets to search through, the \hgcmd{bisect}
-command let us find the changeset that introduced our ``bug'' with
-only five tests.  Because the number of tests that the \hgcmd{bisect}
-command performs grows logarithmically with the number of changesets to
-search, the advantage that it has over the ``brute force'' search
-approach increases with every changeset you add.
-
-\subsection{Cleaning up after your search}
-
-When you're finished using the \hgcmd{bisect} command in a
-repository, you can use the \hgcmdargs{bisect}{reset} command to drop
-the information it was using to drive your search.  The command
-doesn't use much space, so it doesn't matter if you forget to run this
-command.  However, \hgcmd{bisect} won't let you start a new search in
-that repository until you do a \hgcmdargs{bisect}{reset}.
-\interaction{bisect.search.reset}
-
-\section{Tips for finding bugs effectively}
-
-\subsection{Give consistent input}
-
-The \hgcmd{bisect} command requires that you correctly report the
-result of every test you perform.  If you tell it that a test failed
-when it really succeeded, it \emph{might} be able to detect the
-inconsistency.  If it can identify an inconsistency in your reports,
-it will tell you that a particular changeset is both good and bad.
-However, it can't do this perfectly; it's about as likely to report
-the wrong changeset as the source of the bug.
-
-\subsection{Automate as much as possible}
-
-When I started using the \hgcmd{bisect} command, I tried a few times
-to run my tests by hand, on the command line.  This is an approach
-that I, at least, am not suited to.  After a few tries, I found that I
-was making enough mistakes that I was having to restart my searches
-several times before finally getting correct results.
-
-My initial problems with driving the \hgcmd{bisect} command by hand
-occurred even with simple searches on small repositories; if the
-problem you're looking for is more subtle, or the number of tests that
-\hgcmd{bisect} must perform increases, the likelihood of operator
-error ruining the search is much higher.  Once I started automating my
-tests, I had much better results.
-
-The key to automated testing is twofold:
-\begin{itemize}
-\item always test for the same symptom, and
-\item always feed consistent input to the \hgcmd{bisect} command.
-\end{itemize}
-In my tutorial example above, the \command{grep} command tests for the
-symptom, and the \texttt{if} statement takes the result of this check
-and ensures that we always feed the same input to the \hgcmd{bisect}
-command.  The \texttt{mytest} function marries these together in a
-reproducible way, so that every test is uniform and consistent.
-
-\subsection{Check your results}
-
-Because the output of a \hgcmd{bisect} search is only as good as the
-input you give it, don't take the changeset it reports as the
-absolute truth.  A simple way to cross-check its report is to manually
-run your test at each of the following changesets:
-\begin{itemize}
-\item The changeset that it reports as the first bad revision.  Your
-  test should still report this as bad.
-\item The parent of that changeset (either parent, if it's a merge).
-  Your test should report this changeset as good.
-\item A child of that changeset.  Your test should report this
-  changeset as bad.
-\end{itemize}
-
-\subsection{Beware interference between bugs}
-
-It's possible that your search for one bug could be disrupted by the
-presence of another.  For example, let's say your software crashes at
-revision 100, and worked correctly at revision 50.  Unknown to you,
-someone else introduced a different crashing bug at revision 60, and
-fixed it at revision 80.  This could distort your results in one of
-several ways.
-
-It is possible that this other bug completely ``masks'' yours, which
-is to say that it occurs before your bug has a chance to manifest
-itself.  If you can't avoid that other bug (for example, it prevents
-your project from building), and so can't tell whether your bug is
-present in a particular changeset, the \hgcmd{bisect} command cannot
-help you directly.  Instead, you can mark a changeset as untested by
-running \hgcmdargs{bisect}{--skip}.
-
-A different problem could arise if your test for a bug's presence is
-not specific enough.  If you check for ``my program crashes'', then
-both your crashing bug and an unrelated crashing bug that masks it
-will look like the same thing, and mislead \hgcmd{bisect}.
-
-Another useful situation in which to use \hgcmdargs{bisect}{--skip} is
-if you can't test a revision because your project was in a broken and
-hence untestable state at that revision, perhaps because someone
-checked in a change that prevented the project from building.
-
-\subsection{Bracket your search lazily}
-
-Choosing the first ``good'' and ``bad'' changesets that will mark the
-end points of your search is often easy, but it bears a little
-discussion nevertheless.  From the perspective of \hgcmd{bisect}, the
-``newest'' changeset is conventionally ``bad'', and the older
-changeset is ``good''.
-
-If you're having trouble remembering when a suitable ``good'' change
-was, so that you can tell \hgcmd{bisect}, you could do worse than
-testing changesets at random.  Just remember to eliminate contenders
-that can't possibly exhibit the bug (perhaps because the feature with
-the bug isn't present yet) and those where another problem masks the
-bug (as I discussed above).
-
-Even if you end up ``early'' by thousands of changesets or months of
-history, you will only add a handful of tests to the total number that
-\hgcmd{bisect} must perform, thanks to its logarithmic behaviour.
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: "00book"
-%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/00book.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,81 @@
+% The use of oneside here is a temporary hack; \marginpar entries
+% don't show up on odd pages of PDF output without it.  Sigh.
+\documentclass[oneside]{book}
+\usepackage[spanish]{babel}
+\usepackage{enumerate}
+\usepackage{fullpage}
+\usepackage{makeidx}
+\usepackage{ifpdf}
+\usepackage{graphicx}
+\usepackage{pslatex}
+\usepackage{fancyvrb}
+\usepackage[utf8]{inputenc} %accents in spanish
+% leave hyperref until last
+\ifpdf
+\usepackage[colorlinks=true,bookmarks=true,pdftitle={Distributed
+  revision control with Mercurial},pdfsubject={Revision
+  control},pdfkeywords={Mercurial, Revision control, Distributed
+  revision control},pdfauthor={Bryan O'Sullivan}]{hyperref}
+\fi
+
+\include{99defs}
+
+\title{Control Distribuido de Revisiones con Mercurial} \author{Bryan
+  O'Sullivan}
+\date{Copyright \copyright\ 2006, 2007 Bryan O'Sullivan.\\
+  Este material puede distribuirse únicamente bajo los términos y
+  condiciones establecidos en la versión 1.0 de la Licencia de Publicación
+  Abierta (OPL). Refiérase por favor al apéndice~\ref{cha:opl} para encontrar el
+  texto de la licencia.\\
+  Este libro fue preparado a partir de
+  \href{http://mercurial.intuxication.org/hg/mercurial_book_es}{rev~\input{build_id}}
+  usando Mercurial \href{http://www.selenic.com/hg/}{rev~\input{hg_id}}.}
+
+\makeindex
+
+\begin{document}
+\spanishdeactivate{<>"~}
+\maketitle
+
+\addcontentsline{toc}{chapter}{Índice general}
+\pagenumbering{roman}
+\tableofcontents
+\listoffigures
+%\listoftables
+
+\pagenumbering{arabic}
+
+\include{preface}
+\include{intro}
+\include{tour-basic}
+\include{tour-merge}
+\include{concepts}
+\include{daily}
+\include{collab}
+\include{filenames}
+\include{branch}
+\include{undo}
+\include{hook}
+\include{template}
+\include{mq}
+\include{mq-collab}
+\include{hgext}
+
+\appendix
+\include{cmdref}
+\include{mq-ref}
+\include{srcinstall}
+\include{license}
+\addcontentsline{toc}{chapter}{Bibliografía}
+\bibliographystyle{alpha}
+\bibliography{99book}
+
+\addcontentsline{toc}{chapter}{Índice alfabético}
+\printindex
+
+\end{document}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: t
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/99book.bib	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1 @@
+../en/99book.bib
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/99defs.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,146 @@
+% Bug ID.
+\newcommand{\bug}[1]{\index{Base de datos de fallos de Mercurial
+    !\href{http://www.selenic.com/mercurial/bts/issue#1}{fallo
+      ~#1}}\href{http://www.selenic.com/mercurial/bts/issue#1}{Fallo de
+      Mercurial No.~#1}}
+
+% File name in the user's home directory.
+\newcommand{\tildefile}[1]{\texttt{\~{}/#1}}
+
+% File name.
+\newcommand{\filename}[1]{\texttt{#1}}
+
+% Directory name.
+\newcommand{\dirname}[1]{\texttt{#1}}
+
+% File name, with index entry.
+% The ``s'' prefix comes from ``special''.
+\newcommand{\sfilename}[1]{\index{\texttt{#1}, fichero}\texttt{#1}}
+
+% Directory name, with index entry.
+\newcommand{\sdirname}[1]{\index{\texttt{#1}, directorio}\texttt{#1}}
+
+% Mercurial extension.
+\newcommand{\hgext}[1]{\index{\texttt{#1}, extensi\'on}\texttt{#1}}
+
+% Command provided by a Mercurial extension.
+\newcommand{\hgxcmd}[2]{\index{\texttt{#2}, comando (extensi\'on
+\texttt{#1})}\index{\texttt{#1}, extensi\'on!comando \texttt{#2}}``\texttt{hg #2}''}
+
+% Mercurial command.
+\newcommand{\hgcmd}[1]{\index{\texttt{#1}, comando}``\texttt{hg #1}''}
+
+% Mercurial command, with arguments.
+\newcommand{\hgcmdargs}[2]{\index{\texttt{#1}, comando}``\texttt{hg #1 #2}''}
+
+\newcommand{\tplkword}[1]{\index{\texttt{#1}, palabra clave de
+plantilla}\index{palabras clave de plantilla!\texttt{#1}}\texttt{#1}}
+
+\newcommand{\tplkwfilt}[2]{\index{\texttt{#1}, palabra clave de plantilla!filtro
+\texttt{#2}}\index{filtros de plantilla!\texttt{#2}}\index{\texttt{#2}, filtro
+de plantilla}\texttt{#2}}
+
+\newcommand{\tplfilter}[1]{\index{filtros de
+plantilla!\texttt{#1}}\index{\texttt{#1}, filtro de plantilla}\texttt{#1}}
+
+% Shell/system command.
+\newcommand{\command}[1]{\index{\texttt{#1}, comando de sistema}\texttt{#1}}
+
+% Shell/system command, with arguments.
+\newcommand{\cmdargs}[2]{\index{\texttt{#1} comando de sistema}``\texttt{#1 #2}''}
+
+% Mercurial command option.
+\newcommand{\hgopt}[2]{\index{\texttt{#1}, comando!opción \texttt{#2}}\texttt{#2}}
+
+% Mercurial command option, provided by an extension command.
+\newcommand{\hgxopt}[3]{\index{\texttt{#2}, comando (extensión
+\texttt{#1})!opción \texttt{#3}}\index{\texttt{#1}, extensión!comando
+\texttt{#2}!opción\texttt{#3}}\texttt{#3}}
+
+% Mercurial global option.
+\newcommand{\hggopt}[1]{\index{opciones globales!opción \texttt{#1}}\texttt{#1}}
+
+% Shell/system command option.
+\newcommand{\cmdopt}[2]{\index{\texttt{#1}, comando!opción \texttt{#2}}\texttt{#2}}
+
+% Command option.
+\newcommand{\option}[1]{\texttt{#1}}
+
+% Software package.
+\newcommand{\package}[1]{\index{\texttt{#1}, paquete}\texttt{#1}}
+
+% Section name from a hgrc file.
+\newcommand{\rcsection}[1]{\index{\texttt{hgrc}, fichero!sección \texttt{#1}}\texttt{[#1]}}
+
+% Named item in a hgrc file section.
+\newcommand{\rcitem}[2]{\index{\texttt{hgrc}, fichero!sección
+\texttt{#1}!entrada \texttt{#2}}\texttt{#2}}
+
+% hgrc file.
+\newcommand{\hgrc}{\index{fichero de configuración!\texttt{hgrc}
+    (Linux/Unix)}\index{\texttt{hgrc}, fichero de configuración}\texttt{hgrc}}
+
+% Mercurial.ini file.
+\newcommand{\hgini}{\index{fichero de configuración!\texttt{Mercurial.ini}
+    (Windows)}\index{\texttt{Mercurial.ini}, fichero de configuración}\texttt{Mercurial.ini}}
+
+% Hook name.
+\newcommand{\hook}[1]{\index{\texttt{#1}, gancho}\index{ganchos!\texttt{#1}}\texttt{#1}}
+
+% Environment variable.
+\newcommand{\envar}[1]{\index{\texttt{#1}, variable de entorno}\index{variables
+de entorno!\texttt{#1}}\texttt{#1}}
+
+% Python module.
+\newcommand{\pymod}[1]{\index{\texttt{#1}, módulo}\texttt{#1}}
+
+% Python class in a module.
+\newcommand{\pymodclass}[2]{\index{\texttt{#1}, módulo!clase \texttt{#2}}\texttt{#1.#2}}
+
+% Python function in a module.
+\newcommand{\pymodfunc}[2]{\index{\texttt{#1}, módulo!función \texttt{#2}}\texttt{#1.#2}}
+
+% Note: blah blah.
+\newsavebox{\notebox}
+\newenvironment{note}%
+  {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Nota:}\space}%
+  {\end{minipage}\end{lrbox}\fbox{\usebox{\notebox}}}
+\newenvironment{caution}%
+  {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Precaución:}\space}%
+  {\end{minipage}\end{lrbox}\fbox{\usebox{\notebox}}}
+
+% Code sample, eating 4 characters of leading space.
+\DefineVerbatimEnvironment{codesample4}{Verbatim}{frame=single,gobble=4,numbers=left,commandchars=\\\{\}}
+
+% Code sample, eating 2 characters of leading space.
+\DefineVerbatimEnvironment{codesample2}{Verbatim}{frame=single,gobble=2,numbers=left,commandchars=\\\{\}}
+
+% Interaction from the examples directory.
+\newcommand{\interaction}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{examples/#1.lxo}}
+% Example code from the examples directory.
+\newcommand{\excode}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{../examples/#1}}
+
+% Graphics inclusion.
+\ifpdf
+  \newcommand{\grafix}[2][]{\includegraphics[#1]{#2}}
+\else
+  \newcommand{\grafix}[1]{\includegraphics{#1.png}}
+\fi
+
+% Reference entry for a command.
+\newcommand{\cmdref}[2]{\section{\hgcmd{#1}---#2}\label{cmdref:#1}\index{\texttt{#1}, comando}}
+
+% Reference entry for a command option with long and short forms.
+\newcommand{\optref}[3]{\subsubsection{\hgopt{#1}{--#3}, también \hgopt{#1}{-#2}}}
+
+% Reference entry for a command option with only long form.
+\newcommand{\loptref}[2]{\subsubsection{opción \hgopt{#1}{--#2}}}
+
+% command to generate a footnote to be used as a translator's note
+\newcommand{\ndt}[1]{\footnote{\textbf{N. del T.} #1}}
+
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/Leame.1st	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,508 @@
+= Parámetros de Organización =
+
+ * Se mantienen los nombres de los archivos
+ * Se traduce solamente el contenido
+ * Copie los archivos de en a es y tradúzcalos
+ * Las gráficas son tan importantes como los archivos
+ de texto, ya han sido traducidas
+ * Encoding UTF-8 para las tildes, eñes y demás
+ * Ancho de línea de 70 caracteres
+
+= ¿Cómo contribuir? =
+Obtenga la copia :
+hg clone http://mercurial.intuxication.org/hg/mercurial_book_es/
+
+Esto le ofrecerá un clon del repositorio en el directorio recién 
+creado '''mercurial_book_es''':
+
+mercurial_book_es
+|
+|-- en
+|-- es
+|-- examples
+|-- html
+`-- sillybench
+
+El directorio de trabajo es '''es'''.
+
+
+Una vez que haya traducido o aplicado correcciones a los archivos de
+su copia local, haga un commit
+
+ hg commit -m "comentario descriptivo de lo que hizo"
+
+Siempre mantenga actualizado su repositorio local
+ hg pull
+ hg update
+
+Hay dos formas de hacer la contribución, primero envíe un correo a
+igor@tamarapatino.org indicando lo que desea hacer, se le puede
+otorgar permiso de escritura en el repositorio, o si lo prefiere,
+puede enviar un parche (patch).  Describimos a continuación los dos
+procedimientos : Repositorio Público y Parches.   Es preferible el
+repositorio público frente a los parches, puesto que estos segundos
+pueden tardar en propagarse más.
+
+== Repositorio Público ==
+Este sería el método preferido para que los cambios que usted haga
+automáticamente queden en el repositorio y todos los traductores
+podamos contar con la información rápidamente.
+
+Una vez que usted haya recibido la información necesaria, habiendo
+elegido su usuario y su clave podrá "publicar" (push).
+
+Como este es un sistema distribuido, después de hacer la
+consignación (commit), deberá publicarlo.
+
+ hg push
+
+Se le solicitará su usuario y clave.
+
+== Parches ==
+Este método exige que alguien reciba el parche y haga manualmente la
+aplicación del mismo, ese alguien es igor@tamarapatino.org por ahora,
+después de haber hecho commit en su repositorio local, revise su log.
+
+ hg log | head
+
+Esta última orden le permitirá establecer la última revisión que se
+consignó en su repositorio local, su identificador de revisión tendrá
+el formato número:hash.   Generaría el archivo 
+/tmp/patchparahgbook.patch con la orden
+
+ hg -o /tmp/patchparahgbook.patch REV
+
+donde REV es el identificador de revisión que debió haber encontrado.
+
+= Traducción/Revisión =
+
+En esta sección indicamos quienes están traduciendo
+y quienes revisando lo traducido. Coloque su nombre 
+para que los demás colaboradores sepan en dónde 
+enfocar sus esfuerzos.
+
+Indique qué archivos está traduciendo y/o revisando en 
+la lista siguiente. Cada archivo debe ser traducido y
+revisado antes de poder considerarlo terminado. El revisor
+no puede ser la misma persona que hizo la traducción.
+
+Cada traductor puede traducir o revisar el archivo que
+desee, teniendo siempre en cuenta los archivos que ya tengan
+alguien a cargo y escogiendo en la medida de lo posible
+otros que no lo tengan. Los arreglos de 'typos' y problemas
+de ortografía son siempre bienvenidos.
+
+== Archivos en proceso de traducción ==
+||'''archivo'''    ||'''traductor'''||'''Estado'''||'''Inicio'''||  '''Fin'''  ||
+|| 00book.tex      || Igor Támara   ||    100%    || 16/10/2008 ||  16/10/2008 ||
+|| preface.tex     || Javier Rojas  ||    100%    || 18/10/2008 ||  19/10/2008 ||
+|| intro.tex       || Igor Támara   ||	  100%	  || 08/11/2008	||  09/11/2008 ||
+|| tour-basic.tex  || Javier Rojas  ||    100%    || 19/10/2008 ||  27/10/2008 ||
+|| tour-merge.tex  || Javier Rojas  ||    100%    || 28/10/2008 ||  03/11/2008 ||
+|| concepts.tex    || Javier Rojas  ||    100%    || 03/11/2008 ||  23/11/2008 ||
+|| daily.tex       || Igor Támara   ||    100%    || 19/10/2008 ||  26/10/2008 ||
+|| collab.tex      || Igor Támara   ||    100%    || 10/11/2008 ||  06/12/2008 ||
+|| filenames.tex   || Javier Rojas  ||    100%    || 27/11/2008 ||  12/01/2008 ||
+|| branch.tex      || Igor Támara   ||    100%    || 16/10/2008 ||  19/10/2008 ||
+|| undo.tex        || Igor Támara   ||    100%    || 26/10/2008 ||  07/11/2008 ||
+|| hook.tex        || Javier Rojas  ||    100%    || 01/12/2008 ||  04/01/2009 ||
+|| template.tex    || Igor Támara   ||    100%    || 27/12/2008 ||  01/01/2009 ||
+|| mq.tex          || Igor Támara   ||    100%    || 06/12/2008 ||  13/12/2008 ||
+|| mq-collab.tex   || Javier Rojas  ||    100%    || 04/01/2009 ||  08/01/2009 ||
+|| hgext.tex       || Igor Támara   ||    100%    || 13/12/2008 ||  16/12/2008 ||
+|| cmdref.tex      || Igor Támara   ||    100%    || 01/01/2009 ||  01/01/2009 ||
+|| mq-ref.tex      || Igor Támara   ||    100%    || 06/01/2009 ||  10/01/2009 ||
+|| srcinstall.tex  || Igor Támara   ||    100%    || 01/01/2009 ||  01/01/2009 ||
+|| license.tex     || Igor Támara   ||    100%    || 16/12/2008 ||  16/12/2008 ||
+
+== Archivos en proceso de revisión ==
+||'''archivo'''   || '''revisor''' ||'''Estado'''||'''Inicio'''||  '''Fin'''  ||
+|| 00book.tex     || Javier Rojas  ||    100%    || 18/01/2009 ||  18/01/2009 ||
+|| branch.tex     || Javier Rojas  ||    100%    || 25/01/2009 ||  25/01/2009 ||
+|| preface.tex    ||               ||            ||            ||             ||
+|| daily.tex      || Javier Rojas  ||    100%    || 25/01/2009 ||  29/01/2009 ||
+|| tour-basic.tex ||               ||            ||            ||             ||
+|| undo.tex       || Javier Rojas  ||            ||            ||             ||
+|| tour-merge.tex ||               ||            ||            ||             ||
+|| concepts.tex   ||               ||            ||            ||             ||
+|| intro.tex      || Javier Rojas  ||    100%    || 12/01/2009 ||  12/01/2009 ||
+|| collab.tex     || Javier Rojas  ||      0%    || 29/01/2009 ||             ||
+|| mq.tex         ||               ||            ||            ||             ||
+|| hgext.tex      ||               ||            ||            ||             ||
+|| template.tex   ||               ||            ||            ||             ||
+|| mq-collab.tex  ||               ||            ||            ||             ||
+|| mq-ref.tex     ||               ||            ||            ||             ||
+|| cmdref.tex     ||               ||            ||            ||             ||
+|| license.tex    ||               ||            ||            ||             ||
+|| srcinstall.tex ||               ||            ||            ||             ||
+
+== Archivos terminados ==
+||'''archivo'''   ||'''Inicio'''||  '''Fin'''  ||
+|| 00book.tex     || 16/10/2008 ||  18/01/2009 ||
+|| intro.tex      || 08/11/2008 ||  12/01/2009 ||
+|| branch.tex     || 16/10/2008 ||  25/01/2009 ||
+|| daily.tex      || 19/10/2008 ||  29/01/2009 ||
+
+= Unificación de Términos de Traducción =
+Por favor mantenga esta lista en orden alfabético
+
+La mayor parte del texto a continuación fue tomado del glosario de la
+traducción del libro de subversion al idioma español.
+
+Pequeño glosario de términos traducidos. Aquí deben ponerse esos
+"bonitos palabros" que tanto nos ha costado traducir para evitar
+inconsistencias en la traducción por varias personas. Normalmente
+son técnicos, pero puede incluirse cualquier "giro" o expresión que
+consideremos útil mantener y repetir a lo largo de la traducción.
+En el libro final posiblemente se añada una versión de este fichero
+como apéndice.
+
+Para incluir algo, hay que especificar la expresión en inglés, su
+versión traducida, y una pequeña explicación como justificación.
+
+ Alice: Alicia
+ Anne: Ana
+ Back out: Retroceder
+ Binary test: Prueba binaria
+ Bob : Roberto
+ Branch: Rama
+ Bug: Fallo
+ Build Script: Guión de construcción
+ Builtin: integrada/o
+ Bundle: Agrupamiento 
+ Bundled: Incluído o agrupado
+ Changelog: Bitácora de Cambios
+ Changeset: Conjunto de Cambios
+ Command: Orden
+ Commit: Consignar
+ Core: alma
+ Directory: Directorio
+ Escape Sequence: Secuencia de control
+ File: fichero
+ Filelog: fichero de registro
+ Fold: Integrar
+ Fork: Bifurcación
+ Hash: No se traduce
+ Head: Principal. En el contexto de revisiones HEAD se sugiere usar "frente"
+ Hook: Gancho
+ Merge: Fusión
+ Milestone: Etapa
+ Mistake: Equivocación, cometida por un humano
+ Output: salida o despliegue
+ Patch: Parche
+ Path: Ruta de archivo
+ Pointer: apuntador
+ Pop: Sustraer, la contraparte push, será publicar
+ Probe: Sondeo
+ Pull: Jalar
+ Push: Publicar.  En el contexto de parches introducir.
+ Queue: Cola
+ Release: Versión o liberación de versión
+ Revlog: Bitácora de revisiones
+ Roll back: NO se traduce Ver más abajo
+ Snapshot: instantánea
+ Snippet: Recorte de código
+ Stack: pila
+ Stripped: 
+ Sprint: sprint
+ Tarball: paquete de cambios
+ Timestamp : marca de tiempo
+ Tip: punta
+ Update: actualización
+ Upstream: principal, mantenedor principal. De acuerdo al contexto.
+
+abort -> cancelar
+
+ancestry -> ascendencia
+    La traducción literal concuerda con el significado que se le
+    da al mismo término en la jerga de Subversion.
+
+API, GUI -> no se traduce
+    La primera vez que aparecen, poner nota del traductor indicando
+    qué significan las siglas y su traducción al castellano. De
+    hecho, verificar la aparición de las notas de traductor en el
+    sitio correcto debería ser una entrada del fichero TODO...
+
+back-end -> ???
+    Se refiere al término opuesto de front-end. En el octavo
+    capítulo se usa al menos tres veces para referirse al "motor"
+    que hay detrás de la capa de base de datos. Hmmm... pero motor
+    suena raro...
+
+backup -> copia de seguridad
+    Obtenido del glosario ORCA.
+
+Blanket Access Control -> Control de acceso simple
+    Por ahora no se me ocurre mejor traducción. Aquí blanket se
+    refiere a un control muy genérico, con poca granularidad.
+
+branching and merging -> crear ramas y fusionarlas
+    Aunque branch está bien traducido como rama o rama de desarrollo
+    (en su versión "verbose"), no hay forma de hacer de un sustantivo
+    un verbo.  Por lo tanto, se crean, borran y fusionan ramas.
+
+browse -> navegar
+    Usado con frecuencia para navegar por directorios o repositorios.
+
+build -> comodín
+    No es que se traduzca como comodín, sino que en función del
+    contexto es una de esas palabras que significan muchas cosas y
+    no es posible traducirla literalmente. Por ejemplo, cuando se
+    usa como verbo se suele referir a compilar código fuente. En
+    cambio, cuando se usa como sustantivo se suele referir a una
+    versión particular del fichero binario ejecutable de un software,
+    resultado de una compilación previa. Cuidado con esto. Anotar
+    aquí traducciones realizadas para comparar.
+
+        ...using and building Subversion...
+        ...usando y compilando Subversion...
+
+changeset -> ???
+    Aparentemente conjunto de cambios. No puede ser traducido
+    como parche, el libro inglés indica que un "changeset" es un
+    parche con nombre único. Por ahora dejar en "changeset", ya se
+    buscará algo en el futuro. Para ver la descripción del libro,
+    buscar en ch04.xml la frase "Subversion y los changesets".
+
+cheap copy -> copia ligera
+    Otras posibilidades barajadas son copia barata o liviana.
+    Veremos si en el futuro éstas suenan mejor.
+
+click -> haga clic, pulse
+    Traducción obtenida del glosario. Parece ser que click sólo se
+    deja tal cual cuando se refiere a un sonido mecánico. Cuando
+    se refiere a pulsar el botón del ratón se traduce como clic.
+
+CVS -> No se traduce
+
+DAV share -> recurso DAV compartido
+    No tengo ni idea de lo que es un DAV share, así que cuando me
+    entere (o alguien lo haga), que cambie esta entrada del glosario.
+
+directory -> directorio
+    Entre carpeta y directorio se prefiere directorio.
+
+email -> correo electrónico
+    Entre las posibilidades de dejar la palabra tal cual, añadir un
+    guión (e-mail) y poner la traducción, se prefiere la traducción
+    completa.
+
+FAQ -> FAQ
+    Se deja tal cual pues se explica en el primer párrafo del prólogo
+    como una nota del traductor, y porque es muy frecuente ver su
+    uso en español. PyRF, PUFs o PFs son realmente desconcertantes.
+
+file -> fichero
+    Entre archivo y fichero se prefiere fichero.
+
+file path -> ruta del fichero
+    Cuando se ve path a secas, la forma más común de traducirlo
+    es decir ruta a secas igualmente. Bueno, el glosario de ORCA
+    también da como válidos camino y trayectoria. A ser posible
+    usar ruta si el contexto de la frase así lo favorece, en caso
+    contrario probar con camino o trayectoria.
+
+hash table -> tabla hash
+    Sugerido por Miguel Pérez Ibars. También encontrado en el
+    glosario ORCA.
+
+history -> Depende del contexto. Cuando se use en el contexto del repositorio
+    (the history of the repository), debe usarse el término historial. En otro
+    caso, historia. Valga anotar que ambas traducciones son aceptadas (al menos
+    en wordreference.com).
+
+hook, to hook -> gancho, enganchar
+    Usado en terminología de programación para indicar que el usuario
+    tiene un mecanismo estándar para modificar el comportamiento de
+    un dispositivo existente. Un ejemplo a nivel de programación
+    son las funciones "callback" que se pasan como parámetros,
+    o a nivel de sistema, scripts que existen en un directorio
+    concreto y que se ejecutan por el servidor de Subversion para
+    realizar tareas personalizadas por el administrador.
+
+ignore pattern -> ignorar patrones, pero patrones de exclusión
+    Subversion permite que ciertas opciones almacenen patrones
+    con los que se ignoran ficheros no versionados. Cuando la
+    frase original usa el verbo, se puede traducir como ignorar
+    directamente, pero cuando se usa a modo de sustantivo,
+    es mejor traducirlo como "patrón de exclusión" en lugar de
+    "patrón a ignorar".
+
+language -> lenguaje o idioma
+    Precisamente para diferenciar si nos estamos refiriendo a un
+    lenguaje de programación o a un lenguaje hablado por humanos,
+    se usará idioma en este último caso.
+
+language binding, SWIG binding, wrapper -> interfaz, enlace, ligadura, envoltorio...
+    Dependiendo del contexto, y desde un punto de vista personal,
+    se puede traducir esta palabra de muchas maneras. Una manera
+    genérica es decir "Interfaz con el lenguaje X", o "Ligadura con
+    el lenguaje X". Habitualmente, cuando se habla de una interfaz,
+    se está hablando de un binding ligero, o que únicamente permite
+    a hacer llamadas a funciones del lenguaje de programación A
+    desde el lenguaje de programación B.
+
+    En cambio, se suele hablar de wrapper cuando el código entre
+    el lenguaje A y B es algo más complejo, o adapta el estilo de
+    programación del lenguaje A al del lenguaje B. Un ejemplo de esto
+    último sería una librería en C cuyo binding en Perl/Ruby/Python
+    fuese orientado a objetos.
+
+    Aparte, wrapper también se usa cuando se habla de una función
+    o librería que engloba o asimila otra menor, con el propósito
+    de extender su funcionalidad o hacerla más fácil de usar
+    de cara al usuario, sin necesidad de cruzar ninguna barrera
+    "intra-lenguaje".
+
+    Por lo tanto, hay que decidir con cuidado el contexto de la
+    palabra binding o wrapper, y escoger una. En el capítulo octavo
+    hay varios usos, aunque como son relativos a SWIG, se habla de
+    interfaces o envoltorios simplificados, puesto que se generan
+    de manera automática y no hay ninguna "conversión" en el estilo
+    de uso.
+
+lazy copy -> copia vaga
+    Horrible traducción literal. ¿Sugerencias?
+    copia perezosa
+
+location (repository) -> ubicación (del repositorio)
+    Cuidado, no traducir como localización, que es la acción y
+    efecto de localizar.
+
+log, log message -> informe de cambios, mensaje del informe de cambios
+    Traducción extraída del manual de CVS en español. La traducción
+    de "log message" es muy larga, pero únicamente porque no se
+    tiene contexto alguno. Con contexto suele ser posible omitir
+    la palabra informe si se considera apropiado.
+
+memory pool -> área de memoria
+    Traducción temporal hasta que se revise algún libro en castellano
+    de programación que use el mismo término.
+
+merge -> fusionar cambios, fusión
+    Obtenida referencia del manual de CVS en castellano, la otra
+    alternativa obvia para traducir merge es mezclar. No obstante,
+    mezclar tiene una connotación de azar al realizar la mezcla. Se
+    mezclan líquidos, ingredientes, etc. En cambio, un "merge" es
+    cualquier cosa menos un proceso realizado al azar (especialmente
+    si ha habido conflictos). En caso de traducir como sustantivo,
+    fusión vuelve a "sonar mejor" que mezcla, que por alguna razón me
+    suena a un combustible especial usado en vehículos de transporte.
+
+namespace -> espacio de nombrado,
+    Tecnicismo del C++, obtenido de la traducción del libro
+    "Pensar en C++", en concreto la sección 3.2 disponible en
+    http://arco.inf-cr.uclm.es/~dvilla/pensar_en_C++/ch02s03.html#id2589039.
+
+open source -> código fuente abierto
+    Referencia: http://es.tldp.org/ORCA/glosario.html#O
+
+plugins -> módulos
+    El término fue extraído del glosario de ORCA.
+
+repository -> repositorio
+    No hay mucha alternativa, ¿verdad?
+
+roll back -> No se traduce 
+    El significado igual que en los ambientes
+     de sistemas manejadores de bases de datos se refiere a la atomicidad
+     e integridad al devolver un conjunto de acciones que permitan dejar
+     el repositorio en un estado consistente previo.
+
+repository layou t-> estructura del repositorio En referencia a cómo
+    están organizados los directorios.
+
+schedule -> programa o planifica
+    Parece más correcta la opción programa, en el sentido de pensar en
+    hacer algo.
+    schedule foo to be added -> programa la adición de foo
+
+switch -> cambiar
+    Únicamente cuando se habla del comando svn switch, no como la
+    palabra switch aislada, que significa parámetro o interruptor.
+    En el contexto de svn switch, traducirlo como cambiar. Quizás
+    traducir como reubicar una vez haya suficiente material traducido
+    y una lectura final sugiera una u otra traducción.
+
+tag, tagging -> etiqueta, etiquetar
+    Expresión ya común en español.
+
+three-way differencing program -> programa de diferenciación a tres bandas
+    Una diferenciación "normal" es generar las diferencias entre
+    dos ficheros.  Una diferenciación a tres bandas es comparar las
+    diferencias entre tres ficheros, y se usa cuando se intentan
+    fusionar los cambios de una copia local junto con los cambios
+    recibidos del repositorio (por ejemplo, otra persona ha cambiado
+    el fichero sobre el que trabajábamos).
+
+timestamp, datestamp -> marca de tiempo, fecha y hora
+    Esa traducción viene del ORCA. No obstante en muchos casos es
+    más claro traducirla como "fecha de fichero" o "fecha" a secas.
+    Ejemplo: ...will show the modification timestamp. -> mostrará
+    la fecha de modificación. Decir "mostrará la marca de tiempo de
+    la modificación" o algo así es una traducción demasiado literal,
+    así que ojo con el contexto.
+
+track -> seguir, monitorear
+    este término suele ser usado cuando se habla de archivos, y de llevar la 
+    pista o monitorear los cambios en un archivo.
+
+trunk -> tronco
+    Se refiere al nombre que recibe la línea de desarrollo
+    principal del repositorio que no está asociada a ninguna rama
+    en particular. Traducción obtenida del manual de CVS en español.
+
+Unix-like systems -> sistemas tipo unix
+
+URL -> No se traduce
+
+working copy -> copia (de trabajo) local/activa
+    Traducción similar a la de "commit data" (razonamiento
+    cliente-servidor).
+
+= Términos a no-usar =
+Evite el uso de estos términos en la traducción aún si son de uso
+común para usted; el consenso general de la comunidad hispana puede
+ser diferente del que usted tenga ;)
+
+  * "archivo". Use "fichero" en su lugar.
+  * "carpeta". Use "directorio".
+  * "la historia". Use "el historial" (por supuesto, cuando se refiera al
+  historial del repositorio)
+
+= Diferencias de redacción =
+Hay varias expresiones que pueden terminar siendo traducidas de formas
+diferentes por los traductores, y que aún siendo ambas correctas, ponen en
+evidencia que el trabajo fue llevado a cabo por varias personas y que el estilo
+que ellas usan difiere. Una vez terminada la traducción habrá que buscar cuáles
+son éstos términos y decidirse por uno solo de ellos. A continuación se presenta
+una lista de los términos o expresiones encontrados hasta ahora
+
+  * comando - orden. Ambos son la traducción para "command". Parece que la
+  traducción más adecuada es "comando"
+  (http://www.wordreference.com/es/translation.asp?tranword=command)
+  * kernel - núcleo.
+  * Colas de Mercurial - colas de Mercurial. Creo que lo mejor es revisar qué
+  usó el autor (y rogar que él no haya sido inconsistente :P)
+  * armar - compilar - construir. Build, compile. Más que todo "build"
+  * daemonio - demonio. daemon
+  * kernel - núcleo.
+  * la URL - el URL
+
+= Notas del traductor =
+Por favor use el comando \ndt para insertar notas del traductor. Este
+comando requiere un argumento. Por ejemplo: \ndt{Del inglés del original.}
+
+= Para compilar =
+He aquí algunas dependencias para Debian:
+
+apt-get install texlive-latex-extra tex4ht diffstat patchutils \ 
+   inkscape graphviz texlive-pdfetex
+
+= Traductores =
+Por favor mantenga esta lista en orden alfabético de acuerdo al
+apellido.
+
+ * Javier Rojas <jerojasro@devnull.li>
+ * Igor Támara <igor@tamarapatino.org>
+ * Su nombre <su@e.mail>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/Makefile	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,223 @@
+# This makefile requires GNU make.
+
+sources := \
+	00book.tex \
+	99book.bib \
+	99defs.tex \
+	build_id.tex \
+	branch.tex \
+	cmdref.tex \
+	collab.tex \
+	concepts.tex \
+	daily.tex \
+	filenames.tex \
+	hg_id.tex \
+	hgext.tex \
+	hook.tex \
+	intro.tex \
+	mq.tex \
+	mq-collab.tex \
+	mq-ref.tex \
+	preface.tex \
+	srcinstall.tex \
+	template.tex \
+	tour-basic.tex \
+	tour-merge.tex \
+	undo.tex
+
+image-sources := \
+	feature-branches.dot \
+	filelog.svg \
+	kdiff3.png \
+	metadata.svg \
+	mq-stack.svg \
+	note.png \
+	revlog.svg \
+	snapshot.svg \
+	tour-history.svg \
+	tour-merge-conflict.svg \
+	tour-merge-merge.svg \
+	tour-merge-pull.svg \
+	tour-merge-sep-repos.svg \
+	undo-manual.dot \
+	undo-manual-merge.dot \
+	undo-non-tip.dot \
+	undo-simple.dot \
+	wdir.svg \
+	wdir-after-commit.svg \
+	wdir-branch.svg \
+	wdir-merge.svg \
+	wdir-pre-branch.svg
+
+image-dot := $(filter %.dot,$(image-sources))
+image-svg := $(filter %.svg,$(image-sources))
+image-png := $(filter %.png,$(image-sources))
+
+image-pdf := $(image-dot:%.dot=%.pdf) $(image-svg:%.svg=%.pdf) $(image-png)
+image-html := $(image-dot:%.dot=%.png) $(image-svg:%.svg=%.png) $(image-png)
+
+example-sources := \
+	backout \
+	bisect \
+	branching \
+	branch-named \
+	branch-repo \
+	cmdref \
+	daily.copy \
+	daily.files \
+	daily.rename \
+	daily.revert \
+	extdiff \
+	filenames \
+	hook.msglen \
+	hook.simple \
+	hook.ws \
+	issue29 \
+	mq.guards \
+	mq.qinit-help \
+	mq.dodiff \
+	mq.id \
+	mq.tarball \
+	mq.tools \
+	mq.tutorial \
+	rename.divergent \
+	rollback \
+	tag \
+	template.simple \
+	template.svnstyle \
+	tour \
+	tour-merge-conflict
+
+example-prereqs := \
+	/usr/bin/merge
+
+dist-sources := \
+	../html/hgicon.png \
+	../html/index.html.var \
+	../html/index.en.html \
+	../html/index.es.html
+
+latex-options = \
+	-interaction batchmode \
+	-output-directory $(dir $(1)) \
+	-jobname $(basename $(notdir $(1)))
+
+hg = $(shell which hg)
+
+hg-id = $(shell hg parents --template '{node|short}, fechado {date|isodate},\n')
+
+hg-version = $(shell hg version -q | \
+		     sed 's,.*(versión \(unknown\|[a-f0-9+]*\)),\1,')
+
+all: pdf html
+
+pdf: pdf/hgbook.pdf
+
+define pdf
+	mkdir -p $(dir $@)
+	TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1)
+	cp 99book.bib $(dir $@)
+	cd $(dir $@) && bibtex $(basename $(notdir $@))
+	cd $(dir $@) && makeindex $(basename $(notdir $@))
+	TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1)
+	TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1)
+	if grep 'Reference.*undefined' $(@:.pdf=.log); then exit 1; fi
+endef
+
+pdf/hgbook.pdf: $(sources) examples $(image-pdf)
+	$(call pdf)
+
+html: onepage split
+
+onepage: $(htlatex) html/onepage/hgbook.html html/onepage/hgbook.css $(image-html:%=html/onepage/%)
+
+html/onepage/%: %
+	cp $< $@
+
+split: $(htlatex) html/split/hgbook.html html/split/hgbook.css $(image-html:%=html/split/%)
+
+html/split/%: %
+	cp $< $@
+
+# This is a horrible hack to work around the fact that the htlatex
+# command in tex4ht is itself a horrible hack.  I really don't want to
+# include verbatim the big wad of TeX that is repeated in that script,
+# but I've given up and run a hacked copy as htlatex.book here.
+
+define htlatex
+	mkdir -p $(dir $(1))
+	cp 99book.bib $(dir $(1))
+	TEXINPUTS=$(dir $(2)): ./htlatex.book $(2) "bookhtml,html4-uni,$(3)" " -cunihtf -utf8" "$(dir $(1))" "$(call latex-options,$(1))" || (rm -f $(1); exit 1)
+	cd $(dir $(1)) && tex4ht -f/$(basename $(notdir $(1))) -cvalidate -cunihtf
+	cd $(dir $(1)) && t4ht -f/$(basename $(notdir $(1)))
+	./fixhtml.py $(dir $(1))/*.html
+	rm $(dir $(1))/hgbook.css
+endef
+
+html/onepage/hgbook.html: $(sources) examples $(image-html) bookhtml.cfg
+	$(call htlatex,$@,$<)
+
+html/split/hgbook.html: $(sources) examples bookhtml.cfg
+	$(call htlatex,$@,$<,2)
+
+# Produce 90dpi PNGs for the web.
+
+%.png: %.svg fixsvg
+	./fixsvg $<
+	inkscape -D -e $@ $<-tmp.svg
+	rm $<-tmp.svg
+
+%.svg: %.dot
+	dot -Tsvg -o $@ $<
+
+# Produce eps & pdf for the pdf
+
+%.pdf: %.eps
+	epstopdf $<
+
+%.eps: %.svg
+	./fixsvg $<
+	inkscape -E $@ $<-tmp.svg
+	rm $<-tmp.svg
+
+%.eps: %.dot
+	dot -Tps -o $@ $<
+
+examples: $(example-prereqs) examples/.run
+
+examples/.run: $(example-sources:%=examples/%.run)
+	touch examples/.run
+
+examples/%.run: examples/% examples/run-example
+	cd examples && ./run-example $(notdir $<)
+
+changelog := $(wildcard ../.hg/store/00changelog.[id])
+ifeq ($(changelog),)
+changelog := $(wildcard ../.hg/00changelog.[id])
+endif
+
+build_id.tex: $(changelog)
+	echo -n '$(hg-id)' > build_id.tex
+
+hg_id.tex: $(hg)
+	echo -n '$(hg-version)' > hg_id.tex
+
+clean:
+	rm -rf dist html pdf \
+		$(image-dot:%.dot=%.pdf) \
+		$(image-dot:%.dot=%.png) \
+		$(image-svg:%.svg=%.pdf) \
+		$(image-svg:%.svg=%.png) \
+		examples/*.{lxo,run} examples/.run build_id.tex hg_id.tex
+
+install: pdf split $(dist-sources) 
+	rm -rf dist
+	mkdir -p dist
+	cp pdf/hgbook.pdf dist
+	cp html/split/*.{css,html,png} dist
+	cp html/onepage/hgbook.html dist/onepage.html
+	ln -s index.es.html dist/index.html
+	cp $(dist-sources) dist
+
+rsync: install
+	rsync -avz --delete dist/ ikks@sulaco.devnull.li:public_html/hgbook/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/bookhtml.cfg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1 @@
+../en/bookhtml.cfg
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/branch.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,412 @@
+%% vim: tw=70 encoding=utf8
+\chapter{Administración de versiones y desarrollo ramificado}
+\label{chap:branch}
+
+Mercurial ofrece varios mecanismos que le permiten administrar un
+proyecto que avanza en múltiples frentes simultáneamente. Para
+entender estos mecanismos, demos un vistazo a la estructura usual de
+un proyecto de software.
+
+Muchos proyectos de software liberan una versión ``mayor'' que contiene
+nuevas características substanciales.  En paralelo, pueden liberar
+versiones ``menores''.   Usualmente éstas son idénticas a las
+versiones mayores en las cuales están basadas, pero con arreglos para
+algunos fallos.
+
+En este capítulo, comenzaremos hablando de cómo mantener registro de
+etapas del proyecto como las liberaciones de una
+versión. Continuaremos hablando del flujo de trabajo entre las
+diferentes fases de un proyecto, y cómo puede ayudar Mercurial a
+aislar y administrar tal trabajo.
+
+\section{Dar un nombre persistente a una revisión}
+
+Cuando usted decide otorgar a una revisión el nombre particular de una
+``versión'', es buena idea grabar la identidad de tal revisión.
+Esto le permitirá reproducir dicha versión en una fecha posterior,
+para cualquiera que sea el 
+propósito que se tenga en ese momento (reproducir un fallo, portar
+a una nueva plataforma, etc).
+\interaction{tag.init}
+
+Mercurial le permite dar un nombre permanente a cualquier revisión
+usando la orden \hgcmd{tag}.  Sin causa de sorpresa, esos nombres se llaman
+``tags'' (etiquetas).
+\interaction{tag.tag}
+
+Una etiqueta no es más que un ``nombre simbólico'' para una revisión.  Las
+etiquetas existen únicamente para su conveniencia, brindándole una forma
+permanente y sencilla de referirse a una revisión; Mercurial no
+interpreta de ninguna manera los nombres de las etiquetas que usted use.
+Mercurial tampoco impone restricción alguna al nombre de una etiqueta, más
+allá de lo necesario para asegurar que una etiqueta pueda procesarse sin
+ambigüedades. El nombre de una etiqueta no puede tener ninguno de los
+siguientes caracteres:
+\begin{itemize}
+\item Dos puntos (ASCII 58, ``\texttt{:}'')
+\item Retorno de carro (return) (ASCII 13, ``\Verb+\r+'')
+\item Nueva línea (ASCII 10, ``\Verb+\n+'')
+\end{itemize}
+
+Puede usar la orden \hgcmd{tags} para ver las etiquetas presentes en
+su repositorio. Al desplegarse, cada revisión marcada se identifica
+primero con su nombre, después con el número de revisión y finalmente con
+un hash único de la revisión.
+\interaction{tag.tags}
+Note que \texttt{tip} aparece en en listado generado por \hgcmd{tags}. La etiqueta
+\texttt{tip} es una etiqueta ``flotante'' especial, que identifica siempre
+la revisión más reciente en el repositorio.
+
+Al desplegar la orden \hgcmd{tags}, las etiquetas se listan en orden
+inverso, por número de revisión. Lo que significa usualmente que las
+etiquetas más recientes se listan antes que las más antiguas. También
+significa que la etiqueta \texttt{tip} siempre aparecerá como primera
+etiqueta listada al desplegar la orden \hgcmd{tags}.
+
+Cuando usted ejecuta \hgcmd{log}, si se muestra una revisión que tenga 
+etiquetas asociadas a ella, se imprimirán tales etiquetas.
+\interaction{tag.log}
+
+Siempre que requiera indicar un~ID de revisión a una orden de
+Mercurial, aceptará un nombre de etiqueta en su lugar.  Internamente,
+Mercurial traducirá su nombre de etiqueta en el~ID de revisión
+correspondiente, y lo usará.
+\interaction{tag.log.v1.0}
+
+No hay límites en la cantidad de etiquetas por repositorio, o la cantidad
+de etiquetas que una misma revisión pueda tener. Siendo prácticos, no es
+muy buena idea tener ``demasiadas'' (la cantidad variará de un
+proyecto a otro), debido a que la intención es ayudarle a encontrar
+revisiones. Si tiene demasiadas etiquetas, la facilidad de usarlas
+para identificar revisiones disminuirá rápidamente.
+
+Por ejemplo, si su proyecto tiene etapas (milestones) frecuentes, de pocos
+días, es perfectamente razonable asignarle una etiqueta a cada una de
+ellas. Pero si tiene un sistema de construcción automática de binarios
+que asegura que cada revisión puede generarse limpiamente, estaría
+introduciendo mucho ruido si se usara una etiqueta para cada generación
+exitosa. Más bien, podría usar tags para generaciones fallidas
+(\textexclamdown en
+caso de que estas sean raras!), o simplemente evitar las etiquetas para
+llevar cuenta de la posibilidad de generación de binarios.
+
+
+Si quiere eliminar una etiqueta que no desea, use
+\hgcmdargs{tag}{--remove}.  
+\interaction{tag.remove}
+También puede modificar una etiqueta en cualquier momento, para que
+identifique una revisión distinta, simplemente usando una nueva orden
+\hgcmd{tag}. Deberá usar la opción \hgopt{tag}{-f} para indicarle a
+Mercurial que \emph{realmente} desea actualizar la etiqueta.
+\interaction{tag.replace}
+De todas maneras habrá un registro permanente de la antigua identidad
+de la etiqueta, pero Mercurial no la usará. Por lo tanto no hay
+problema al marcar con una etiqueta una revisión incorrecta; lo único
+que debe hacer es mover la etiqueta hacia la revisión correcta tan
+pronto como localice el error.
+
+Mercurial almacena las etiquetas en un fichero controlado por revisiones en
+su repositorio. Si ha creado etiquetas, las encontrará en un fichero
+llamado \sfilename{.hgtags}.  Cuando invoca la orden \hgcmd{tag},
+Mercurial modifica este fichero, y hace la consignación del cambio al
+mismo automáticamente.  Esto significa que cada vez que ejecuta
+\hgcmd{tag}, verá un conjunto de cambios correspondiente en la salida
+de \hgcmd{log}.
+\interaction{tag.tip}
+
+\subsection{Manejo de conflictos entre etiquetas durante una fusión}
+
+Usualmente no tendrá que preocuparse por el fichero \sfilename{.hgtags},
+pero a veces hace su aparición durante una fusión. El formato del
+fichero es sencillo: Consiste de una serie de líneas. Cada línea
+comienza con un hash de conjunto de cambios, seguido por un espacio,
+seguido por el nombre de una etiqueta.
+
+Si está resolviendo un conflicto en el fichero \sfilename{.hgtags}
+durante una fusión, hay un detalle para tener en cuenta al modificar
+el fichero \sfilename{.hgtags}:
+cuando Mercurial procesa las etiquetas en el repositorio, \emph{nunca}
+lee la copia de trabajo del fichero \sfilename{.hgtags}.  En cambio,
+lee la versión \emph{consignada más reciente} del fichero.
+
+Una consecuencia desafortunada de este diseño es que usted no puede
+verificar que su fichero \sfilename{.hgtags} fusionado sea correcto hasta
+\emph{después} de haber consignado un cambio. Así que si se
+encuentra resolviendo un conflicto en \sfilename{.hgtags} durante una
+fusión, asegúrese de ejecutar la orden \hgcmd{tags} después de
+consignar. Si encuentra un error en el fichero \sfilename{.hgtags}, 
+la orden reportará el lugar del error, que podrá arreglar y después
+consignar. Posteriormente ejecute de nuevo la orden \hgcmd{tags} para
+asegurarse de que su arreglo fue aplicado correctamente .
+
+\subsection{Etiquetas y clonado}
+
+Puede haber notado que la orden \hgcmd{clone} tiene la opción
+\hgopt{clone}{-r} que le permite clonar una copia exacta del
+repositorio hasta un conjunto de cambios específico. El nuevo clon no
+tendrá historial posterior a la revisión que usted haya
+especificado. Esto tiene una interacción con etiquetas que puede
+sorprender a los desprevenidos.
+
+Recuerde que una etiqueta se almacena como una revisión al fichero
+\sfilename{.hgtags}, así que cuando usted crea una etiqueta, el
+conjunto de cambios en el cual ésta se almacena necesariamente se
+refiere a un conjunto de cambios anterior. Cuando ejecuta
+\hgcmdargs{clone}{-r foo} para clonar un repositorio hasta la etiqueta
+\texttt{foo}, el nuevo clon \emph{no contendrá el historial que creo
+la etiqueta} que usó para clonar el repositorio. El resultado es que tendrá
+exactamente el subconjunto correcto del historial del proyecto en el
+nuevo repositorio, pero, \emph{no} la etiqueta que podría haber esperado.
+
+\subsection{Cuando las etiquetas permanentes son demasiado}
+
+Dado que las etiquetas de Mercurial están controladas por revisiones y se
+llevan en el historial del proyecto, todas las personas involucradas
+verán las etiquetas que usted haya creado. El hecho de dar nombres a las
+revisiones tiene usos más allá que simplemente hacer notar que la
+revisión \texttt{4237e45506ee} es realmente \texttt{v2.0.2}.  Si está
+tratando de encontrar un fallo sutil, posiblemente desearía colocar una 
+etiqueta recordándole algo como ``Ana vio los síntomas en esta revisión''.
+
+Para estos casos, lo que usted posiblemente desearía serían etiquetas
+\emph{locales}. Puede crear una etiqueta local con la opción~\hgopt{tag}{-l}
+de la orden \hgcmd{tag}.  Esto guardará la etiqueta en un fichero llamado
+\sfilename{.hg/localtags}.  A diferencia de \sfilename{.hgtags},
+\sfilename{.hg/localtags} no está controlado por revisiones.
+Cualquier etiqueta que usted cree usando \hgopt{tag}{-l} se mantendrá
+local al repositorio en el que esté trabajando en ese momento.
+
+\section{El flujo de cambios---El gran cuadro vs. el pequeño}
+
+Retomando lo mencionado en el comienzo de un capítulo, pensemos en el
+hecho de que un proyecto tiene muchas piezas concurrentes de trabajo
+en desarrollo al mismo tiempo.
+
+Puede haber prisa por una nueva versión ``principal''; una nueva
+versión con un arreglo de fallo a la última versión; y una versión de
+``mantenimiento correctivo'' a una versión antigua que ha entrado en
+modo de mantenimiento.
+
+Usualmente la gente se refiere a esas direcciones
+concurrentes de desarrollo como ``ramas''.  Sin embargo, ya hemos visto que
+en varias ocasiones Mercurial trata a \emph{todo el historial} como
+una serie de ramas y fusiones.  Realmente lo que tenemos aquí es dos
+ideas que se relacionan periféricamente, pero que en esencia comparten
+un nombre.
+\begin{itemize}
+\item ``El gran cuadro'' Las ramas representan un barrido de la
+  evolución del proyecto; la gente les da nombres y hablan acerca de
+  ellas en sus conversaciones.
+\item ``El cuadro pequeño'' Las ramas son artefactos de las
+  actividades diarias de desarrollar y fusionar cambios. Exponen la
+  narrativa de cómo se desarrolló el código.
+\end{itemize}
+
+\section{Administrar ramas en repositorios estilo gran cuadro}
+
+En Mercurial la forma más sencilla de aislar una rama del ``gran
+cuadro'' es a través de un repositorio dedicado.  Si cuenta con un
+repositorio compartido existente ---llamémoslo
+\texttt{myproject}---que alcanzó la etapa ``1.0'', puede comenzar a
+prepararse para versiones de mantenimiento futuras a partir de la
+versión~1.0 marcando con una etiqueta la revisión con la cual preparó la versión~1.0.
+\interaction{branch-repo.tag}
+Ahora puede clonar un repositorio compartido nuevo
+\texttt{myproject-1.0.1} con tal etiqueta.
+\interaction{branch-repo.clone}
+
+Posteriormente, si alguien necesita trabajar en la reparación de un
+fallo debería dirigirse a la liberación de versión~1.0.1 que viene en
+camino, ellos clonarían el repositorio \texttt{myproject-1.0.1},
+harían sus cambios y los empujarían de vuelta.
+\interaction{branch-repo.bugfix}
+Mientras tanto, el desarrollo para la siguiente versión mayor puede
+continuar aislado e incólume, en el repositorio \texttt{myproject}.
+\interaction{branch-repo.new}
+
+\section{No repita trabajo: fusión entre ramas}
+
+En muchos casos, cuando tiene un fallo para arreglar en una rama de
+mantenimiento, es muy probable que el fallo también esté en la rama
+principal (y posiblemente en otras ramas de mantenimiento
+también). Solamente un desarrollador extraño desearía corregir el
+mismo fallo muchas veces, por tanto, veremos varias alternativas con
+las que Mercurial puede ayudarle a administrar tales arreglos de fallo
+sin duplicar su trabajo.
+
+En el caso más sencillo, basta con jalar los cambios de la rama de
+mantenimiento a la rama objetivo en su clon local.
+\interaction{branch-repo.pull}
+A continuación deberá mezclar las cabezas de las dos ramas, y empujar
+de nuevo a la rama principal.
+\interaction{branch-repo.merge}
+
+\section{Nombrar ramas dentro de un repositorio}
+
+La aproximación correcta en casi todas las oportunidades es aislar las
+ramas en los repositorios.  Es fácil de entender gracias a su
+simplicidad; y es difícil cometer errores. Hay una relación uno a uno
+entre las ramas y los directorios con los que está trabajando en su
+sistema. Esto le permite usar emplear herramientas usuales (que no son
+conscientes de Mercurial) para trabajar con los ficheros dentro de una
+rama/repositorio.
+
+Si se encuentra más en la categoría ``usuario diestro'' (\emph{y} sus
+colaboradores también), puede considerar otra alternativa para
+administrar las ramas. He mencionado con anterioridad la distinción a
+nivel humano entre las ramas estilo ``cuadro pequeño'' y ``gran
+cuadro''.  Mientras que Mercurial trabaja con muchas ramas del estilo
+``cuadro pequeño'' en el repositorio todo el tiempo (por ejemplo cuando
+usted jala cambios, pero antes de fusionarlos), \emph{también} puede
+trabajar con varias ramas del ``cuadro grande''.
+
+El truco para trabajar de esta forma en Mercurial se logra gracias a
+que puede asignar un \emph{nombre} persistente a una rama.  Siempre
+existe una rama llamada \texttt{default}.  Incluso antes de que
+empiece a nombrar ramas por su cuenta, puede encontrar indicios de la
+rama \texttt{default} si los busca.
+
+Por ejemplo, cuando invoca la orden \hgcmd{commit}, y se lanza su
+editor para introducir el mensaje de la consignación, busque la línea
+que contiene el texto ``\texttt{HG: branch default}'' al final. Le
+está indicando que su consignación ocurrirá en la rama llamada 
+\texttt{default}.
+
+Use la orden \hgcmd{branches} para empezar a trabajar con ramas
+nombradas. Esta orden mostrará las ramas presentes en su repositorio,
+indicándole qué conjunto de cambios es la punta de cada una.
+\interaction{branch-named.branches}
+Dado que todavía no ha creado ramas nombradas, la única que verá será
+\texttt{default}.
+
+Para hallar cuál es la rama ``actual'', invoque la orden
+\hgcmd{branch}, sin argumento alguno. Le informará en qué rama se
+encuentra el padre del conjunto de cambios actual.
+\interaction{branch-named.branch}
+
+Para crear una nueva rama, invoque la orden \hgcmd{branch} de
+nuevo. En esta oportunidad, ofrezca un argumento: el nombre de la rama
+que desea crear.
+\interaction{branch-named.create}
+
+Después de crear la rama, usted podría desear ver el efecto que tuvo
+la orden \hgcmd{branch}.  ¿Qué reportan las ordenes \hgcmd{status} y
+\hgcmd{tip}?
+\interaction{branch-named.status}
+Nada cambia en el directorio actual, y no se ha añadido nada al
+historial. Esto sugiere que al ejecutar la orden \hgcmd{branch} no hay
+un efecto permanente; solamente le indica a que nombre de rama usará
+la \emph{próxima} vez que consigne un conjunto de cambios.
+
+Cuando consigna un cambio, Mercurial almacena el nombre de la rama en
+la cual consignó.  Una vez que haya cambiado de la rama \texttt{default}
+y haya consignado, verá que el nombre de la nueva rama se mostrará
+cuando use la orden \hgcmd{log}, \hgcmd{tip}, y otras órdenes que
+desplieguen la misma clase de información.
+\interaction{branch-named.commit}
+Las órdenes del tipo \hgcmd{log} imprimirán el nombre de la rama de
+cualquier conjunto de cambios que no esté en la rama
+\texttt{default}. Como resultado, si nunca usa ramas nombradas, nunca
+verá esta información.
+
+Una vez que haya nombrado una rama y consignado un cambio con ese
+nombre, todas las consignaciones subsecuentes que desciendan de ese
+cambio heredarán el mismo nombre de rama. Puede cambiar el nombre de
+una rama en cualquier momento con la orden \hgcmd{branch}.  
+\interaction{branch-named.rebranch}
+Esto es algo que no hará muy seguido en la práctica, debido que los
+nombres de las ramas tienden a tener vidas largas.  (Esto no es una
+regla, solamente una observación.)
+
+\section{Tratamiento de varias ramas nombradas en un repositorio}
+
+Si tiene más de una rama nombrada en un repositorio, Mercurial
+recordará la rama en la cual está su directorio de trabajo cuando
+invoque una orden como \hgcmd{update} o \hgcmdargs{pull}{-u}.  Se
+actualizará su directorio de trabajo actual a la punta de esta rama, sin
+importar cuál sea la punta ``a lo largo del repositorio''.  Para
+actualizar a una revisión que está en una rama con distinto nombre,
+puede necesitar la opción \hgopt{update}{-C} de \hgcmd{update}.
+
+Este comportamiento puede ser sutil, así que veámoslo en acción.  Primero,
+recordemos en qué rama estamos trabajando, y qué ramas están en
+nuestro repositorio.
+\interaction{branch-named.parents}
+Estamos en la rama \texttt{bar}, pero existe otra rama más antigua
+llamada \hgcmd{foo}.
+
+Podemos hacer \hgcmd{update} entre los tipos de las ramas \texttt{foo}
+y \texttt{bar} sin necesidad de usar la opción \hgopt{update}{-C},
+puesto que esto solamente implica ir linealmente hacia adelante y
+atrás en nuestro historial de cambios.
+\interaction{branch-named.update-switchy}
+
+Si volvemos a la rama \texttt{foo} e invocamos la orden \hgcmd{update},
+nos mantendrá en \texttt{foo}, sin movernos a la punta de \texttt{bar}.
+\interaction{branch-named.update-nothing}
+
+Al consignar un cambio a la rama \texttt{foo} se introducirá una nueva
+cabeza.
+\interaction{branch-named.foo-commit}
+
+\section{Nombres de ramas y fusiones}
+
+Posiblemente ha notado que las fusiones en Mercurial no son simétricas.
+Supongamos que su repositorio tiene dos cabezas, 17 y 23.  Si yo invoco
+\hgcmd{update} a 17 y aplico \hgcmd{merge} a 23, Mercurial almacena 17
+como el primer padre de la fusión, y 23 como el segundo. Mientras que
+si hago \hgcmd{update} a 23 y después aplico \hgcmd{merge} con 17,
+grabará a 23 como el primer padre, y 17 como el segundo.
+
+Esto afecta el cómo elige Mercurial el nombre de la rama cuando usted
+hace la fusión.  Después de una fusión, Mercurial mantendrá el nombre de la
+rama del primer padre cuando consigne el resultado de la fusión.  Si
+el primer nombre de su padre es \texttt{foo}, y fusiona con
+\texttt{bar}, el nombre de la rama continuará siendo \texttt{foo}
+después de fusionar.
+
+No es inusual que un repositorio contenga varias cabezas, cada una con
+el mismo nombre de rama.  Digamos que estoy trabajando en la rama
+\texttt{foo}, y usted también.  Consignamos cambios distintos; yo jalo
+sus cambios; Ahora tengo dos cabezas, cada una afirmando estar en la
+rama \texttt{foo}.  El resultado de una fusión será una única cabeza
+en la rama \texttt{foo} como usted esperaría.
+
+Pero si estoy trabajando en la rama \texttt{bar}, y fusiono el trabajo
+de la rama \texttt{foo}, el resultado permanecerá en la rama
+\texttt{bar}.
+\interaction{branch-named.merge}
+
+En un ejemplo más concreto, si yo estoy trabajando en la rama
+\texttt{bleeding-edge}, y deseo traer los arreglos más recientes de la
+rama \texttt{estable}, Mercurial elegirá el nombre de rama ``correcto''
+(\texttt{bleeding-edge}) cuando yo jale una fusión desde \texttt{estable}.
+
+\section{Normalmente es útil nombrar ramas}
+
+No debería considerar que las ramas nombradas son aplicables
+únicamente en situaciones con muchas ramas de larga vida cohabitando
+en un mismo repositorio.  Son muy útiles incluso en los casos de
+una rama por repositorio.
+
+En el caso más sencillo, dar un nombre a cada rama ofrece un registro
+permanente acerca de en qué conjunto de cambios se generó la rama.
+Esto le ofrece más contexto cuando esté tratando de seguir el
+historial de un proyecto ramificado de larga vida.
+
+Si está trabajando con repositorios compartidos, puede configurar el gancho
+\hook{pretxnchangegroup} para que cada uno bloquee los cambios con
+nombres de rama ``incorrectos'' que están por adicionarse.  Este
+provee una defensa sencilla, pero efectiva, para evitar que la gente
+publique accidentalmente cambios de una rama ``super nueva'' a la rama
+``estable''.  Tal gancho podría verse de la siguiente forma dentro de
+un repositorio compartido de \hgrc.
+\begin{codesample2}
+  [hooks]
+  pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch
+\end{codesample2}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/cmdref.py	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1 @@
+../en/cmdref.py
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/cmdref.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,186 @@
+\chapter{Referencia de Órdenes}
+\label{cmdref}
+
+\cmdref{add}{Añade ficheros en la próxima consignación}
+\optref{add}{I}{include}
+\optref{add}{X}{exclude}
+\optref{add}{n}{dry-run}
+
+\cmdref{diff}{imprime los cambios en el historial o el directorio actual}
+
+Mostrar las diferencias entre revisiones para ficheros especificados o
+directorios, con el formato unificado diff.  Si desea ver una
+descripción del formato unificado diff, ver la sección~\ref{sec:mq:patch}.
+
+De forma predeterminada, esta orden no imprime las diferencias para
+los ficheros binarios que Mercurial esté siguiendo.  Para controlar
+este comportamiento, vea las opciones \hgopt{diff}{-a} y
+\hgopt{diff}{--git}.
+
+\subsection{Options}
+
+\loptref{diff}{nodates}
+
+Omite la fecha y hora cuando se muestran los encabezados de las
+diferencias.
+
+\optref{diff}{B}{ignore-blank-lines}
+
+No imprime los cambios que solamente insertan o eliminan líneas en
+blanco.  Una línea que contiene espacios en blanco no se considera
+como una línea en blanco.
+
+\optref{diff}{I}{include}
+
+Incluye ficheros y directorios cuyos nombres coinciden con los
+patrones elegidos.
+
+\optref{diff}{X}{exclude}
+
+Excluye los ficheros y directorios cuyos nombres coinciden con los
+patrones elegidos.
+
+\optref{diff}{a}{text}
+
+Si no especifica esta opción, \hgcmd{diff} no mostrará las diferencias
+de los ficheros que detecte como binarios.  Al especificar \hgopt{diff}{-a}
+se forza a \hgcmd{diff} a tratar los ficheros como texto, y generar
+diferencias para todos.
+
+Esta opción es útil para los ficherso que son ``texto en mayor
+medida'' pero que tienen caracteres NUL.  Si lo usa en ficheros que
+contienen muchos datos binarios, la salida será incomprensible.
+
+\optref{diff}{b}{ignore-space-change}
+
+No imprime si el único cambio que en la línea es la cantidad de
+espacio en blanco.
+
+\optref{diff}{g}{git}
+
+Mostrar diferencias compatibles con \command{git}.  XXX reference a format
+description.
+
+\optref{diff}{p}{show-function}
+
+Mostrar el nombre de la función que contiene el código en una porción
+del encabzado usando una heurística simple.  Esta funcionalidad se
+habilita de forma predeterminada, así que la opción \hgopt{diff}{-p}
+no tiene efectos a menos que cambie el valor de
+\rcitem{diff}{showfunc} en la configuración, como en el ejemplo
+siguiente.
+\interaction{cmdref.diff-p}
+
+\optref{diff}{r}{rev}
+
+Especifique una o más revisiones para comparar.  La orden \hgcmd{diff}
+acepta hasta dos opciones \hgopt{diff}{-r} para especificar las
+revisiones a comparar.
+
+\begin{enumerate}
+\setcounter{enumi}{0}
+\item Despliega las diferencias entre la revisión padre y del directorio
+  de trabajo.
+\item Despliega las diferencias entre el conjunto de cambios
+  especificados y el directorio de trabajo.
+\item Despliega las diferencias entre dos conjuntos de cambios
+  especificados.
+\end{enumerate}
+
+Puede especificar dos revisiones usando o bien sea las opciones
+\hgopt{diff}{-r} o la notación de rango.  Por ejemplo, las dos
+especificaciones de revisiones a continuación son equivalentes:
+\begin{codesample2}
+  hg diff -r 10 -r 20
+  hg diff -r10:20
+\end{codesample2}
+
+Cuando especifica dos revisiones, esto tiene significado para
+Mercurial.  Esto significa que \hgcmdargs{diff}{-r10:20} producirá un
+diff que transformará los ficheros desde los contenidos en la revisión
+10 a los contenidos de la revisión 20, mientras que
+\hgcmdargs{diff}{-r20:10} significa lo opuesto:  el diff que
+transformaría los contenidos de los ficheros de la revisión 20 a los
+contenidos de la revisión 10.  No puede invertir el orden de esta
+forma si está haciendo un diff frente al directorio de trabajo.
+
+\optref{diff}{w}{ignore-all-space}
+
+\cmdref{version}{imprime la información de versión y derechos de reproducción}
+
+Esta orden despliega la versión de Mercurial que está usando, y su
+nota de derechos de reproducción.  Hay cuatro clases de cadenas de
+versión posibles:
+\begin{itemize}
+\item La cadena ``\texttt{unknown}''. Esta versión de Mercurial no fue
+  construida en un repositorio de Mercurial, y no puede determinar su
+  propia versión.
+\item Una cadena numérica corta, tal como ``\texttt{1.1}''. Esta es
+  una construcción de una versión de Mercurial que se identifica con
+  una etiqueta específica en el repositorio en el cual fue
+  armada (Esto no significa necesariamente que está ejecutando una
+  versión oficial; alguien pudo haber añadido tal etiqueta a cualquier
+  versión del repositorio en el cual armaron Mercurial).
+\item Una cadena hexadecimal, tal como ``\texttt{875489e31abe}''.
+  Esta es una construcción de una revisión dada de Mercurial.
+\item Una cadena hexadecimal seguida por una fecha, tal como
+  ``\texttt{875489e31abe+20070205}''.  Esta construcción de la
+  revisión de Mercurial fue la construcción de un repositorio que tuvo
+  cambios locales que no han sido consignados.
+\end{itemize}
+
+\subsection{Consejos y trucos}
+
+\subsubsection{¿Por qué difieren los resultados de \hgcmd{diff} y
+  \hgcmd{status}?}
+\label{cmdref:diff-vs-status}
+
+Cuando ejecuta la orden \hgcmd{status}, verá una lista de ficheros
+para los cuales Mercurial almacenará cambios la próxima vez que
+consigne.  Si ejecuta la orden \hgcmd{diff}, verá que imprime
+diferencias solamente para un \emph{subconjunto} de los ficheros que
+\hgcmd{status} liste.  Hay dos posibles razones para este comportamiento:
+
+La primera es que \hgcmd{status} imprime cierta clase de
+modificaciones que \hgcmd{diff} no despliega normalmente.  La orden
+\hgcmd{diff} usualmente despliega diferencias unificadas, las cuales
+no tienen la habilidad de representar algunos cambios que Mercurial
+puede seguir.  Lo más notable es que las diferencias tradicionales no
+pueden representar un cambio acerca de la ejecutabilidad de un
+fichero, pero Mercurial sí almacena esta información.
+
+Si usa la opción \hgopt{diff}{--git} de \hgcmd{diff}, mostrará
+diferencias compatibles con \command{git} que \emph{pueden} desplegar
+esta información adicional.
+
+La segunda razón posible para que \hgcmd{diff} esté imprimiendo
+diferencias para un subconjunto de ficheros de lo que muestra
+\hgcmd{status} es que si usted le invoca sin argumento alguno,
+\hgcmd{diff} imprime diferencias frente al primer padre del directorio
+de trabajo.  Si ha ejecutado \hgcmd{merge} para fusionar dos conjuntos
+de cambios, pero no ha consignado aún los resultados de la fusión,  su
+directorio de trabajo tiene dos padres (use \hgcmd{parents} para
+verlos).  Mientras que \hgcmd{status} imprime modificaciones relativas
+a \emph{ambos} padres después de una fusión que no se ha consignado,
+\hgcmd{diff} opera aún relativo solamente al primer padre.  Puede
+lograr que imprima las diferencias relativas al segundo padre
+especificando tal padre con la opción \hgopt{diff}{-r}.  No hay forma
+de hacer que imprima las diferencias relativas a los dos padres.
+
+\subsubsection{Generar diferencias seguras en binarios}
+
+Si usa la opción \hgopt{diff}{-a} para forzar que Mercurial imprima
+las diferencias de los ficheros que so o bien ``casi completamente
+texto'' o contienen muchos datos binarios, tales diferencias no pueden
+aplicarse subsecuentemente a la orden \hgcmd{import} de Mercurial o a
+la orden \command{patch} del sistema.
+
+Si desea generar una diferencia de un fichero binario que es seguro
+para usarlo como entrada a la orden \hgcmd{import}, use la opción
+\hgcmd{diff}{--git} cuando genere el parche.  La orden \command{patch}
+del sistema no puede tratar con parches binarios.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/collab.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1059 @@
+\chapter{Colaborar con otros}
+\label{cha:collab}
+
+Debido a su naturaleza descentralizada, Mercurial no impone política
+alguna de cómo deben trabajar los grupos de personas. Sin embargo, si
+usted es nuevo al control distribuido de versiones, es bueno tener
+herramientas y ejemplos a la mano al pensar en posibles modelos de
+flujo de trabajo.
+
+\section{La interfaz web de Mercurial}
+
+Mercurial tiene una poderosa interfaz web que provee bastantes
+capacidades útiles.
+
+Para uso interactivo, la interfaz le permite visualizar uno o varios
+repositorios. Puede ver el historial de un repositorio, examinar cada
+cambio (comentarios y diferencias), y ver los contenidos de cada
+directorio y fichero.
+
+Adicionalmente la interfaz provee notificaciones RSS de los cambios de los
+repositorios. Que le permite ``subscribirse''a un repositorio usando
+su herramienta de lectura de notificaciones favorita, y ser notificado
+automáticamente de la actividad en el repositorio tan pronto como
+sucede. Me gusta mucho más este modelo que el estar suscrito a una
+lista de correo a la cual se envían las notificaciones, dado que no
+requiere configuración adicional de parte de quien sea que está
+administrando el repositorio.
+
+La interfaz web también permite clonar repositorios a los usuarios
+remotos, jalar cambios, y (cuando el servidor está configurado para
+permitirlo) publicar cambios en el mismo.  El protocolo de entunelamiento
+de Mercurial comprime datos agresivamente, de forma que trabaja
+eficientemente incluso con conexiones de red con poco ancho de banda.
+
+La forma más sencilla de iniciarse con la interfaz web es usar su
+navegador para visitar un repositorio existente, como por ejemplo el
+repositorio principal de Mercurial \url{http://www.selenic.com/repo/hg?style=gitweb}.
+
+Si está interesado en proveer una interfaz web a sus propios
+repositorios, Mercurial provee dos formas de hacerlo.  La primera es
+usando la orden \hgcmd{serve}, que está enfocada a servir ``de forma
+liviana'' y por intervalos cortos.  Para más detalles de cómo usar
+esta orden vea la sección~\ref{sec:collab:serve} más adelante. Si
+tiene un repositorio que desea hacer permanente, Mercurial tiene
+soporte embebido del \command{ssh} para publicar cambios con seguridad
+al repositorio central, como se documenta en la
+sección~\ref{sec:collab:ssh}.  Es muy usual que se publique una copia
+de sólo lectura en el repositorio que está corriendo sobre HTTP usando
+CGI, como en la sección~\ref{sec:collab:cgi}.  Publicar sobre HTTP
+satisface las necesidades de la gente que no tiene permisos de
+publicación y de aquellos que quieren usar navegadores web para
+visualizar el historial del repositorio.
+
+\subsection{Trabajo con muchas ramas}
+
+Los proyectos de cierta talla tienden naturalmente a progresar de
+forma simultánea en varios frentes. En el caso del software, es común
+que un proyecto tenga versiones periódicas oficiales. Una versión
+puede entrar a ``modo mantenimiento'' por un tiempo después de su
+primera publicación; las versiones de mantenimiento tienden a contener
+solamente arreglos de fallos, pero no nuevas características. En
+paralelo con las versiones de mantenimiento puede haber una o muchas
+versiones futuras pueden estar en desarrollo. La gente usa normalmente
+la palabra ``rama'' para referirse a una de las direcciones
+ligeramente distintas en las cuales procede el desarrollo.
+
+Mercurial está especialmente preparado para administrar un buen número
+de ramas simultáneas pero no idénticas. Cada ``dirección de
+desarrollo'' puede vivir en su propio repositorio central, y puede
+mezclar los cambios de una a otra de acuerdo con las necesidades. Dado
+que los repositorios son independientes, uno del otro, los cambios
+inestables de una rama de desarrollo nunca afectarán una rama estable
+a menos que alguien explícitamente mezcle los cambios.
+
+A continuación un ejemplo de cómo podría hacerse esto en la
+práctica. Digamos que tiene una ``rama principal'' en un servidor
+central.
+\interaction{branching.init}
+Alguien lo clona, hace cambios locales, los prueba, y los publica allí
+mismo.
+
+Una vez que la rama principal alcanza una estado de versión se puede
+usar la orden \hgcmd{tag} para dar un nombre permanente a la revisión.
+\interaction{branching.tag}
+Digamos que en la rama principal ocurre más desarrollo.
+\interaction{branching.main}
+Cuando se usa la etiqueta con que se identificó la versión, la gente
+puede clonar el repositorio en cualquier momento en el futuro
+empleando \hgcmd{update} para obtener una copia del directorio de
+trabajo exacta como cuando se creó la etiqueta de la revisión que se
+consignó.
+\interaction{branching.update}
+
+Adicionalmente, justo después de que la rama principal se etiquete,
+alguien puede clonarla en el servidor a una nueva rama ``estable'',
+también en el servidor.
+\interaction{branching.clone}
+
+Alguien que requiera hacer un cambio en la rama estable puede clonar
+\emph{ese} repositorio, hacer sus cambios, consignar y publicarlos
+posteriormente al inicial.
+\interaction{branching.stable}
+Puesto que los repositorios de Mercurial son independientes, y que
+Mercurial no mueve los cambios de un lado a otro automáticamente, las
+ramas estable y principal están \emph{aisladas} la una de la otra.
+Los cambios que haga en la rama principal no ``se filtran'' a la rama
+estable o vice versa.
+
+Es usual que los arreglos de fallos de la rama estable deban hacerse
+aparecer en la rama principal también.  En lugar de reescribir el
+arreglo del fallo en la rama principal, puede jalar y mezclar los
+cambios de la rama estable a la principal, Mercurial traerá tales
+arreglos por usted.
+\interaction{branching.merge}
+La rama principal contendrá aún los cambios que no están en la
+estable y contendrá además todos los arreglos de fallos de la rama
+estable.  La rama estable permanece incólume a tales cambios.
+
+\subsection{Ramas de Características}
+
+En proyectos grandes, una forma efectiva de administrar los cambios es
+dividir el equipo en grupos más pequeños. Cada grupo tiene una rama
+compartida, clonada de una rama ``principal'' que conforma el proyecto
+completo.   Aquellos que trabajan en ramas individuales típicamente
+están aislados de los desarrollos de otras ramas.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{feature-branches}
+  \caption{Ramas de Características}
+  \label{fig:collab:feature-branches}
+\end{figure}
+
+Cuando una rama particular alcanza un estado deseado, alguien del
+equipo de características jala y fusiona de la rama principal hacia
+la rama de características y publica posteriormente a la rama principal.
+
+\subsection{El tren de publicación}
+
+Algunos proyectos se organizan al estilo``tren'': Una versión se
+planifica para ser liberada cada cierto tiempo, y las características
+que estén listas cuando ha llegado el momento ``tren'', se incorporan.
+
+Este modelo tiene cierta similitud a las ramas de características. La
+diferencia es que cuando una característica pierde el tren, alguien en
+el equipo de características jala y fusiona los cambios que se fueron
+en la versión liberada hacia la rama de característica, y el trabajo
+continúa sobre lo fusionado para que la característica logre estar en
+la próxima versión.
+
+\subsection{El modelo del kernel linux}
+
+El desarrollo del Kernel Linux tiene una estructura jerárquica
+bastante horizontal, rodeada de una nube de caos aparente. Dado que la
+mayoría de desarrolladores usan \command{git}, una herramienta distribuida
+de control de versiones con capacidades similares a Mercurial, resulta
+de utilidad describir la forma en que el trabajo fluye en tal
+ambiente; si le gustan las ideas, la aproximación se traduce bien
+entre Git y Mercurial.
+
+En el centro de la comunidad está Linus Torvalds, el creador de Linux.
+Él publica un único repositorio que es considerado el árbol
+``oficial'' actual por la comunidad completa de
+desarrolladores. Cualquiera puede clonar el árbol de Linus, pero él es
+muy selectivo acerca de los árboles de los cuales jala.
+
+Linus tiene varios ``lugartenientes confiables''.  Como regla, él jala
+todos los cambios que ellos publican, en la mayoría de los casos sin
+siquiera revisarlos.  Algunos de sus lugartenientes generalmente
+aceptan ser los ``mantenedores'', responsables de subsistemas
+específicos dentro del kernel.  Si un hacker cualquiera desea hacer un
+cambio a un subsistema y busca que termine en el árbol de Linus, debe
+encontrar quién es el mantenedor del subsistema y solicitarle que
+tenga en cuenta su cambio.  Si el mantenedor revisa los cambios y está
+de acuerdo en tomarlos, estos pasarán al árbol de Linus de acuerdo a
+lo expuesto.
+
+Cada lugarteniente tiene su forma particular de revisar, aceptar y
+publicar los cambios; y para decidir cuando hacerlos presentes a
+Linus.  Adicionalmente existen varias ramas conocidas que mucha gente
+usa para propósitos distintos. Por ejemplo, pocas personas mantienen
+repositorios ``estables'' de versiones anteriores del kernel, a los
+cuales aplican arreglos de fallos críticos necesarios. Algunos
+mantenedores publican varios árboles: uno para cambios
+experimentales; uno para cambios que van a ofrecer al mantenedor
+principal; y así sucesivamente. Otros publican un solo árbol.
+
+Este modelo tiene dos características notables. La primera es que son
+de ``jalar exclusivamente''.  Usted debe solicitar, convencer o
+incluso rogar a otro desarrollador para que tome sus cambios, porque
+casi no hay árboles en los cuales más de una persona pueda publicar, y
+no hay forma de publicar cambios en un árbol que otra persona controla.
+
+El segundo está basado en reputación y meritocracia.  Si usted es un
+desconocido, Linus probablemente ignorará sus cambios, sin siquiera
+responderle.  Pero un mantenedor de un subsistema probablemente los
+revisara, y los acogerá en caso de que aprueben su criterio de
+aplicabilidad.  A medida que usted ofrezca ``mejores'' cambios a un
+mantenedor, habrá más posibilidad de que se confíe en su juicio y se
+acepten los cambios.   Si usted es reconocido y mantiene una rama
+durante bastante tiempo para algo que Linus no ha aceptado, personas
+con intereses similares pueden jalar sus cambios regularmente para
+estar al día con su trabajo.
+
+La reputación y meritocracia no necesariamente es transversal entre
+``personas'' de diferentes subsistemas.  Si usted es respetado pero es
+un hacker en almacenamiento y trata de arreglar un fallo de redes,
+tal cambio puede recibir un nivel de escrutinio de un mantenedor de
+redes comparable con el que se le haría a un completo extraño.
+
+Personas que vienen de proyectos con un ordenamiento distinto, sienten
+que el proceso comparativamente caótico del Kernel Linux es
+completamente lunático.  Es objeto de los caprichos individuales; la
+gente desecha cambios cuando lo desean; y la fase de desarrollo es
+alucinante. A pesar de eso Linux es una pieza de software exitosa y
+bien reconocida.
+
+\subsection{Solamente jalar frente a colaboración pública}
+
+Una fuente perpetua de discusiones en la comunidad de código abierto
+yace en el modelo de desarrollo en el cual la gente solamente jala
+cambios de otros ``es mejor que'' uno  en el cual muchas personas
+pueden publicar cambios a un repositorio compartido.
+
+Típicamente los partidarios del modelo de publicar usan las herramientas
+que se apegan a este modelo.  Si usted usa una herramienta
+centralizada de control de versiones como Subversion, no hay forma de
+elegir qué modelo va a usar: La herramienta le ofrece publicación
+compartida, y si desea hacer cualquier otra cosa, va a tener que
+aplicar una aproximación artificial (tal como aplicar parches a mano).
+
+Una buena herramienta distribuida de control de versiones, tal como
+Mercurial soportará los dos modelos.   Usted y sus colaboradores
+pueden estructurar cómo trabajarán juntos basados en sus propias
+necesidades y preferencias,  sin depender de las peripecias que la
+herramienta les obligue a hacer.
+
+\subsection{Cuando la colaboración encuentra la administración ramificada}
+
+Una vez que usted y su equipo configurar algunos repositorios
+compartidos y comienzan a propagar cambios entre sus repositorios
+locales y compartidos, comenzará a encarar un reto relacionado, pero
+un poco distinto:  Administrar las direcciones en las cuales su equipo
+puede moverse.   A pesar de que está íntimamente ligado acerca de cómo
+interactúa su equipo, es lo suficientemente denso para ameritar un
+tratamiento en el capítulo~\ref{chap:branch}.
+
+\section{Aspectos técnicos de la colaboración}
+
+Lo que resta del capítulo lo dedicamos a las cuestiones de servir
+datos a sus colaboradores.
+
+\section{Compartir informalmente con \hgcmd{serve}}
+\label{sec:collab:serve}
+
+La orden \hgcmd{serve} de Mercurial satisface de forma espectacular
+las necesidades de un grupo pequeño, acoplado y de corto
+tiempo.  Se constituye en una demostración de cómo se siente usar los
+comandos usando la red.
+
+Ejecute \hgcmd{serve} dentro de un repositorio, y en pocos segundos
+iniciará un servidor HTTP especializado; aceptará conexiones desde
+cualquier cliente y servirá datos de este repositorio mientrs lo
+mantenga funcionando. Todo el que sepa el URL del servidor que ha
+iniciado, y que puede comunicarse con su computador por la red, puede
+usar un navegador web o Mercurial para leer datos del repositorio. Un
+URL para una instancia de \hgcmd{serve} ejecutándose en un portátil
+debería lucir algo \Verb|http://my-laptop.local:8000/|.
+
+La orden \hgcmd{serve} \emph{no} es un servidor web de propósito
+general. Solamente puede hacer dos cosas:
+\begin{itemize}
+\item Permitir que se pueda visualizar el historial del repositorio que
+  está sirviendo desde navegadores web.
+\item Hablar el protocolo de conexión de Mercurial para que puedan hacer
+  \hgcmd{clone} o \hgcmd{pull} (jalar) cambios de tal repositorio.
+\end{itemize}
+En particular, \hgcmd{serve} no permitirá que los usuarios remotos
+puedan \emph{modificar} su repositorio.  Es de tipo solo lectura.
+
+Si está comenzando con Mercurial, no hay nada que le impida usar
+\hgcmd{serve} para servir un repositorio en su propio computador, y
+usar posteriormente órdenes como \hgcmd{clone}, \hgcmd{incoming}, para
+comunicarse con el servidor como si el repositorio estuviera alojado
+remotamente. Lo que además puede ayudarle a adecuarse rápidamente para
+usar comandos en repositorios alojados en la red.
+
+\subsection{Cuestiones adicionales para tener en cuenta}
+
+Dado que permite lectura sin autenticación a todos sus clientes,
+debería usar \hgcmd{serve} exclusivamente en ambientes en los cuáles
+no tenga problema en que otros vean, o en los cuales tenga control
+completo acerca de quien puede acceder a su red y jalar cambios de su
+repositorio.
+
+La orden \hgcmd{serve} no tiene conocimiento acerca de programas
+cortafuegos que puedan estar instalados en su sistema o en su red. No
+puede detectar o controlar sus cortafuegos.  Si otras personas no
+pueden acceder a su instancia \hgcmd{serve}, lo siguiente que debería hacer
+(\emph{después} de asegurarse que tienen el URL correcto) es verificar
+su configuración de cortafuegos.
+
+De forma predeterminada, \hgcmd{serve} escucha conexiones entrantes en
+el puerto~8000.  Si otro proceso está escuchando en tal puerto, usted
+podrá especificar un puerto distinto para escuchar con la opción
+\hgopt{serve}{-p}.
+
+Normalmente, cuando se inicia \hgcmd{serve}, no imprime nada, lo cual
+puede ser desconcertante.  Si desea confirmar que en efecto está
+ejecutándose correctamente, y darse cuenta qué URL debería enviar a
+sus colaboradores, inícielo con la opción \hggopt{-v}.
+
+\section{Uso del protocolo Secure Shell (ssh)}
+\label{sec:collab:ssh}
+
+Usted puede publicar y jalar cambios en la red de forma segura usando
+el protocolo Secure Shell (\texttt{ssh}).  Para usarlo satisfactoriamente,
+tendrá que hacer algo de configuración a nivel de cliente o el
+servidor.
+
+Si no está familiarizado con ssh, es un protocolo de red que le permite
+comunicarse con seguridad con otro computador.  Para usarlo con
+Mercurial, estará estableciendo una o más cuentas de usuario en un
+servidor de forma tal que los usuarios remotos puedan entrar y
+ejecutar órdenes.
+
+(Si ssh le \emph{es} familiar, encontrará probablemente elemental una
+porción del material a continuación.)
+
+\subsection{Cómo leer y escribir URLs de ssh}
+
+Los URLs de ssh tienden a lucir de la siguiente forma:
+\begin{codesample2}
+  ssh://bos@hg.serpentine.com:22/hg/hgbook
+\end{codesample2}
+\begin{enumerate}
+\item La parte ``\texttt{ssh://}'' indica a Mercurial que use el
+  protocolo ssh.
+\item El componente ``\texttt{bos@}'' indica el nombre del usuario que
+  está entrando al servidor.  Puede omitirlo si el usuario remoto
+  coincide con el usuario local.
+\item ``\texttt{hg.serpentine.com}'' es el nombre del servidor al cual
+  se desea entrar.
+\item El ``:22'' identifica el número del puerto en el servidor al cual
+  se conectará.  El predeterminado es el~22, así que solamente
+  necesitará especificar esa porción si \emph{no} está usando el
+  puerto~22.
+\item La última porción del URL es la ruta local al repositorio en el
+  servidor.
+\end{enumerate}
+
+El componente de la ruta del URL para ssh es una fuente de confusión,
+puesto que no hay una forma estándar para que las herramientas puedan
+interpretarlo.  Algunos programas se comportan de manera distinta a
+otros cuando manipulan estas rutas.  No es la situación ideal, pero
+es muy poco probable que vaya a cambiar.  Por favor lea los párrafos
+siguientes cuidadosamente.
+
+Mercurial trata la ruta al repositorio en el servidor como relativo al
+directorio personal del usuario remoto.  Por ejemplo, si el usuario
+\texttt{foo} en el servidor tiene el directorio casa
+\dirname{/home/foo},
+entonces un URL ssh que contenga en su ruta a \dirname{bar}
+\emph{realmente} se refiere al directorio \dirname{/home/foo/bar}.
+
+Si desea especificar una ruta relativa a otro directorio de usuario,
+puede usar una ruta que comience con un caracter tildado, seguido del
+nombre del usuario (llamémosle \texttt{otrousuario}, así
+\begin{codesample2}
+  ssh://server/~otrousuario/hg/repo
+\end{codesample2}
+
+Y si realmente desea especifica una ruta \emph{absoluta} en el
+servidor, comience con el componente de la ruta con dos barras como
+en el siguiente ejemplo:
+\begin{codesample2}
+  ssh://server//absolute/path
+\end{codesample2}
+
+\subsection{Encontrar un cliente ssh para su sistema}
+
+Casi todos los sistemas tipo Unix vienen con OpenSSH preinstalado.  Si
+usted está usando un sistema de estos, ejecute \Verb|which ssh| para
+identificar dónde está instalada la orden \command{ssh} (usualmente
+estará en \dirname{/usr/bin}).  Si por casualidad no está presente,
+vea la documentación de sus sistema para lograr instalarlo.
+
+En Windows, tendrá que escoger primero un cliente adecuado para
+descargarlo.  Hay dos alternativas:
+\begin{itemize}
+\item El excelente paquete PuTTY~\cite{web:putty} de Simon Tatham, que
+  ofrece un suite completo de órdenes de cliente ssh.
+\item Si tiene alta tolerancia al dolor, puede usar el porte de Cygwin
+  para OpenSSH.
+\end{itemize}
+En cualquier caso, tendrá que editar su fichero \hgini\ para indicarle
+a Mercurial dónde encontrar la orden real del cliente.  Por ejemplo, si
+está usando PuTTY, tendrá que usar la orden \command{plink} como un
+cliente de línea de órdenes.
+\begin{codesample2}
+  [ui]
+  ssh = C:/ruta/a/plink.exe -ssh -i "C:/ruta/a/mi/llave/privada"
+\end{codesample2}
+
+\begin{note}
+  La ruta a \command{plink} no debería contener espacios o caracteres
+  en blanco, o Mercurial no podrá encontrarlo correctamente (por lo
+  tanto, probablemente no sería buena idea colocarlo en 
+  \dirname{C:\\Program Files}
+\end{note}
+
+\subsection{Generar un par de llaves}
+
+Para evitar la necesidad de teclear una clave de forma repetitiva cada
+vez que necesita usar el cliente, recomiendo generar un par de llaves.
+En un sistema tipo Unix, la orden \command{ssh-keygen} también se
+comportará bien. En Windows, si está usando PuTTY, la orden
+\command{puttygen} es la que necesitará.
+
+Cuando genera un par de llaves, se aconseja \emph{comedidamente} 
+protegerlas con una frase de clave.  (La única oportunidad en la cual
+usted querría identificarse una única vez, es cuando está usando
+el protocolo ssh para tareas automatizadas en una red segura.)
+
+No basta con generar un par de llaves.  Se requiere adicionar una llave
+pública al conjunto de llaves autorizadas para todos los usuarios
+remotos que se vayan a autenticar.  Para aquellos servidores que usen
+OpenSSH (la gran mayoría), significará añadir la llave pública a la
+lista en el fichero llamado \sfilename{authorized\_keys} en su
+directorio \sdirname{.ssh}.
+
+En sistemas tipo Unix, su llave pública tendrá la extensión
+\filename{.pub}.  Si usa \command{puttygen} en Windows, puede
+guardar la llave pública en un fichero de su elección, o pegarla desde
+la ventana en la cual se despliega directamente en el fichero
+\sfilename{authorized\_keys}.
+
+\subsection{Uso de un agente de autenticación}
+
+Un agente de autenticación es un demonio que almacena frases clave en
+memoria (olvidará las frases clave si sale y vuelve a entrar).  Un cliente
+ssh notará si está corriendo, y solicitará una frase clave.  Si no hay
+un agente de autenticación corriendo, o el agente no almacena la frase
+clave necesaria, tendrá que teclear su frase clave cada vez que 
+Mercurial intente comunicarse con un servidor para usted (p.e.~cada vez
+que jale o publique cambios).
+
+El problema de almacenar frases claves en un agente es que es posible
+para un atacante bien preparado recuperar el texto plano de su frase
+clave, en algunos casos incluso si su sistema sea muy alternante.
+Es su decisión si es un riesgo aceptable.  Lo que si es seguro es que
+evita reteclear.
+
+En sistemas tipo Unix, el agente se llama \command{ssh-agent}, y
+usualmente se ejecuta automáticamente cuando usted entra.  Tendrá que
+usar la orden \command{ssh-add} para añadir frases claves al agente.  En
+Windows, si está usando PuTTY, la orden \command{pageant} actúa como
+el agente.  Añade un icono a su barra del sistema que le permitirá
+almacenar frases clave.
+
+\subsection{Configurar el lado del servidor apropiadamente}
+
+Dado que puede ser dispendioso configurar ssh si usted es nuevo, hay 
+una variedad de cosas que podrían ir mal.  Añada piense primero en
+Mercurial y hay mucho más en qué pensar.  La mayor parte de estos
+problemas potenciales ocurren en el lado del servidor, no en el cliente.
+Las buenas noticias es que una vez tiene una configuración funcional,
+usualmente continuará trabajando indefinidamente.
+
+Antes de intentar que Mercurial hable con un servidor ssh, es mejor
+asegurarse que puede usar la orden normal \command{ssh} o \command{putty}
+para comunicarse con el servidor primero.  Si tiene problemas usando
+estas órdenes directamente, de seguro Mercurial no funcionará.  Pero aún,
+esconderá el problema subyacente.  Cuando desee revisar un problema
+relacionado con ssh y Mercurial, debería asegurarse primero que las
+órdenes de ssh en el lado del cliente funcionan primero, \emph{antes}
+de preocuparse por si existe un problema con Mercurial.
+
+Lo primero para asegurar en el lado del servidor es que puede entrar
+desde otra máquina.  Si no puede entrar con \command{ssh} o 
+\command{putty}, el mensaje de error que obtenga le puede dar pistas
+de qué ha ido mal.  Los problemas más comunes son los siguientes:
+\begin{itemize}
+\item Si obtiene un error de ``conexión rehusada'', es posible que no 
+  haya un demonio SSH corriendo en el servidor o que no pueda accederse
+  a él por configuraciones de cortafuegos.
+\item Si obtiene un error de ``no hay ruta hasta el servidor'', puede
+  tener la dirección del servidor incorrecta o un cortafuegos con
+  bloqueo agresivo que no permitirá su existencia.
+\item Si obtiene un mensaje de ``permiso denegado'', puede que haya
+  tecleado mal el usuario en el servidor, o que haya tecleado
+  incorrectamente la frase clave o la clave del usuario remoto.
+\end{itemize}
+En resumen, si tiene problemas al comunicarse con el demonio ssh del
+servidor, primero asegúrese de que está corriendo.  En muchos sistemas
+estará instalado, pero deshabilitado de forma predeterminada.  Una vez
+que haya hecho este paso tendrá que revisar si el cortafuegos del
+servidor está configurado para recibir conexiones entrantes en el
+puerto en el cual el demonio de ssh está escuchando (usualmente el~22).
+No trate de buscar otras posibilidades exóticas o configuraciones
+erradas hasta que haya revisado primero estas dos.
+
+Si está usando un agente de autenticación en el lado del cliente para
+almacenar las frase claves de sus contraseñas, debería poder entrar al
+servidor sin necesidad de que se le solicite frases claves o
+contraseñas.  Si se le pregunta alguna, a continuación algunas
+posibilidades:
+\begin{itemize}
+\item Puede haber olvidado usar \command{ssh-add} o
+  \command{pageant} para guardar la frase clave.
+\item Puede haber almacenado una frase clave errónea para la llave.
+\end{itemize}
+Si se le solicita la clave del usuario remoto, hay otras posibilidades
+que deben revisarse:
+\begin{itemize}
+\item O bien el directorio del usuario o su directorio \sdirname{.ssh}
+  tiene permisos excesivamente abiertos.  Como resultado el daemonio
+  ssh no creerá o leerá su fichero \sfilename{authorized\_keys}.  
+  Por ejemplo, un directorio casa o \sdirname{.ssh} causará aveces
+  este síntoma.
+\item El fichero de usuario \sfilename{authorized\_keys} puede tener
+  un problema.  Si alguien distinto al usuario es dueño o puede
+  escribir el fichero, el demonio ssh no confiará o lo leerá.
+\end{itemize}
+
+En un mundo ideal, debería poder ejecutar la siguiente orden
+exitosamente, y debería imprimir exactamente una línea de salida,
+la fecha y hora actual.
+\begin{codesample2}
+  ssh miservidor fecha
+\end{codesample2}
+
+Si en su servidor tiene guión que se ejecuta a la entrada e imprime
+letreros o cualquier otra cosa, incluso cuando se ejecutan órdenes no
+interactivas como esta, debería arreglarlo antes de continuar, de
+forma que solamente imprima algo si se ejecuta interactivamente.  De
+otra forma estos letreros al menos llenarán la salida de Mercurial. 
+Incluso podrían causar problemas potenciales cuando se ejecuten
+órdenes de forma remota.  Mercurial intenta detectar e ignorar los
+letreros en sesiones no interactivas de \command{ssh}, pero no es
+a prueba de tontos.  (Si edita sus guiones de entrada en el servidor,
+la forma usual de ver si un guión de línea de comandos se ejecuta en un intérprete
+interactivo, es verificar el código de retorno de la orden
+\Verb|tty -s|.)
+
+Cuando verifique que el venerado ssh funciona en su servidor, el
+paso siguiente es asegurar que Mercurial corre en el servidor.  La
+orden siguiente debería ejecutarse satisfactoriamente:
+\begin{codesample2}
+  ssh miservidor hg version
+\end{codesample2}
+Si ve un mensaje de error en lugar de la salida usual de 
+\hgcmd{version}, será porque no ha instalado Mercurial en
+\dirname{/usr/bin}.  No se preocupe si este es el caso; no necesita
+hacerlo.  Pero debería revisar los posibles problemas presentados a
+continuación:
+\begin{itemize}
+\item Está instalado Mercurial en el servidor?  Se que suena trivial
+  pero es mejor revisar!
+\item Tal vez la ruta de búsqueda de la interfaz de órdenes
+  (normalmente vía la variable de ambiente \envar{PATH}) simplemente
+  está mal configurada.
+\item Puede ser que su variable de ambiente \envar{PATH} soalamente
+  apunte al lugar en el cual está el ejecutable \command{hg} si la
+  sesión de entrada es interactiva.  Puede suceder si establece la
+  ruta en el guión de línea de comandos de entrada incorrecto.  Consulte la
+  documentación de su línea de órdenes.
+\item La variable de ambiente \envar{PYTHONPATH} puede requerir la
+  ruta a los módulos de Mercurial en Python.  Puede que ni siquiera
+  está establecida; podría estar incorrecta; o puede ser que se
+  establezca únicamente cuando hay entradas interactivas.
+\end{itemize}
+
+Si puede ejecutar \hgcmd{version} sobre una conexión ssh,
+felicitaciones!  Ha logrado la interacción entre el cliente y el 
+servidor.  Ahora debería poder acceder a los repositorios de
+Mercurial que tiene el usuario en el servidor.  Si tiene problemas
+con Mercurial y ssh en este punto, intente usar la opción
+\hggopt{--debug} para tener información más clara de lo que está
+sucediendo.
+
+\subsection{Compresión con ssh}
+
+Mercurial no comprime datos cuando usa el protocolo ssh, dado que
+el protocolo puede comprimir datos transparentemente.  Pero el
+comportamiento predeterminado del cliente ssh es \emph{no}
+solicitar compresión.
+
+Sobre cualquier red distinta a una LAN rápida (incluso con una red
+inalámbrica), hacer uso de compresión puede mejorar el rendimiento
+de las operaciones de Mercurial que involucren la red.  Por ejemplo,
+sobre WAN, alguien ha medido la compresión reduciendo la cantidad
+de tiempo requerido para clonar un repositorio particularmente
+grande de~51 minutos a~17 minutos.
+
+Tanto \command{ssh} como \command{plink} aceptan la opción
+\cmdopt{ssh}{-C} que activa la compresión.  Puede editar fácilmente
+su \hgrc\ para habilitar la compresión para todos los usos de
+Mercurial sobre el protocolo ssh.
+\begin{codesample2}
+  [ui]
+  ssh = ssh -C
+\end{codesample2}
+
+Si usa \command{ssh}, puede reconfigurarlo para que siempre use
+compresión cuando se comunique con su servidor.  Para hacerlo,
+edite su fichero \sfilename{.ssh/config} (que puede no existir
+aún), de la siguiente forma:
+\begin{codesample2}
+  Host hg
+    Compression yes
+    HostName hg.ejemplo.com
+\end{codesample2}
+Que define un alias, \texttt{hg}.  Cuando lo usa con la orden
+\command{ssh} o con una URL de Mercurial con protocolo\texttt{ssh},
+logrará que \command{ssh} se conecte a \texttt{hg.ejemplo.com}
+con compresión.  Que le dará un nombre más corto para teclear y
+compresión, los cuales por derecho propio son buenos.
+
+\section{Uso de CGI a través de HTTP}
+\label{sec:collab:cgi}
+
+Dependiendo de qué tan ambicioso sea, configurar la interfaz CGI
+de Mercurial puede tomar desde unos minutos hasta varias horas.
+
+Comenzaremos con el ejemplo más sencillo, y nos dirigiremos hacia
+configuraciones más complejas.  Incluso para el caso más básico
+necesitará leer y modificar su configuración del servidor web.
+
+\begin{note}
+  Configurar un servidor web es una actividad compleja, engorrosa y
+  altamente dependiente del sistema.  De ninguna manera podremos
+  cubrir todos los casos posibles con los cuales pueda encontrarse.
+  Use su discreción y juicio respecto a las secciones siguientes.
+  Esté preparado para cometer muchas equivocaciones, y emplear
+  bastante tiempo leyendo sus bitácoras de error del servidor.
+\end{note}
+
+\subsection{Lista de chequeo de la configuración del servidor web}
+
+Antes de continuar, tómese un tiempo para revisar ciertos aspectos de
+la configuración de su sistema:
+
+\begin{enumerate}
+\item ¿Tiene un servidor web?  Mac OS X viene con Apache, pero otros
+  sistemas pueden no tener un servidor web instalado.
+\item Si tiene un servidor web instalado, ¿Está ejecutándose?  En la
+  mayoría de sistemas, aunque esté presente, puede no estar habilitado
+  de forma predeterminada.
+\item ¿u servidor está configurado para permitir ejecutar programas
+  CGI en el directorio donde planea hacerlo?  Casi todos los
+  servidores de forma predeterminada explícitamente inhiben la
+  habilidad de ejecutar programas CGI.
+\end{enumerate}
+
+Si no tiene un servidor web instalado, y no tiene cierta experiencia
+configurando  Apache, debería considerar usar el servidor web
+\texttt{lighttpd} en lugar de Apache.  Apache tiene una reputación
+bien ganada por su configuración barroca y confusa.
+A pesar de que \texttt{lighttpd} tiene menos características que
+Apache en ciertas áreas, las mismas no son relevantes para servir
+repositorios de Mercurial.  Definitivamente es mucho más sencillo
+comenzar con \texttt{lighttpd} que con Apache.
+
+\subsection{Configuración básica de CGI}
+
+En sistemas tipo Unix es común que los usuarios tengan un subdirectorio
+con un nombre como \dirname{public\_html} en su directorio personal,
+desde el cual pueden servir páginas web.  Un fichero llamado \filename{foo}
+en este directorio será visible en una URL de la forma
+\texttt{http://www.example.com/\~username/foo}.
+
+Para comenzar, encuentre el guión \sfilename{hgweb.cgi} que debería
+estar presente en su instalación de Mercurial.  Si no puede
+encontrarlo rápidamente una copia local en su sistema, puede
+descargarlo del repositorio principal de Mercurial en
+\url{http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi}.
+
+Tendrá que copiar este guión en su directorio \dirname{public\_html},
+y asegurarse que sea ejecutable.
+\begin{codesample2}
+  cp .../hgweb.cgi ~/public_html
+  chmod 755 ~/public_html/hgweb.cgi
+\end{codesample2}
+El argumento \texttt{755} de la orden \command{chmod} es un poco más
+general que hacerlo ejecutable: Asegura que el guión sea ejecutable
+por cualquiera, y que el ``grupo'' y los ``otros'' \emph{no}  tengan
+permiso de escritura.  Si dejara los permisos de escritura abiertos,
+, el subsistema \texttt{suexec} de  Apache probablemente se negaría
+a ejecutar el guión.  De hecho, \texttt{suexec} también insiste en que
+el \emph{directorio} en el cual reside el guión no tenga permiso de
+escritura para otros.
+\begin{codesample2}
+  chmod 755 ~/public_html
+\end{codesample2}
+
+\subsubsection{¿Qué \emph{podría} resultar mal?}
+\label{sec:collab:wtf}
+
+Cuando haya ubicado el CGI en el sitio correspondiente con un navegador
+intente visitar el URL \url{http://myhostname/~myuser/hgweb.cgi},
+\emph{sin} dejarse abatir por un error.  Hay una alta probabilidad de
+que esta primera visita al URL sea fallida, y hay muchas razones posibles
+para este comportamiento.  De hecho, podría toparse con cada uno de los
+errores que describimos a continuación, así que no deje de leerlos
+cuidadosamente.   A continuación presento los problemas que yo tuve en
+un sistema con Fedora~7, con una instalación nueva de Apache, y una
+cuenta de usuario que creé específicamente para desarrollar este
+ejercicio.
+
+Su servidor web puede tener directorios por usuario deshabilitados. Si
+usa Apache, busque el fichero de configuración que contenga la
+directiva \texttt{UserDir}.  Si no está presente en sitio alguno, los
+directorios por usuario están deshabilitados.  Si la hay, pero su
+valor es \texttt{disabled}, los directorios por usuario estarán
+deshabilitados. La directiva \texttt{UserDir} en caso contrario tendrá
+el nombre del subdirectorio bajo el cual Apache mirará en el
+directorio de cada usuario, por ejemplo \dirname{public\_html}.
+
+Los permisos de sus ficheros pueden ser demasiado restrictivos.  El
+servidor web debe poder recorrer su directorio personal y los
+directorios que estén bajo \dirname{public\_html}, además de tener
+permiso para leer aquellos que estén adentro.  A continuación una
+receta rápida para hacer que sus permisos estén acordes con las
+necesidades básicas.
+\begin{codesample2}
+  chmod 755 ~
+  find ~/public_html -type d -print0 | xargs -0r chmod 755
+  find ~/public_html -type f -print0 | xargs -0r chmod 644
+\end{codesample2}
+
+Otra posibilidad con los permisos es que obtenga una ventana
+completamente en blanco cuando trata de cargar el guión. En cuyo
+caso, es posible que los permisos que tiene son \emph{demasiado
+ permisivos}.  El subsistema \texttt{suexec} de Apache no ejecutará un
+guión que tenga permisos de escritura para el grupo o el planeta, por
+ejemplo.
+
+Su servidor web puede estar configurado para evitar la ejecución de
+programas CGI en los directorios de usuario.  A continuación presento
+una configuración predeterminada por usuario en mi sistema Fedora.
+
+\begin{codesample2}
+  <Directory /home/*/public_html>
+      AllowOverride FileInfo AuthConfig Limit
+      Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
+      <Limit GET POST OPTIONS>
+          Order allow,deny
+          Allow from all
+      </Limit>
+      <LimitExcept GET POST OPTIONS>
+          Order deny,allow
+          Deny from all
+      </LimitExcept>
+  </Directory>
+\end{codesample2}
+Si encuentra un grupo de instrucciones de \texttt{Directory} similares
+en su configuración de Apache,  la directiva a revisar es \texttt{Options}.
+Adicione \texttt{ExecCGI} al final de esta lista en caso de que haga
+falta y reinicie su servidor web.
+
+Si resulta que Apache le muestra el texto del guión CGI en lugar de
+ejecutarlo, necesitará o bien descomentar (si se encuentra presente) o
+adicionar una directiva como la siguiente:
+\begin{codesample2}
+  AddHandler cgi-script .cgi
+\end{codesample2}
+
+Otra posibilidad es que observe una traza de Python en colores
+informando que no puede importar un módulo relacionado con
+\texttt{mercurial}.  Esto es un gran progreso!  El servidor es capaz
+de ejecutar su guión CGI.  Este error solamente ocurrirá si está
+ejecutando una instalación privada de Mercurial en lugar de una
+instalación para todo el sistema.  Recuerde que el servidor que
+ejecuta el programa CGI no cuenta con variables de ambiente de las
+cuales usted si dispone en una sesión interactiva.  Si este error le
+ocurre, edite su copia de \sfilename{hgweb.cgi} y siga las indicaciones
+dentro del mismo para establecer de forma adecuada su variable de
+ambiente \envar{PYTHONPATH}.
+
+Finalmente, si encuentra \emph{otra} traza a todo color de Python al visitar
+el URL: Esta seguramente se referirá a que no puede encontrar
+\dirname{/path/to/repository}.  Edite su script \sfilename{hgweb.cgi}
+y reemplace la cadena \dirname{/path/to/repository} con la ruta
+completa al repositorio que desea servir.
+
+En este punto, cuando trate de recargar la página, deberá visualizar
+una linda vista HTML del historial de su repositorio. Uff!
+
+\subsubsection{Configuración de lighttpd}
+
+En mi intención de ser exhaustivo, intenté configurar
+\texttt{lighttpd}, un servidor web con creciente aceptación, para
+servir los repositorios de la misma forma como lo describí
+anteriormente con Apache. Después de superar los problemas que mostré
+con Apache, muchos de los cuáles no son específicos del servidor.  Por
+lo tanto estaba seguro de que mis permisos para directorios y ficheros
+eran correctos y que mi guión \sfilename{hgweb.cgi} también lo era.
+
+Dado que ya Apache estaba en ejecución correctamente, lograr que
+\texttt{lighttpd} sirviera mi repositorio fue rápido (en otras
+palabras, si está tratando de usar \texttt{lighttpd}, debe leer la
+sección de Apache).  Primero tuve que editar la sección
+\texttt{mod\_access} para habilitar \texttt{mod\_cgi} y
+\texttt{mod\_userdir}, los cuales estaban inhabilitados en mi
+instalación predeterminada.  Añadí posteriormente unas líneas al final
+del fichero de configuración, para hacer lo propio con los módulos.
+\begin{codesample2}
+  userdir.path = "public_html"
+  cgi.assign = ( ".cgi" => "" )
+\end{codesample2}
+Hecho esto, \texttt{lighttpd} funcionó inmediatamente para
+mí. Configuré \texttt{lighttpd} antes que Apache, tuve casi los mismos
+reparos a nivel de configuración del sistema que con Apache.  De todas
+maneras, considero que \texttt{lighttpd} es bastante más sencillo de
+configurar que Apache, a pesar de haber usado Apache por lo menos por
+una década, y esta fue mi primera experiencia con \texttt{lighttpd}.
+
+\subsection{Compartir varios repositorios con un guión CGI}
+
+El guión \sfilename{hgweb.cgi} permite publicar únicamente un
+repositorio, una restricción frustrante.  Si desea publicar más de uno
+sin complicarse con varias copias del mismo guión, cada una con un
+nombre distinto, resulta mucho mejor usar el guión
+\sfilename{hgwebdir.cgi}.
+
+El procedimiento para configurar \sfilename{hgwebdir.cgi} tiene una
+porción adicional frente al trabajo requerido con
+\sfilename{hgweb.cgi}.  Primero se debe obtener una copia del
+guión. Si no tiene una a mano, puede descargar una copia del ftp
+principal del repositorio de Mercurial en
+\url{http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi}.
+
+Necesitará una copia del guión en su directorio \dirname{public\_html},
+y asegurarse de que sea ejecutable.
+\begin{codesample2}
+  cp .../hgwebdir.cgi ~/public_html
+  chmod 755 ~/public_html ~/public_html/hgwebdir.cgi
+\end{codesample2}
+Con la configuración básica, intente visitar en su navegador
+\url{http://myhostname/~myuser/hgwebdir.cgi}.  Debería mostrar una
+lista vacía de repositorios.  Si obtiene una ventana en blanco o un
+mensaje de error, verifique la lista de problemas potenciales en la 
+sección~\ref{sec:collab:wtf}.
+
+El guión \sfilename{hgwebdir.cgi} se apoya en un fichero externo de
+configuración.  En principio, busca un fichero llamado
+\sfilename{hgweb.config} en el mismo directorio.  Tendrá que crear el
+fichero, y permitir lectura de todo el mundo.  El formato del fichero
+es similar a un fichero ``ini'' de Windows, que puede interpretar el módulo
+\texttt{ConfigParser}~\cite{web:configparser} de Python.
+
+La forma más sencilla de configurar \sfilename{hgwebdir.cgi} es con
+una sección llamada \texttt{collections}.  Esta publicará automáticamente
+\emph{todos} los repositorios en los directorios que usted
+especifique.  La sección debería lucir así:
+\begin{codesample2}
+  [collections]
+  /mi/ruta = /mi/ruta
+\end{codesample2}
+Mercurial lo interpreta buscando el nombre del directorio que esté a la
+\emph{derecha} del símbolo ``\texttt{=}''; encontrando repositorios en
+la jerarquía de directorios; y usando el texto a la \emph{izquierda}
+para eliminar el texto de los nombres que mostrará en la interfaz
+web.  El componente restante de la ruta después de esta eliminación
+usualmente se llama ``ruta virtual''.
+
+Dado el ejemplo de arriba, si tenemos un repositorio cuya ruta local es
+\dirname{/mi/ruta/este/repo}, el guión CGI eliminará la porción inicial
+\dirname{/mi/ruta} del nombre y publicará el repositorio con una ruta
+virtual \dirname{este/repo}.  Si el URL base de nuestro guión CGI es
+\url{http://myhostname/~myuser/hgwebdir.cgi}, el URL completo al
+repositorio será
+\url{http://myhostname/~myuser/hgwebdir.cgi/this/repo}.
+
+Si reemplazamos \dirname{/mi/ruta} en el lado izquierdo de este
+ejemplo con \dirname{/mi}, \sfilename{hgwebdir.cgi} eliminará solamente
+\dirname{/mi} del nombre del repositorio, y nos ofrecerá la ruta
+virtual \dirname{ruta/este/repo} en lugar de \dirname{este/repo}.
+
+El guión \sfilename{hgwebdir.cgi} buscará recursivamente en cada
+directorio listado en la sección \texttt{collections} de su fichero de
+configuración, pero \texttt{no} hará el recorrido recursivo dentro de
+los repositorios que encuentre.
+
+El mecanismo de \texttt{collections} permite publicar fácilmente
+repositorios de una forma ``hacer y olvidar''.  Solamente requiere
+configurar el guión CGI y el fichero de configuración una vez.
+Después de eso puede publicar y sacar de publicación un repositorio en
+cualquier momento incluyéndolo o excluyéndolo de la jerarquía de
+directorios en la cual le haya indicado a \sfilename{hgwebdir.cgi} que
+mirase.
+
+\subsubsection{Especificación explícita de los repositorios a publicar}
+
+Además del mecanismo \texttt{collections}, el guión
+\sfilename{hgwebdir.cgi} le permite publicar una lista específica de
+repositorios.  Para hacerlo, cree una sección \texttt{paths}, con los
+contenidos de la siguiente forma:
+\begin{codesample2}
+  [paths]
+  repo1 = /mi/ruta/a/un/repo
+  repo2 = /ruta/a/otro/repo
+\end{codesample2}
+En este caso, la ruta virtual (el componente que aparecerá en el URL)
+está en el lado derecho de cada definición, mientras que la ruta al
+repositorio está a la derecha.  Note que no tiene que haber relación
+alguna entre la ruta virtual que elija y el lugar del repositorio en
+su sistema de ficheros.
+
+Si lo desea, puede usar los dos mecanismos \texttt{collections} y
+\texttt{paths} simultáneamente en un sólo fichero de configuración.
+
+\begin{note}
+  Si varios repositorios tienen la misma ruta virtual,
+  \sfilename{hgwebdir.cgi} no reportará error.  Pero se comportará
+  impredeciblemente.
+\end{note}
+
+\subsection{Descarga de ficheros fuente}
+
+La interfaz web de Mercurial permite a los usuarios descargar
+un conjunto de cualquier revisión.  Este fichero contendrá una réplica
+del directorio de trabajo en la revisión en cuestión, pero no
+contendrá una copia de los datos del repositorio.
+
+De forma predeterminada esta característica no está habilitada.  Para
+lograrlo adicione un \rcitem{web}{allow\_archive} a la sección \rcsection{web}
+de su fichero \hgrc.
+
+\subsection{Opciones de configuración en Web}
+
+Las interfaces web de Mercurial (la orden \hgcmd{serve}, y los guiones
+\sfilename{hgweb.cgi} y \sfilename{hgwebdir.cgi}) tienen varias
+opciones de configuración para establecer. Todas ellas en la sección
+\rcsection{web}.
+\begin{itemize}
+\item[\rcitem{web}{allow\_archive}] Determina cuáles tipos de ficheros
+  de descarga soportará Mercurial.  Si habilita esta característica,
+  los usuarios de la interfaz web podrán descargar una copia de la
+  revisión del repositorio que estén viendo. Para activar la
+  característica de descarga de fichero, el valor tendrá una secuencia
+  de palabras extraídas de la lista de abajo.
+  \begin{itemize}
+  \item[\texttt{bz2}] Un fichero \command{tar} con el método de
+    compresión \texttt{bzip2}.  Tiene la mejor tasa de compresión,
+    pero usa más tiempo de procesamiento en el servidor.
+  \item[\texttt{gz}] Un fichero \command{tar}, comprimido con
+    \texttt{gzip}.
+  \item[\texttt{zip}] Un fichero \command{zip}, comprimido con LZW.
+    Este formato posee la peor tasa de compresión, pero es muy usado en
+    el mundo Windows.
+  \end{itemize}
+  Si da una lista vacía o no tiene la entrada
+  \rcitem{web}{allow\_archive}, esta característica se deshabilitará.
+  A continuación un ejemplo de cómo habilitar los tres formatos soportados.
+  \begin{codesample4}
+    [web]
+    allow_archive = bz2 gz zip
+  \end{codesample4}
+\item[\rcitem{web}{allowpull}] Booleano.  Determina si la interfaz web
+  permite a los usuarios remotos emplear \hgcmd{pull} y \hgcmd{clone}
+  sobre el repositorio~HTTP.  Si se coloca \texttt{no} o
+  \texttt{false}, solamente la porción de los procesos
+  ``orientados-a-humanos'' se habilita de la interfaz web.
+\item[\rcitem{web}{contact}] Cadena.  Una cadena en forma libre (pero
+  preferiblemente corta) que identifica a la persona o grupo a cargo
+  del repositorio.  Usualmente contiene el nombre y la dirección de
+  correo electrónico de una persona o de una lista de correo.  Aveces
+  tiene sentido colocar esta opción en el fichero \sfilename{.hg/hgrc}
+  del repositorio, pero en otras oportunidades en el \hgrc\ global si
+  todos los repositorios tienen un único mantenedor.
+\item[\rcitem{web}{maxchanges}] Entero.  La cantidad máxima de
+  conjuntos de cambios a mostrar de forma predeterminada en cada página.
+\item[\rcitem{web}{maxfiles}] Entero.  La cantidad máxima
+  predeterminada de ficheros modificados a desplegar en una página.
+\item[\rcitem{web}{stripes}] Entero.  Si la interfaz web despliega
+  ``franjas'' para facilitar la visualización alineada de filas cuando
+  se ve una tabla, este valor controla la cantidad de filas en cada
+  franja.
+\item[\rcitem{web}{style}] Controla la plantilla que Mercurial usa para
+  desplegar la interfaz web.  Mercurial viene con dos plantillas web,
+  llamadas \texttt{default} y \texttt{gitweb} (La primera es
+  visualmente más atractiva).  Puede especificar una plantilla propia;
+  consulte el capítulo~\ref{chap:template}.  A continuación mostramos
+  cómo habilitar el estilo \texttt{gitweb}.
+  \begin{codesample4}
+    [web]
+    style = gitweb
+  \end{codesample4}
+\item[\rcitem{web}{templates}] Ruta.  Directorio en el que se buscarán
+  los ficheros plantilla.  De forma predeterminada, busca en el
+  directorio en el cual fue instalado.
+\end{itemize}
+Si usa \sfilename{hgwebdir.cgi}, puede añadir otras opciones de
+configuración en una sección \section{web} del fichero
+\sfilename{hgweb.config} en lugar del fichero \hgrc\, si lo considera
+más conveniente.  Estas opciones son \rcitem{web}{motd} y
+\rcitem{web}{style}.
+
+\subsubsection{Opciones específicas para repositorios individuales}
+
+Ciertas opciones de configuración de \rcsection{web} deben estar
+ubicadas en el \sfilename{.hg/hgrc} de un repositorio en lugar del
+fichero del usuario o el \hgrc global.
+\begin{itemize}
+\item[\rcitem{web}{description}] Cadena.  Una cadena de forma
+  libre (preferiblemente corta) que describa los contenidos o el
+  propósito del repositorio.
+\item[\rcitem{web}{name}] Cadena.  El nombre para visualizar en la
+  interfaz web del repositorio. Sustituye el nombre predeterminado, el
+  cual es el último componente de la ruta del repositorio.
+\end{itemize}
+
+\subsubsection{Opciones específicas a la orden \hgcmd{serve}}
+
+Algunas opciones en la sección \rcsection{web} de un fichero \hgrc\
+son de uso exclusivo para la orden \hgcmd{serve}.
+\begin{itemize}
+\item[\rcitem{web}{accesslog}] Ruta.  El nombre del fichero en el cual
+  se escribe la bitácora de acceso.  En principio, la orden
+  \hgcmd{serve} escribe esta información a la salida estándar, no a un
+  fichero. Las líneas de la bitácora se escriben en un formato de
+  fichero ``combinado'' estándar, usado por casi todos los servidores
+  web.
+\item[\rcitem{web}{address}] Cadena.  La dirección local en la cual el
+  servidor debe escuchar peticiones entrantes.  En principio, el
+  servidor escucha en todas las direcciones.
+\item[\rcitem{web}{errorlog}] Ruta.  El nombre de un fichero en el
+  cual escribir la bitácora de error.  En principio, la orden
+  \hgcmd{serve} escribe esta información en la salida de error
+  estándar, no a un fichero.
+\item[\rcitem{web}{ipv6}] Booleano.  Si se usa o no el protocolo
+  IPv6. En principio, IPv6 no se usa.
+\item[\rcitem{web}{port}] Entero.  El número del puerto~TCP en el cuál
+  el servidor escuchará.  El puerto predeterminado es el~8000.
+\end{itemize}
+
+\subsubsection{Elegir el fichero \hgrc\ correcto para las
+  configuraciones de \rcsection{web}}
+
+Es importante recordar que un servidor web como Apache o
+\texttt{lighttpd} se ejecutarán bajo el usuario~ID que generalmente no
+es el suyo  Los guiones CGI ejecutados por su servidor, tales como
+\sfilename{hgweb.cgi}, se ejecutarán también con el usuario~ID.
+
+Si añade opciones \rcsection{web} a su fichero personal \hgrc\, Los
+guiones CGI no leerán tal fichero \hgrc\.  Tales configuraciones
+solamente afectarán el comportamiento de la orden \hgcmd{serve} cuando
+usted lo ejecuta.  Para logar que los guiones CGI vean sus
+configuraciones, o bien cree un fichero \hgrc\ en el directorio hogar
+del usuario ID que ejecuta su servidor web, o añada tales
+configuraciones al fichero global \hgrc.
+
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/concepts.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,650 @@
+\chapter{Tras bambalinas}
+\label{chap:concepts}
+
+A diferencia de varios sistemas de control de revisiones, los
+conceptos en los que se fundamenta Mercurial son lo suficientemente
+simples como para entender fácilmente cómo funciona el software. 
+Saber esto no es necesario, pero considero útil tener un ``modelo
+mental'' de qué es lo que sucede.
+
+Comprender esto me da la confianza de que Mercurial ha sido
+cuidadosamente diseñado para ser tanto \emph{seguro} como
+\emph{eficiente}.  Y tal vez con la misma importancia, si es fácil
+para mí hacerme a una idea adecuada de qué está haciendo el software
+cuando llevo a cabo una tarea relacionada con control de revisiones,
+es menos probable que me sosprenda su comportamiento.
+
+En este capítulo, cubriremos inicialmente los conceptos centrales
+del diseño de Mercurial, y luego discutiremos algunos detalles
+interesantes de su implementación.
+
+\section{Registro del historial de Mercurial}
+
+\subsection{Seguir el historial de un único fichero}
+
+Cuando Mercurial sigue las modificaciones a un fichero, guarda el
+historial de dicho fichero en un objeto de metadatos llamado
+\emph{filelog}\ndt{Fichero de registro}.  Cada entrada en el fichero
+de registro contiene suficiente información para reconstruir una
+revisión del fichero que se está siguiendo. Los ficheros de registro
+son almacenados como ficheros el el directorio
+\sdirname{.hg/store/data}. Un fichero de registro contiene dos tipos
+de información: datos de revisiones, y un índice para ayudar a
+Mercurial a buscar revisiones eficientemente.
+
+El fichero de registro de un fichero grande, o con un historial muy
+largo, es guardado como ficheros separados para datos (sufijo
+``\texttt{.d}'') y para el índice (sufijo ``\texttt{.i}''). Para
+ficheros pequeños con un historial pequeño, los datos de revisiones y
+el índice son combinados en un único fichero ``\texttt{.i}''. La
+correspondencia entre un fichero en el directorio de trabajo y el
+fichero de registro que hace seguimiento a su historial en el
+repositorio se ilustra en la figura~\ref{fig:concepts:filelog}.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{filelog}
+  \caption{Relación entre ficheros en el directorio de trabajo y
+  ficheros de registro en el repositorio}
+  \label{fig:concepts:filelog}
+\end{figure}
+
+\subsection{Administración de ficheros monitoreados}
+
+Mercurial usa una estructura llamada \emph{manifiesto} para
+% TODO collect together => centralizar
+centralizar la información que maneja acerca de los ficheros que
+monitorea. Cada entrada en el manifiesto contiene información acerca
+de los ficheros involucrados en un único conjunto de cambios. Una
+entrada registra qué ficheros están presentes en el conjunto de
+cambios, la revisión de cada fichero, y otros cuantos metadatos del
+mismo.
+
+\subsection{Registro de información del conjunto de cambios}
+
+La \emph{bitácora de cambios} contiene información acerca de cada
+conjunto de cambios. Cada revisión indica quién consignó un cambio, el
+comentario para el conjunto de cambios, otros datos relacionados con
+el conjunto de cambios, y la revisión del manifiesto a usar.
+
+\subsection{Relaciones entre revisiones}
+
+Dentro de una bitácora de cambios, un manifiesto, o un fichero de
+registro, cada revisión conserva un apuntador a su padre inmediato
+(o sus dos padres, si es la revisión de una fusión). Como menciońe
+anteriormente, también hay relaciones entre revisiones \emph{a través}
+de estas estructuras, y tienen naturaleza jerárquica.
+
+Por cada conjunto de cambios en un repositorio, hay exactamente una
+revisión almacenada en la bitácora de cambios. Cada revisión de la
+bitácora de cambios contiene un apuntador a una única revisión del
+manifiesto. Una revisión del manifiesto almacena un apuntador a una
+única revisión de cada fichero de registro al que se le hacía
+seguimiento cuando fue creado el conjunto de cambios. Estas relaciones
+se ilustran en la figura~\ref{fig:concepts:metadata}.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{metadata}
+  \caption{Relaciones entre metadatos}
+  \label{fig:concepts:metadata}
+\end{figure}
+
+Como lo muestra la figura, \emph{no} hay una relación ``uno a uno''
+entre las revisiones en el conjunto de cambios, el manifiesto, o el
+fichero de registro. Si el manifiesto no ha sido modificado de un
+conjunto de cambios a otro, las entradas en la bitácora de cambios
+para esos conjuntos de cambios apuntarán a la misma revisión del
+manifiesto. Si un fichero monitoreado por Mercurial no sufre ningún
+cambio de un conjunto de cambios a otro, la entrada para dicho fichero
+en las dos revisiones del manifiesto apuntará a la misma revisión de
+su fichero de registro.
+
+\section{Almacenamiento seguro y eficiente}
+
+La base común de las bitácoras de cambios, los manifiestos, y los
+ficheros de registros es provista por una única estructura llamada el
+\emph{revlog}\ndt{Contracción de \emph{revision log}, registro de
+revisión.}.
+
+\subsection{Almacenamiento eficiente}
+
+El revlog provee almacenamiento eficiente de revisiones por medio del
+mecanismo de \emph{deltas}\ndt{Diferencias.}.  En vez de almacenar una
+copia completa del fichero por cada revisión, almacena los cambios
+necesarios para transformar una revisión anterior en la nueva
+revisión. Para muchos tipos de fichero, estos deltas son típicamente
+de una fracción porcentual del tamaño de una copia completa del
+fichero.
+
+Algunos sistemas de control de revisiones obsoletos sólo pueden
+manipular deltas de ficheros de texto plano. Ellos o bien almacenan
+los ficheros binarios como instantáneas completas, o codificados en
+alguna representación de texto plano adecuada, y ambas alternativas
+son enfoques que desperdician bastantes recursos. Mercurial puede
+manejar deltas de ficheros con contenido binario arbitrario; no
+necesita tratar el texto plano como un caso especial.
+
+\subsection{Operación segura}
+\label{sec:concepts:txn}
+
+Mercurial sólo \emph{añade} datos al final de los ficheros de revlog. Nunca
+modifica ninguna sección de un fichero una vez ha sido escrita. Esto es más
+robusto y eficiente que otros esquemas que requieren modificar o reescribir
+datos.
+
+Adicionalmente, Mercurial trata cada escritura como parte de una
+\emph{transacción}, que puede cubrir varios ficheros. Una transacción es
+\emph{atómica}: o bien la transacción tiene éxito y entonces todos sus efectos
+son visibles para todos los lectores, o la operación completa es cancelada.
+% TODO atomicidad no existe de acuerdo a DRAE, reemplazar
+Esta garantía de atomicidad implica que, si usted está ejecutando dos copias de
+Mercurial, donde una de ellas está leyendo datos y la otra los está escribiendo,
+el lector nunca verá un resultado escrito parcialmente que podría confundirlo.
+
+El hecho de que Mercurial sólo hace adiciones a los ficheros hace más fácil
+proveer esta garantía transaccional. A medida que sea más fácil hacer
+operaciones como ésta, más confianza tendrá usted en que sean hechas
+correctamente.
+
+\subsection{Recuperación rápida de datos}
+
+Mercurial evita ingeniosamente un problema común a todos los sistemas de control
+de revisiones anteriores> el problema de la
+\emph{recuperación\ndt{\emph{Retrieval}. Recuperación en el sentido de traer los
+datos, o reconstruirlos a partir de otros datos, pero no debido a una falla o
+calamidad, sino a la operación normal del sistema.} ineficiente de datos}.
+Muchos sistemas de control de revisiones almacenan los contenidos de una
+revisión como una serie incremental de modificaciones a una ``instantánea''.
+Para reconstruir una versión cualquiera, primero usted debe leer la instantánea,
+y luego cada una de las revisiones entre la instantánea y su versión objetivo.
+Entre más largo sea el historial de un fichero, más revisiones deben ser leídas,
+y por tanto toma más tiempo reconstruir una versión particular.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{snapshot}
+  \caption{Instantánea de un revlog, con deltas incrementales}
+  \label{fig:concepts:snapshot}
+\end{figure}
+
+La innovación que aplica Mercurial a este problema es simple pero efectiva.
+Una vez la cantidad de información de deltas acumulada desde la última
+instantánea excede un umbral fijado de antemano, se almacena una nueva
+instantánea (comprimida, por supuesto), en lugar de otro delta. Esto hace
+posible reconstruir \emph{cualquier} versión de un fichero rápidamente. Este
+enfoque funciona tan bien que desde entonces ha sido copiado por otros sistemas
+de control de revisiones.
+
+La figura~\ref{fig:concepts:snapshot} ilustra la idea. En una entrada en el
+fichero índice de un revlog, Mercurial almacena el rango de entradas (deltas)
+del fichero de datos que se deben leer para reconstruir una revisión en
+particular.
+
+\subsubsection{Nota al margen: la influencia de la compresión de vídeo}
+
+Si le es familiar la compresión de vídeo, o ha mirado alguna vez una emisión de
+TV a través de cable digital o un servicio de satélite, puede que sepa que la 
+mayor parte de los esquemas de compresión de vídeo almacenan cada cuadro del
+mismo como un delta contra el cuadro predecesor. Adicionalmente, estos esquemas
+usan técnicas de compresión ``con pérdida'' para aumentar la tasa de
+compresión, por lo que los errores visuales se acumulan a lo largo de una
+cantidad de deltas inter-cuadros.
+
+Ya que existe la posibilidad de que un flujo de vídeo se ``pierda''
+ocasionalmente debido a fallas en la señal, y para limitar la acumulación de
+errores introducida por la compresión con pérdidas, los codificadores de vídeo
+insertan periódicamente un cuadro completo (también llamado ``cuadro clave'') en
+el flujo de vídeo; el siguiente delta es generado con respecto a dicho cuadro.
+Esto quiere decir que si la señal de vídeo se interrumpe, se reanudará una vez
+se reciba el siguiente cuadro clave. Además, la acumulación de errores de
+codificación se reinicia con cada cuadro clave.
+
+\subsection{Identificación e integridad fuerte}
+
+Además de la información de deltas e instantáneas, una entrada en un
+% TODO de pronto aclarar qué diablos es un hash?
+revlog contiene un hash criptográfico de los datos que representa.
+Esto hace difícil falsificar el contenido de una revisión, y hace
+fácil detectar una corrupción accidental.
+
+Los hashes proveen más que una simple revisión de corrupción: son
+usados como los identificadores para las revisiones. 
+% TODO no entendí completamente la frase a continuación
+Los hashes de
+identificación de conjuntos de cambios que usted ve como usuario final
+son de las revisiones de la bitácora de cambios. Aunque los ficheros
+de registro y el manifiesto también usan hashes, Mercurial sólo los
+usa tras bambalinas.
+
+Mercurial verifica que los hashes sean correctos cuando recupera
+revisiones de ficheros y cuando jala cambios desde otro repositorio.
+Si se encuentra un problema de integridad, Mercurial se quejará y
+detendrá cualquier operación que esté haciendo.
+
+Además del efecto que tiene en la eficiencia en la recuperación, el
+uso periódico de instantáneas de Mercurial lo hace más robusto frente
+a la corrupción parcial de datos. Si un fichero de registro se
+corrompe parcialmente debido a un error de hardware o del sistema, a
+menudo es posible reconstruir algunas o la mayoría de las revisiones a
+partir de las secciones no corrompidas del fichero de registro, tanto
+antes como después de la sección corrompida. Esto no sería posible con
+un sistema de almacenamiento basado únicamente en deltas.
+
+\section{Historial de revisiones, ramas y fusiones}
+
+Cada entrada en el revlog de Mercurial conoce la identidad de la
+revisión de su ancestro inmediato, al que se conoce usualmente como su
+\emph{padre}. De hecho, una revisión contiene sitio no sólo para un
+padre, sino para dos. Mercurial usa un hash especial, llamado el
+``ID nulo'', para representar la idea de ``no hay padre aquí''. Este
+hash es simplemente una cadena de ceros.
+
+En la figura~\ref{fig:concepts:revlog} usted puede ver un ejemplo de
+la estructura conceptual de un revlog. Los ficheros de registro,
+manifiestos, y bitácoras de cambios comparten la misma estructura;
+sólo difieren en el tipo de datos almacenados en cada delta o
+instantánea.
+
+La primera revisión en un revlog (al final de la imagen) tiene como
+padre al ID nulo, en las dos ranuras disponibles para padres. En una
+revisión normal, la primera ranura para padres contiene el ID de la
+revisión padre, y la segunda contiene el ID nulo, señalando así que la
+revisión sólo tiene un padre real. Un par de revisiones que tenga el
+mismo ID padre son ramas. Una revisión que representa una fusión entre
+ramas tiene dos IDs de revisión normales en sus ranuras para padres.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{revlog}
+  \caption{}
+  \label{fig:concepts:revlog}
+\end{figure}
+
+\section{El directorio de trabajo}
+
+% TODO revisar párrafo, no me convence la traducción
+En el directorio de trabajo, Mercurial almacena una instantánea de los
+ficheros  del repositorio como si fueran los de un conjunto de cambios
+particular.
+
+El directorio de trabajo ``sabe'' qué conjunto de cambios contiene.
+Cuando usted actualiza el directorio de trabajo para que contenga un
+conjunto de cambios particular, Mercurial busca la revisión adecuada
+del manifiesto para averiguar qué ficheros estaba monitoreando cuando
+se hizo la consignación del conjunto de cambios, y qué revisión de
+cada fichero era la actual en ese momento. Luego de eso, recrea una
+copia de cada uno de esos ficheros, con los mismos contenidos que
+tenían cuando fue consignado el conjunto de cambios.
+
+El \emph{estado de directorio}\ndt{dirstate, en inglés en el
+original.} contiene el conocimiento de Mercurial acerca del directorio
+de trabajo. Allí se detalla a qué conjunto de cambios es actualizado
+el directorio de trabajo, y todos los ficheros que Mercurial está
+monitoreando en este directorio.
+
+Tal como la revisión de un revlog tiene espacio para dos padres, para
+que pueda representar tanto una revisión normal (con un solo padre) o
+una fusión de dos revisiones anteriores, el estado de directorio tiene
+espacio para dos padres. Cuando usted usa el comando \hgcmd{update},
+el conjunto de cambios al que usted se actualiza es almacenado en la
+casilla destinada al ``primer padre'', y un ID nulo es almacenado en
+la segunda. Cuando usted hace una fusión (\hgcmd{merge}) con otro
+conjunto de cambios, la casilla para el primer padre permanece sin
+cambios, y la casilla para el segundo es actualizada con el conjunto
+de cambios con el que usted acaba de hacer la fusión. El comando
+\hgcmd{parents} le indica cuáles son los padres del estado de
+directorio.
+
+\subsection{Qué pasa en una consignación}
+
+El estado de directorio almacena información sobre los padres para
+algo más que mero registro. Mercurial usa los padres del estado de
+directorio como \emph{los padres de un nuevo conjunto de cambios}
+cuando usted hace una consignación.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{wdir}
+  \caption{El directorio de trabajo puede tener dos padres}
+  \label{fig:concepts:wdir}
+\end{figure}
+
+La figura~\ref{fig:concepts:wdir} muestra el estado normal del
+directorio de trabajo, que tiene un único conjunto de cambios como
+padre. Dicho conjunto de cambios es la \emph{punta}, el conjunto de
+cambios más reciente en el repositorio que no tiene hijos.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{wdir-after-commit}
+  \caption{El directorio de trabajo obtiene nuevos padres luego de una
+  consignación}
+  \label{fig:concepts:wdir-after-commit}
+\end{figure}
+
+Es útil pensar en el directorio de trabajo como en ``el conjunto de
+cambios que estoy a punto de enviar''. Cualquier fichero que usted le
+diga a Mercurial que fue añadido, borrado, renombrado o copiado, se
+verá reflejado en ese conjunto de cambios, como también se verán las
+modificaciones a cualquiera de los ficheros que Mercurial ya esté
+monitoreando; el nuevo conjunto de cambios dentrá los padres del
+directorio de trabajo como propios.
+
+Luego de una consignación, Mercurial actualizará los padres del
+directorio de trabajo, de tal manera que el primer padre sea el ID del
+nuevo conjunto de cambios, y el segundo sea el ID nulo. Esto puede
+verse en la figura~\ref{fig:concepts:wdir-after-commit}.  Mercurial no
+toca ninguno de los ficheros del directorio de trabajo cuando usted
+hace la consignación; sólo modifica el estado de directorio para
+anotar sus nuevos padres.
+
+\subsection{Creación de un nuevo frente}
+
+Es perfectamente normal actualizar el directorio de trabajo a un
+conjunto de cambios diferente a la punta actual. Por ejemplo, usted
+podría desear saber en qué estado se encontraba su proyecto el martes
+pasado, o podría estar buscando en todos los conjuntos de cambios para
+saber cuándo se introdujo un fallo. En casos como éstos, la acción
+natural es actualizar el directorio de trabajo al conjunto de cambios
+de su interés, y examinar directamente los ficheros en el directorio
+de trabajo para ver sus contenidos tal como estaban en el momento de
+hacer la consignación. El efecto que tiene esto se muestra en la
+figura~\ref{fig:concepts:wdir-pre-branch}.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{wdir-pre-branch}
+  \caption{El directorio de trabajo, actualizado a un conjunto de
+  cambios anterior}
+  \label{fig:concepts:wdir-pre-branch}
+\end{figure}
+
+Una vez se ha actualizado el directorio de trabajo a un conjunto de
+cambios anterior, qué pasa si se hacen cambios, y luego se hace una
+consignación? Mercurial se comporta en la misma forma que describí
+anteriormente. Los padres del directorio de trabajo se convierten en
+los padres del nuevo conjunto de cambios. Este nuevo conjunto de
+cambios no tiene hijos, así que se convierte en la nueva punta. Y el
+repositorio tiene ahora dos conjuntos de cambios que no tienen hijos;
+a éstos los llamamos \emph{frentes}. Usted puede apreciar la
+estructura que esto crea en la figura~\ref{fig:concepts:wdir-branch}.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{wdir-branch}
+  \caption{Después de una consignación hecha mientras se usaba un
+  conjunto de cambios anterior}
+  \label{fig:concepts:wdir-branch}
+\end{figure}
+
+\begin{note}
+    Si usted es nuevo en Mercurial, debería tener en mente un
+    ``error'' común, que es usar el comando \hgcmd{pull} sin ninguna
+    opción. Por defecto, el comando \hgcmd{pull} \emph{no} actualiza
+    el directorio de trabajo, así que usted termina trayendo nuevos
+    conjuntos de cambios a su repositorio, pero el directorio de
+    trabajo sigue usando el mismo conjunto de cambios que tenía antes
+    de jalar. Si usted hace algunos cambios, y luego hace una
+    consignación, estará creando un nuevo frente, porque su directorio
+    de trabajo no es sincronizado a cualquiera que sea la nueva punta.
+
+    Pongo la palabra ``error'' en comillas porque todo lo que usted
+    debe hacer para rectificar la situación es hacer una fusión
+    (\hgcmd{merge}), y luego una consignación (\hgcmd{commit}). En
+    otras palabras, esto casi nunca tiene consecuencias negativas;
+    sólo sorprende a la gente. Discutiré otras formas de evitar este
+    comportamiento, y porqué Mercurial se comporta de esta forma,
+    inicialmente sorprendente, más adelante.
+\end{note}
+
+\subsection{Fusión de frentes}
+
+Cuando usted ejecuta el comando \hgcmd{merge}, Mercurial deja el
+primer padre del directorio de trabajo intacto, y escribe como segundo
+padre el conjunto de cambios contra el cual usted está haciendo la
+fusión, como se muestra en la figura~\ref{fig:concepts:wdir-merge}.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{wdir-merge}
+  \caption{Fusión de dos frentes}
+  \label{fig:concepts:wdir-merge}
+\end{figure}
+
+Mercurial también debe modificar el directorio de trabajo, para
+fusionar los ficheros que él monitorea en los dos conjuntos de
+cambios. Con algunas simplificaciones, el proceso es el siguiente, por
+cada fichero en los manifiestos de ambos conjuntos de cambios.
+\begin{itemize}
+\item Si ningún conjunto de cambios ha modificado un fichero, no se
+    hace nada con el mismo.
+\item Si un conjunto de cambios ha modificado un fichero, y el otro no
+    lo ha hecho, se crea una copia del fichero con las modificaciones
+    pertinentes en el directorio de trabajo.
+\item Si un conjunto de cambios borra un fichero, y el otro no lo ha
+    hecho (o también lo borró), se borra dicho fichero del directorio
+    de trabajo.
+\item Si un conjunto de cambios ha borrado un fichero, pero el otro lo ha
+    modificado, se le pregunta al usuario qué hacer: conservar el
+    fichero modificado, o borrarlo?
+\item Si ambos conjuntos de cambios han modificado un fichero, se
+    invoca el programa externo de fusión para definir el nuevo
+    contenido del fichero fusionado. Esto puede requerir interacción
+    directa de parte del usuario.
+\item Si un conjunto de cambios ha modificado un fichero, y el otro ha
+    renombrado o copiado el mismo, asegurarse de que los cambios sigan
+    al nuevo nombre de fichero.
+\end{itemize}
+Hay más detalles---hacer una fusión tiene una gran cantidad de casos
+especiales---pero éstas son las elecciones más comunes que se ven
+involucradas en una fusión. Como usted puede ver, muchos de los casos
+son completamente automáticos, y de hecho la mayoría de las fusiones
+terminan automáticamente, sin requerir la interacción del usuario para
+resolver ningún conflicto.
+
+Cuando considere qué pasa cuando usted hace una consignación después
+de una fusión, de nuevo el directorio de trabajo es ``el conjunto de
+cambios que estoy a punto de consignar''. Una vez termina su trabajo
+el comando \hgcmd{merge}, el directorio de trabajo tiene dos padre;
+éstos se convertirán en los padres del nuevo conjunto de cambios.
+
+Mercurial le permite hacer múltiples fusiones, pero usted debe
+consignar los resultados de cada fusión sucesivamente. Esto es
+necesario porque Mercurial sólo monitorea dos padres, tanto para las
+revisiones como para los directorios de trabajo. Aunque técnicamente
+es posible fusionar varios conjuntos de trabajo en una sola operación,
+la posibilidad de confundir al usuario y crear un desorden terrible en
+la fusión se hace incontenible de inmediato.
+
+\section{Otras características de diseño interesantes}
+
+En las secciones anteriores, he tratado de resaltar algunos de los
+aspectos más importantes del diseño de Mercurial, para mostrar que se
+presta gran cuidado y atención a la confiabilidad y el desempeño. Sin
+embargo, la atención a los detalles no para ahí. Hay una cantidad de
+aspectos de la construcción de Mercurial que encuentro interesantes
+personalmente. Detallaré unos cuantos de ellos aquí, aparte de los
+elementos ``importantes'' de arriba, para que, si usted está
+% TODO the amount of thinking => (la cantidad de) esfuerzo mental
+interesado, pueda obetener una idea mejor de la cantidad de esfuerzo
+mental invertido en el diseño de un sistema bien diseñado.
+
+
+\subsection{Compresión ingeniosa}
+
+Cuando es adecuado, Mercurial almacenará tanto las instantáneas como
+los deltas en formato comprimido. Lo hace \emph{tratando} siempre de
+comprimir una instantánea o delta, y conservando la versión comprimida
+sólo si es más pequeña que la versión sin compresión.
+
+Esto implica que Mercurial hace ``lo correcto'' cuando almacena un
+fichero cuyo formato original está comprimido, como un fichero
+\texttt{zip} o una imagen JPEG.  Cuando estos tipos de ficheros son
+comprimidos por segunda vez, el fichero resultante usualmente es más
+grande que la versión comprimida una sola vez, por lo que Mercurial
+almacenará el fichero \texttt{zip} o JPEG original.
+
+Los deltas entre revisiones de un fichero comprimido usualmente son
+más grandes que las instantáneas del mismo fichero, y Mercurial de
+nuevo hace ``lo correcto'' en estos casos. Él encuentra que dicho
+delta excede el umbral respecto al cual se debería almacenar una
+instantánea completa del fichero, así que almacena la instantánea,
+ahorrando espacio de nuevo respecto al enfoque simplista de usar
+únicamente deltas.
+
+\subsubsection{Recompresión de red}
+
+Cuando almacena las revisiones en disco, Mercurial usa el algoritmo de
+compresión ``deflación'' (el mismo usado en el popular formato de
+fichero \texttt{zip}), que provee una buena velocidad con una tasa de
+compresión respetable. Sin embargo, cuando se transmiten datos de
+revisiones a través de una conexión de red, Mercurial descomprime los
+datos comprimidos de las revisiones.
+
+Si la conexión es hecha a través de HTTP, Mercurial recomprime el
+flujo completo de datos usando un algoritmo de compresión que brinda
+una mejor tasa de compresión (el algoritmo Burrows-Wheeler del
+ampliamente usado paquete de compresión \texttt{bzip2}). Esta
+combinación de algoritmo y compresión del flujo completo de datos
+(en vez de una revisión a la vez) reduce sustancialmente la cantidad
+de bytes a transferir, brindando así un mejor desempeño de red sobre
+casi todo tipo de redes.
+
+(Si la conexión se hace sobre \command{ssh}, Mercurial \emph{no}
+recomprmime el flujo, porque \command{ssh} puede hacer esto por sí
+mismo.)
+
+\subsection{Reordenado de lectura/escritura y atomicidad}
+
+Añadir datos al final de un fichero no es todo lo que hace falta para
+garantizar que un lector no verá una escritura parcial. Si recuerda la
+figura~\ref{fig:concepts:metadata}, las revisiones en la bitácora de
+cambios apuntan a revisiones en el manifiesto, y las revisiones en el
+manifiesto apuntan a revisiones en ficheros de registro. Esta
+jerarquía es deliberada.
+
+Un escritor inicia una transacción al escribir los datos del ficheros
+del fichero de registro y el manifiesto, y no escribe nada en la
+bitácora de cambios hasta que dichas escrituras hayan terminado. Un
+lector empieza leyendo datos de la bitácora de cambios, luego del
+manifiesto, y finalmente del fichero de registro.
+
+%TODO revisar párrafo completo, no me gusta el resultado
+Como el escritor siempre termina de escribir los datos en el fichero
+de registro y en el manifiesto antes de escribir a la bitácora de
+cambios, un lector nunca verá un apuntador a una versión parcialmente
+escrita de revisiones del manifiesto desde la bitácora de cambios, y
+nunca leerá un apuntador a una revisión parcialmente escrita del
+fichero de registro desde el manifiesto.
+
+\subsection{Acceso concurrente}
+
+El reordenado de lectura/escritura y la atomicidad garantizan que
+Mercurial nunca necesita \emph{bloquear} un repositorio cuando está
+leyendo datos, aún si se está escribiendo al repositorio mientras se
+hace la lectura. Esto tiene un gran efecto en la escalabilidad; usted
+puede tener cualquier cantidad de procesos Mercurial leyendo datos de
+un repositorio de manera segura al mismo tiempo, sin importar si se
+está escribiendo al mismo o no.
+
+La naturaleza carente de bloqueos de la lectura significa que si usted
+está compartiendo un repositorio en un sistema multiusuario, no
+necesita dar a los usuarios locales permisos de \emph{escritura} a su
+repositorio para que ellos puedan clonarlo o jalar cambios; sólo
+necesitan permisos de \emph{lectura}. (Esta \emph{no} es una
+%TODO signo de admiración de apertura
+característica común entre los sistemas de control de revisiones, así
+que no la dé por hecha! Muchos de ellos requieren que los lectores
+sean capaces de bloquear el repositorio antes de poder leerlo, y esto
+requiere acceso de escritura en al menos un directorio, lo que por
+supuesto se convierte en una fuente de todo tipo de problemas
+administrativos y de seguridad bastante molestos.)
+
+Mercurial usar bloqueos para asegurarse de que sólo un proceso pueda
+escribir a un repositorio al mismo tiempo (el mecanismo de bloqueo es
+seguro incluso sobre sistemas de ficheros notoriamente hostiles al
+bloqueo, como NFS). Si un repositorio está bloqueado, los escritores
+esperarán un buen rato para revisar si el repositorio ya ha sido
+desbloqueado, pero si el repositorio sique bloqueado por mucho tiempo,
+el proceso que intenta escribir fallará por tiempo de espera máximo.
+Esto significa que sus guiones automáticos diarios no se quedarán
+esperando para siempre, apilándose si el sistema se cayó sin que nadie
+se diera cuenta, por ejemplo. (Sí, el tiempo de espera máximo es
+configurable, de cero a infinito).
+
+
+\subsubsection{Acceso seguro al estado de directorio}
+
+Al igual que con los datos de revisión, Mercurial no requiere un
+bloqueo para leer el fichero de estado de directorio; sí se usa un
+bloqueo para escribir a él. Para evitar la posibilidad de leer una
+copia parcialmente escrita del fichero de estado de directorio,
+Mercurial escribe a un fichero con un nombre único en el mismo
+directorio del fichero de estado de directorio, y luego renombra
+atómicamente este fichero temporal a \filename{dirstate}\ndt{Estado de
+directorio.}. Así se garantiza que el fichero llamado
+\filename{dirstate} esté completo, y no parcialmente escrito.
+
+\subsection{Evitar movimientos de brazo}
+
+Un aspecto crítico para el desempeño de Mercurial es evitar los
+movimientos del brazo de lectura del disco duro, ya que cualquier
+movimiento de brazo es mucho más costoso que incluso una operación de
+lectura relativamente grande.
+
+Es por esto que, por ejemplo, el estado de directorio es almacenado
+como un solo fichero. Si hubiera un estado de directorio por cada
+directorio que Mercurial monitorea, el disco haría un movimiento de
+brazo por cada directorio. En cambio, Mercurial lee el estado de
+directorio completo en un solo paso.
+
+Mercurial también usa un esquema de ``copiar al escribir'' cuando
+clona un repositorio en un mismo medio de almacenamiento local. En vez
+de copiar cada fichero de revlog del repositorio viejo al nuevo, se
+crea un ``enlace duro'', que es una manera sucinta de decir
+``estos dos nombres apuntan al mismo fichero''. Cuando Mercurial está
+a punto de escribir a uno de los ficheros de revlog, revisa si la
+cantidad de nombres apuntando al fichero es de más de uno. Si lo es,
+más de un repositorio está usando el fichero, así que Mercurial hace
+una nueva copia del fichero, privada para este repositorio.
+
+Algunos desarrolladores de control de revisiones han indicado que la
+idea de hacer una copia privada completa de un fichero no es eficiente
+desde el punto de vista de almacenamiento. Aunque esto es cierto, el
+almacenamiento es barato, y este método brinda el máximo rendimiento
+al tiempo que delega la mayor parte del trabajo de manejo de ficheros
+al sistema operativo. Un esquema alternativo seguramente reduciría el
+desempeño y aumentaría la complejidad del software, cada uno de los
+cuales es mucho más importante para la ``sensación'' que se tiene del
+software en el trabajo día a día.
+
+\subsection{Otros contenidos del estado de directorio}
+
+Debido a que Mercurial no lo fuerza a indicar si usted está
+modificando un fichero, se usa el estado de directorio para almacenar
+información extra para poder determinar efecientemente si usted ha
+modificado un fichero. Por cada fichero en el directorio de trabajo,
+se almacena el momento en que Mercurial modificó por última vez el
+fichero, y el tamaño del fichero en ese momento.
+
+Cuando usted añade (\hgcmd{add}), remueve (\hgcmd{remove}), renombra
+(\hgcmd{rename}) o copia (\hgcmd{copy}) ficheros, Mercurial actualiza
+el estado de directorio para saber qué hacer con dichos ficheros
+cuando usted haga la consignación.
+
+Cuando Mercurial está revisando el estado de los ficheros en el
+directorio de trabajo, revisa primero la fecha de modificación del
+fichero. Si no ha cambiado, el fichero no ha sido modificado. Si el
+tamaño del fichero ha cambiado, el fichero ha sido modificado. Sólo en
+el caso en que el tiempo de modificación ha cambiado, pero el tamaño
+no, es necesario leer el contenido del fichero para revisar si ha
+cambiado. Almacenar estos pocos datos reduce dramáticamente la
+cantidad de datos que Mercurial debe leer, lo que brinda una mejora en
+el rendimiento grande, comparado con otros sistemas de control de
+revisiones.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/daily.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,404 @@
+\chapter{Mercurial día a día}
+\label{chap:daily}
+
+\section{Cómo indicarle a Mercurial qué ficheros seguir}
+
+Mercurial no trabaja con ficheros en su repositorio a menos que usted
+se lo indique explícitamente.  La orden \hgcmd{status} le mostrará
+cuáles ficheros son desconocidos para Mercurial; se emplea un
+``\texttt{?}'' para mostrar tales ficheros.
+
+Para indicarle a Mercurial que tenga en cuenta un fichero, emplee la
+orden \hgcmd{add}. Una vez que haya adicionado el fichero, la línea
+referente al fichero al aplicar la orden \hgcmd{status} para tal
+fichero cambia de ``\texttt{?}'' a ``\texttt{A}''.
+\interaction{daily.files.add}
+
+Después de invocar \hgcmd{commit}, los ficheros que haya adicionado
+antes de consignar no se listarán en la salida de \hgcmd{status}.  La
+razón para esto es que \hgcmd{status} solamente le muestra aquellos
+ficheros ``interesantes'' ---~los que usted haya modificado o a aquellos
+sobre los que usted haya indicado a Mercurial hacer algo--- de forma
+predeterminada. Si tiene un repositorio que contiene miles de
+ficheros, rara vez deseará saber cuáles de ellos están siendo
+seguidos por Mercurial, pero que no han cambiado.  (De todas maneras,
+puede obtener tal información; más adelante hablaremos de ello.)
+
+
+Cuando usted añade un fichero, Mercurial no hace nada con él inmediatamente.
+En cambio, tomará una instantánea del estado del fichero la próxima vez
+que usted consigne. Continuará haciendo seguimiento a los cambios que
+haga sobre el fichero cada vez que consigne, hasta que usted lo elimine.
+
+\subsection{Nombramiento explícito e implícito de ficheros}
+
+Mercurial tiene un comportamiento útil en el cual si a una orden,
+le pasa el nombre de un directorio, todas las órdenes lo interpretarán como
+``Deseo operar en cada fichero de este directorio y sus 
+subdirectorios''.
+\interaction{daily.files.add-dir}
+Tenga en cuenta que en este ejemplo Mercurial imprimió los nombres de
+los ficheros que se adicionaron, mientras que no lo hizo en el ejemplo
+anterior cuando adicionamos el fichero con nombre \filename{a}.
+
+En el último caso hicimos explícito el nombre del fichero que
+deseábamos adicionar en la línea de órdenes, y Mercurial asume en
+tales casos que usted sabe lo que está haciendo y no imprime
+información alguna.
+
+Cuando hacemos \emph{implícitos} los nombres de los ficheros dando el
+nombre de un directorio, Mercurial efectúa el paso extra de imprimir
+el nombre de cada fichero con el que va a hacer algo.  Esto para
+aclarar lo que está sucediendo, y reducir en lo posible una sorpresa
+silenciosa pero fatal.  Este comportamiento es común a la mayoría de
+órdenes en Mercurial.
+
+\subsection{Nota al margen: Mercurial trata ficheros, no directorios}
+
+Mercurial no da seguimiento a la información de los directorios.  En
+lugar de eso tiene en cuenta las rutas de los ficheros.  Antes  de
+crear un fichero, primero crea todos los directorios que hagan falta
+para completar la ruta del mismo. Después de borrar un fichero,
+borra todos los directorios vacíos que estuvieran en la ruta del
+fichero borrado. Suena como una diferencia trivial, pero tiene una
+consecuencia práctica menor: no es posible representar un directorio
+completamente vacío en Mercurial.
+
+Los directorios vacíos rara vez son útiles, y hay soluciones
+alternativas no intrusivas que usted puede emplear para obtener el efecto
+apropiado. Los desarrolladores de Mercurial pensaron que la
+complejidad necesaria para administrar directorios vacíos no valía la
+pena frente al beneficio limitado que esta característica podría traer.
+
+Si necesita un directorio vacío en su repositorio, hay algunas formas
+de lograrlo. Una es crear un directorio, después hacer \hgcmd{add} a
+un fichero ``oculto'' dentro de ese directorio. En sistemas tipo
+Unix, cualquier fichero cuyo nombre comience con un punto
+(``\texttt{.}'') es tratado como oculto por la mayoría de
+comandos y herramientas GUI. Esta aproximación se ilustra en la figura~\ref{ex:daily:hidden}.
+
+\begin{figure}[ht]
+  \interaction{daily.files.hidden}
+  \caption{Simular un directorio vacío con un fichero oculto}
+  \label{ex:daily:hidden}
+\end{figure}
+
+Otra forma de abordar la necesidad de un directorio vacío es
+simplemente crear uno en sus guiones de construcción antes de que lo
+necesiten.
+
+\section{Cómo dejar de hacer seguimiento a un fichero}
+
+Si decide que un fichero no pertenece a su repositorio, use la orden
+\hgcmd{remove}; se borrará el fichero y le indicará a Mercurial que
+deje de hacerle seguimiento.  Los ficheros eliminados se representan
+con ``\texttt{R}'' al usar \hgcmd{status}.
+\interaction{daily.files.remove}
+
+Después de hacer \hgcmd{remove} a un fichero, Mercurial dejará de
+hacer seguimiento al mismo, incluso si recrea el fichero con el mismo
+nombre en su directorio de trabajo. Si decide recrear un fichero con
+el mismo nombre y desea que Mercurial le haga seguimiento, basta con
+hacerle \hgcmd{add}. Mercurial sabrá que el fichero recientemente
+adicionado no está relacionado con el fichero anterior que tenía el
+mismo nombre.
+
+\subsection{Al eliminar un fichero no se afecta su historial}
+
+Es preciso tener en cuenta que eliminar un fichero tiene sólo dos
+efectos.
+\begin{itemize}
+\item Se elimina la versión actual del fichero del directorio de 
+trabajo.
+\item Mercurial deja de hacer seguimiento a los cambios del fichero
+  desde la próxima consignación.
+\end{itemize}
+Al eliminar un fichero \emph{no} se altera de ninguna manera el
+\emph{historial} del mismo.
+
+Si actualiza su directorio de trabajo a un conjunto de cambios en el
+cual el fichero que eliminó aún era tenido en cuenta, éste reaparecerá en
+el directorio de trabajo, con los contenidos que este tenía cuando se
+consignó tal conjunto de cambios.  Si usted actualiza el directorio de
+trabajo a un conjunto de cambios posterior en el cual el fichero había
+sido eliminado, Mercurial lo eliminará de nuevo del directorio de
+trabajo.
+
+\subsection{Ficheros perdidos}
+
+Mercurial considera como \emph{perdido} un fichero que usted borró,
+pero para el que no se usó \hgcmd{remove}.  Los ficheros perdidos se
+representan con ``\texttt{!}'' al visualizar \hgcmd{status}.
+Las órdenes de Mercurial generalmente no harán nada con los ficheros
+perdidos.
+\interaction{daily.files.missing}
+
+Si su repositorio contiene un fichero que \hgcmd{status} reporta como
+perdido, y desea que el mismo se vaya, se puede usar 
+\hgcmdargs{remove}{\hgopt{remove}{--after}} posteriormente para
+indicarle a Mercurial que usted deseaba borrar tal fichero.
+\interaction{daily.files.remove-after}
+
+Por otro lado, si borró un fichero perdido por accidente, puede usar
+\hgcmdargs{revert}{\emph{nombre de fichero}} para recuperar el
+fichero. Reaparecerá, sin modificaciones.
+\interaction{daily.files.recover-missing}
+
+\subsection{Nota al margen: ¿Por qué decirle explícitamente a Mercurial
+  que elimine un fichero?}
+
+Es posible que se haya preguntado por qué Mercurial exige que usted le
+indique explícitamente que está borrando un fichero. Al principio del
+desarrollo de Mercurial, este permitía que usted borrara el fichero
+sin más; Mercurial se daría cuenta de la ausencia del fichero
+automáticamente después de la ejecución de \hgcmd{commit}, y dejaría de
+hacer seguimiento al fichero.  En la práctica, resultaba muy sencillo
+borrar un fichero accidentalmente sin darse cuenta.
+
+\subsection{Atajo útil---agregar y eliminar ficheros en un solo paso}
+
+Mercurial ofrece una orden combinada, \hgcmd{addremove}, que agrega
+los ficheros que no tienen seguimiento y marca los ficheros faltantes
+como eliminados.
+\interaction{daily.files.addremove}
+La orden \hgcmd{commit} se puede usar con la opción \hgopt{commit}{-A} 
+que aplica el mismo agregar-eliminar, seguido inmediatamente de una
+consignación.
+\interaction{daily.files.commit-addremove}
+
+\section{Copiar ficheros}
+
+Mercurial ofrece la orden \hgcmd{copy} para hacer una copia nueva de
+un fichero.  Cuando se copia un fichero con esta orden, Mercurial
+lleva un registro indicando que el nuevo fichero es una copia del
+fichero original. Los ficheros copiados se tratan de forma especial  cuando
+usted hace una fusión con el trabajo de alguien más.
+
+\subsection{Resultados de copiar un fichero durante una fusión}
+
+Durante una fusión los cambios ``siguen'' una copia.  Para ilustrar
+lo que esto significa, haremos un ejemplo.  Comenzaremos con el mini
+repositorio usual que contiene un solo fichero
+\interaction{daily.copy.init}
+Debemos hacer algo de trabajo en paralelo, de forma que tengamos algo para
+fusionar. Aquí clonamos el repositorio.
+\interaction{daily.copy.clone}
+De vuelta en el repositorio inicial, usemos la orden \hgcmd{copy} para hacer
+una copia del primer fichero que creamos.
+\interaction{daily.copy.copy}
+
+Si vemos la salida de la orden \hgcmd{status}, el fichero copiado luce
+tal como un fichero que se ha añadido normalmente.
+\interaction{daily.copy.status}
+Pero si usamos la opción \hgopt{status}{-C} de la orden
+\hgcmd{status}, se imprimirá otra línea: el fichero \emph{desde} el
+cual fue copiado nuestro fichero recién añadido.
+\interaction{daily.copy.status-copy}
+
+Ahora, en el repositorio que clonamos, hagamos un cambio en
+paralelo. Adicionaremos una línea de contenido al fichero original que
+creamos.
+\interaction{daily.copy.other}
+Hemos modificado el fichero \filename{file} en este
+repositorio. Cuando jalemos los cambios del primer repositorio y
+fusionemos las dos cabezas, Mercurial propagará los cambios que hemos
+hecho localmente en \filename{file} a su copia, \filename{new-file}.
+\interaction{daily.copy.merge}
+
+\subsection{¿Por qué los cambios se reflejan en las copias?}
+\label{sec:daily:why-copy}
+
+Este comportamiento de cambios en ficheros que se propagan a las
+copias de los ficheros parecería esotérico, pero en la mayoría de
+casos es absolutamente deseable.
+Es indispensable recordar que esta propagación \emph{solamente} sucede
+cuando fusionamos.  Por lo tanto si sobre un fichero se usa
+\hgcmd{copy}, y se modifica el fichero original durante el curso
+normal de su trabajo, nada pasará.
+
+Lo segundo a tener en cuenta es que las modificaciones solamente se
+propagarán en las copias únicamente si los repositorios de los cuales
+está jalando los cambios \emph{no saben} de la copia.
+
+Explicaremos a continuación la razón de este comportamiento de
+Mercurial. Digamos que yo he aplicado un arreglo de un fallo importante a un
+fichero fuente y consigné los cambios.  Por otro lado, usted decidió hacer
+\hgcmd{copy} sobre el fichero en su repositorio, sin saber acerca del
+fallo o sin ver el arreglo, y ha comenzado a trabajar sobre su copia
+del fichero.
+
+Si jala y fusiona mis cambios y Mercurial \emph{no hubiera} propagado
+los cambios en las copias, su fichero fuente tendría el fallo, a menos
+que usted haya recordado propagar el arreglo del fallo a mano, el
+mismo \emph{permanecería} en su copia del fichero.
+
+Mercurial previene esta clase de problemas, gracias a la propagación
+automática del cambio que arregló el fallo del fichero original. Hasta
+donde sé, Mercurial es el \emph{único} sistema de control de
+revisiones que propaga los cambios en las copias de esta forma.
+
+Cuando su historial de cambios tiene un registro de la copia y la
+subsecuente fusión, usualmente no es necesario propagar los cambios el
+fichero original a las copias del mismo, y por esta razón Mercurial
+propaga únicamente los cambios en las copias hasta este punto y no más
+allá.
+
+
+\subsection{Cómo hacer que los cambios \emph{no} sigan a la copia?}
+
+Si por algún motivo usted decide que esta característica de
+propagación automática de cambios en las copias no es para usted,
+simplemente use
+la orden usual de su sistema para copiar ficheros (en sistemas tipo
+Unix, es \command{cp}), y posteriormente use \hgcmd{add} sobre la nueva
+copia hecha a mano.  Antes de hacerlo, de todas maneras, relea la
+sección~\ref{sec:daily:why-copy}, y tome una decisión asegurándose que
+este comportamiento no es el apropiado para su caso específico.
+
+\subsection{Comportamiento de la orden \hgcmd{copy}}
+
+Cuando usa la orden \hgcmd{copy}, Mercurial hace una copia de cada
+fichero fuente tal como se encuentra en el directorio actual. Esto
+significa que si usted hace
+modificaciones a un fichero, y le aplica \hgcmd{copy} sin haber
+consignado primero los cambios, la nueva copia contendrá también las
+modificaciones que haya hecho hasta ese punto. (Este comportamiento me
+parece poco intuitivo, y por tal motivo lo menciono.)
+
+La orden \hgcmd{copy} actúa de forma parecida a la orden \command{cp}
+de Unix (puede usar el alias \hgcmd{cp} si le es más cómodo).  El
+último argumento es el \emph{destino}, y todos los argumentos previos
+son las \emph{fuentes}.  Si solamente indica un fichero como la
+fuente, y el destino no existe, se crea un fichero nuevo con ese nombre.
+\interaction{daily.copy.simple}
+Si el destino es un directorio, Mercurial copia las fuentes en éste.
+\interaction{daily.copy.dir-dest}
+La copia de un directorio es recursiva, y preserva la estructura del
+directorio fuente.
+\interaction{daily.copy.dir-src}
+Si tanto la fuente como el destino son directorios, la estructura de
+la fuente se recrea en el directorio destino.
+\interaction{daily.copy.dir-src-dest}
+
+De la misma forma que la orden \hgcmd{rename}, si copia un fichero
+manualmente y desea que Mercurial sepa que ha copiado un fichero,
+basta con aplicar la opción \hgopt{copy}{--after} a la orden 
+\hgcmd{copy}.
+\interaction{daily.copy.after}
+
+\section{Renombrar ficheros}
+
+La necesidad de renombrar un fichero es más común que hacer una copia
+del mismo.  La razón por la cual discutí la orden \hgcmd{copy} antes
+de hablar acerca de cambiar el nombre de los ficheros, es que
+Mercurial trata el renombrar un fichero de la misma forma que una
+copia.  Por lo tanto, saber lo que hace Mercurial cuando usted copia
+un fichero le indica qué esperar cuando renombra un fichero.
+
+Cuando usa la orden \hgcmd{rename}, Mercurial hace una copia de cada
+fichero fuente, lo borra y lo marca como fichero eliminado.
+\interaction{daily.rename.rename}
+La orden \hgcmd{status} muestra la nueva copia del fichero como
+añadida y el fichero inicial de la copia, como eliminado.
+\interaction{daily.rename.status}
+De la misma forma en que se usa la orden \hgcmd{copy}, debemos usar la
+opción \hgopt{status}{-C} de la orden \hgcmd{status} para verificar
+que el fichero añadido realmente comienza a  ser seguido por Mercurial
+como una copia del fichero original, ahora eliminado.
+\interaction{daily.rename.status-copy}
+
+Igual que con \hgcmd{remove} y \hgcmd{copy}, puede indicársele a
+Mercurial acerca de un renombramiento inmediato con la opción
+\hgopt{rename}{--after}.   El comportamiento de la orden
+\hgcmd{rename} y las opciones que acepta, son similares a la orden
+\hgcmd{copy} en casi todo.
+
+\subsection{Renombrar ficheros y fusionar cambios}
+
+Dado que el renombrado de Mercurial se implementa como un
+copiar-y-eliminar, la misma propagación de cambios ocurre cuando usted
+fusiona después de renombrar como después de hacer una copia.
+
+Si yo modifico un fichero y usted lo renombra a un nuevo fichero, y
+posteriormente fusionamos nuestros respectivos cambios, mi
+modificación al fichero bajo su nombre original se propagará en el
+fichero con el nuevo nombre. (Es lo que se esperaría que ``simplemente
+funcione,''
+pero, no todos los sistemas de control de revisiones hacen esto.)
+
+Aunque el hecho de que los cambios sigan la copia es una característica
+respecto a la cual usted puede estar de acuerdo y decir ``si, puede
+ser útil,'' debería ser claro
+que el seguimiento de cambios de un renombramiento es definitivamente
+importante.  Sin esto, sería muy sencillo que los cambios se
+quedaran atrás cuando los ficheros se renombran.
+
+\subsection{Cambios de nombre divergentes y fusión}
+
+El caso de renombramiento con nombres divergentes ocurre cuando dos
+desarrolladores comienzan  con un fichero---llamémoslo
+\filename{foo}---en sus repositorios respectivos.
+
+\interaction{rename.divergent.clone}
+%TODO we must either change the example's names, and these names, or
+%use the original names. as of now, we keep the old names
+Anne renombra el fichero a \filename{bar}.
+\interaction{rename.divergent.rename.anne}
+Mientras que Bob lo renombra como \filename{quux}.
+\interaction{rename.divergent.rename.bob}
+
+Veo esto como un conflicto porque cada desarrollador ha expresado
+intenciones diferentes acerca de cómo considera debería haberse
+nombrado el fichero.
+
+¿Qué cree que debería pasar cuando fusionen su trabajo?
+El comportamiento de Mercurial es que siempre preserva \emph{ambos}
+nombres cuando fusiona  los conjuntos de cambios que contienen nombres
+divergentes.
+%TODO traducir texto interaccion
+\interaction{rename.divergent.merge}
+
+Tenga en cuenta que Mercurial le advierte acerca de nombres
+divergentes, pero deja que usted decida qué hacer con la divergencia
+después de la fusión.
+
+\subsection{Cambios de nombre convergentes y fusión}
+
+Otra clase de conflicto al cambiar el nombre de ficheros ocurre cuando dos
+personas eligen renombrar diferentes ficheros \emph{fuente} al mismo
+\emph{destino}. En este caso Mercurial aplica su maquinaria de fusión
+usual, y le permite a usted guiar la situación a una resolución adecuada.
+
+\subsection{Otros casos límite relacionados con renombramientos}
+
+Mercurial tiene un fallo de mucho tiempo en el cual no es capaz de
+fusionar cuando por un lado hay un fichero con un nombre dado,
+mientras que en otro hay un directorio con el mismo nombre. Esto está
+documentado como~\bug{29}.
+\interaction{issue29.go}
+
+\section{Recuperarse de equivocaciones}
+
+Mercurial tiene unas órdenes poderosas que le ayudarán a recuperarse
+de equivocaciones comunes.
+
+La orden \hgcmd{revert} le permite deshacer cambios que haya hecho a
+su directorio de trabajo. Por ejemplo, si aplicó \hgcmd{add} a un
+fichero por accidente, ejecute \hgcmd{revert} con el nombre del
+fichero que añadió, y en tanto que el fichero no haya sido tocado de
+forma alguna, no será adicionado, ni seguido por Mercurial.  También
+puede usar \hgcmd{revert} para deshacerse de cambios erróneos a un
+fichero.
+
+Tenga en cuenta que la orden \hgcmd{revert} se usa para cambios que no
+han sido consignados. Cuando haya consignado un cambio, si decide que
+era un error, puede hacer algo todavía, pero sus opciones pueden estar
+más limitadas.
+
+Para obtener información acerca de la orden \hgcmd{revert} y detalles
+de cómo tratar con cambios consignados, vea el capítulo~\ref{chap:undo}.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/backout	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,83 @@
+#!/bin/bash
+
+# We have to fake the merges here, because they cause conflicts with
+# three-way command-line merge, and kdiff3 may not be available.
+
+export HGMERGE=$(mktemp)
+echo '#!/bin/sh' >> $HGMERGE
+echo 'echo first change > "$1"' >> $HGMERGE
+echo 'echo third change >> "$1"' >> $HGMERGE
+chmod 700 $HGMERGE
+
+#$ name: init
+
+hg init myrepo
+cd myrepo
+echo first change >> myfile
+hg add myfile
+hg commit -m 'first change'
+echo second change >> myfile
+hg commit -m 'second change'
+
+#$ name: simple
+
+hg backout -m 'back out second change' tip
+cat myfile
+
+#$ name: simple.log
+#$ ignore: \s+200[78]-.*
+
+hg log --style compact
+
+#$ name: non-tip.clone
+
+cd ..
+hg clone -r1 myrepo non-tip-repo
+cd non-tip-repo
+
+#$ name: non-tip.backout
+
+echo third change >> myfile
+hg commit -m 'third change'
+hg backout --merge -m 'back out second change' 1
+
+#$ name: non-tip.cat
+cat myfile
+
+#$ name: manual.clone
+
+cd ..
+hg clone -r1 myrepo newrepo
+cd newrepo
+
+#$ name: manual.backout
+
+echo third change >> myfile
+hg commit -m 'third change'
+hg backout -m 'back out second change' 1
+
+#$ name: manual.log
+
+hg log --style compact
+
+#$ name: manual.parents
+
+hg parents
+
+#$ name: manual.heads
+
+hg heads
+
+#$ name: manual.cat
+
+cat myfile
+
+#$ name: manual.merge
+
+hg merge
+hg commit -m 'merged backout with previous tip'
+cat myfile
+
+#$ name:
+
+rm $HGMERGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/bisect	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,96 @@
+#!/bin/bash
+
+if  hg -v | head -1 | grep -e "version 0.*"
+then
+#On mercurial 1.0 and later bisect is a builtin
+echo '[extensions]' >> $HGRC
+echo 'hbisect =' >> $HGRC
+fi
+
+# XXX There's some kind of horrible nondeterminism in the execution of
+# bisect at the moment.  Ugh.
+
+#$ ignore: .*
+
+#$ name: init
+
+hg init mybug
+cd mybug
+
+#$ name: commits
+
+buggy_change=22
+
+for (( i = 0; i < 35; i++ )); do
+  if [[ $i = $buggy_change ]]; then
+    echo 'i have a gub' > myfile$i
+    hg commit -q -A -m 'buggy changeset'
+  else
+    echo 'nothing to see here, move along' > myfile$i
+    hg commit -q -A -m 'normal changeset'
+  fi
+done
+
+#$ name: help
+
+hg help bisect
+
+#$ name: search.init
+
+if  hg -v | head -1 | grep -e "version 0.*"
+then
+#On mercurial 1.0 --init disappeared
+hg bisect --init
+fi
+
+#$ name: search.bad-init
+
+hg bisect --bad
+
+#$ name: search.good-init
+
+hg bisect --good 10
+
+#$ name: search.step1
+
+if grep -q 'i have a gub' *
+then
+  result=bad
+else
+  result=good
+fi
+
+echo this revision is $result
+hg bisect --$result
+
+#$ name: search.mytest
+
+mytest() {
+  if grep -q 'i have a gub' *
+  then
+    result=bad
+  else
+    result=good
+  fi
+
+  echo this revision is $result
+  hg bisect --$result
+}
+  
+#$ name: search.step2
+
+mytest
+
+#$ name: search.rest
+
+mytest
+mytest
+mytest
+
+#$ name: search.reset
+
+hg bisect --reset
+
+#$ name:
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/branch-named	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+hg init a
+cd a
+echo hello > myfile
+hg commit -A -m 'Initial commit'
+
+#$ name: branches
+
+hg tip
+hg branches
+
+#$ name: branch
+
+hg branch
+
+#$ name: create
+
+hg branch foo
+hg branch
+
+#$ name: status
+
+hg status
+hg tip
+
+#$ name: commit
+
+echo 'hello again' >> myfile
+hg commit -m 'Second commit'
+hg tip
+
+#$ name: rebranch
+
+hg branch
+hg branch bar
+echo new file > newfile
+hg commit -A -m 'Third commit'
+hg tip
+
+#$ name: parents
+
+hg parents
+hg branches
+
+#$ name: update-switchy
+
+hg update foo
+hg parents
+hg update bar
+hg parents
+
+#$ name: update-nothing
+
+hg update foo
+hg update
+
+#$ name: foo-commit
+
+echo something > somefile
+hg commit -A -m 'New file'
+hg heads
+
+#$ name: update-bar
+
+hg update bar
+
+#$ name: merge
+
+hg branch
+hg merge foo
+hg commit -m 'Merge'
+hg tip
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/branch-repo	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+hg init myproject
+cd myproject
+echo hello > myfile
+hg commit -A -m 'Initial commit'
+cd ..
+
+#$ name: tag
+
+cd myproject
+hg tag v1.0
+
+#$ name: clone
+
+cd ..
+hg clone myproject myproject-1.0.1
+
+#$ name: bugfix
+
+hg clone myproject-1.0.1 my-1.0.1-bugfix
+cd my-1.0.1-bugfix
+echo 'I fixed a bug using only echo!' >> myfile
+hg commit -m 'Important fix for 1.0.1'
+#$ ignore: /tmp/branch-repo.*
+hg push
+
+#$ name: new
+
+cd ..
+hg clone myproject my-feature
+cd my-feature
+echo 'This sure is an exciting new feature!' > mynewfile
+hg commit -A -m 'New feature'
+hg push
+
+#$ name: pull
+
+cd ..
+hg clone myproject myproject-merge
+cd myproject-merge
+hg pull ../myproject-1.0.1
+
+#$ name: merge
+
+hg merge
+hg commit -m 'Merge bugfix from 1.0.1 branch'
+hg push
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/branching	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+#$ name: init
+
+hg init main
+cd main
+echo 'This is a boring feature.' > myfile
+hg commit -A -m 'We have reached an important milestone!'
+
+#$ name: tag
+
+hg tag v1.0
+hg tip
+hg tags
+
+#$ name: main
+
+cd ../main
+echo 'This is exciting and new!' >> myfile
+hg commit -m 'Add a new feature'
+cat myfile
+
+#$ name: update
+
+cd ..
+hg clone -U main main-old
+cd main-old
+hg update v1.0
+cat myfile
+
+#$ name: clone
+
+cd ..
+hg clone -rv1.0 main stable
+
+#$ name: stable
+
+hg clone stable stable-fix
+cd stable-fix
+echo 'This is a fix to a boring feature.' > myfile
+hg commit -m 'Fix a bug'
+#$ ignore: /tmp/branching.*
+hg push
+
+#$ name:
+
+export HGMERGE=$(mktemp)
+echo '#!/bin/sh' > $HGMERGE
+echo 'echo "This is a fix to a boring feature." > "$1"' >> $HGMERGE
+echo 'echo "This is exciting and new!" >> "$1"' >> $HGMERGE
+chmod 700 $HGMERGE
+
+#$ name: merge
+
+cd ../main
+hg pull ../stable
+hg merge
+hg commit -m 'Bring in bugfix from stable branch'
+cat myfile
+
+#$ name:
+
+rm $HGMERGE
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/cmdref	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+hg init diff
+cd diff
+cat > myfile.c <<EOF
+int myfunc()
+{
+    return 1;
+}
+EOF
+hg ci -Ama
+
+sed -ie 's/return 1/return 10/' myfile.c
+
+#$ name: diff-p
+
+echo '[diff]' >> $HGRC
+echo 'showfunc = False' >> $HGRC
+
+hg diff
+
+hg diff -p
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/daily.copy	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,82 @@
+#!/bin/bash
+
+#$ name: init
+
+hg init my-copy
+cd my-copy
+echo line > file
+hg add file
+hg commit -m 'Added a file'
+
+#$ name: clone
+
+cd ..
+hg clone my-copy your-copy
+
+#$ name: copy
+
+cd my-copy
+hg copy file new-file
+
+#$ name: status
+
+hg status
+
+#$ name: status-copy
+
+hg status -C
+hg commit -m 'Copied file'
+
+#$ name: other
+
+cd ../your-copy
+echo 'new contents' >> file
+hg commit -m 'Changed file'
+
+#$ name: cat
+
+cat file
+cat ../my-copy/new-file
+
+#$ name: merge
+
+hg pull ../my-copy
+hg merge
+cat new-file
+
+#$ name:
+
+cd ..
+hg init copy-example
+cd copy-example
+echo a > a
+echo b > b
+mkdir c
+mkdir c/a
+echo c > c/a/c
+hg ci -Ama
+
+#$ name: simple
+
+mkdir k
+hg copy a k
+ls k
+
+#$ name: dir-dest
+
+mkdir d
+hg copy a b d
+ls d
+
+#$ name: dir-src
+
+hg copy c e
+
+#$ name: dir-src-dest
+
+hg copy c d
+
+#$ name: after
+
+cp a z
+hg copy --after a z
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/daily.files	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,93 @@
+#!/bin/bash
+
+#$ name: add
+
+hg init add-example
+cd add-example
+echo a > a
+hg status
+hg add a
+hg status
+hg commit -m 'Added one file'
+hg status
+
+#$ name: add-dir
+
+mkdir b
+echo b > b/b
+echo c > b/c
+mkdir b/d
+echo d > b/d/d
+hg add b
+hg commit -m 'Added all files in subdirectory'
+
+#$ name:
+
+cd ..
+
+#$ name: hidden
+
+hg init hidden-example
+cd hidden-example
+mkdir empty
+touch empty/.hidden
+hg add empty/.hidden
+hg commit -m 'Manage an empty-looking directory'
+ls empty
+cd ..
+hg clone hidden-example tmp
+ls tmp
+ls tmp/empty
+
+#$ name: remove
+
+hg init remove-example
+cd remove-example
+echo a > a
+mkdir b
+echo b > b/b
+hg add a b
+hg commit -m 'Small example for file removal'
+hg remove a
+hg status
+hg remove b
+
+#$ name:
+
+cd ..
+
+#$ name: missing
+hg init missing-example
+cd missing-example
+echo a > a
+hg add a
+hg commit -m 'File about to be missing'
+rm a
+hg status
+
+#$ name: remove-after
+
+hg remove --after a
+hg status
+
+#$ name: recover-missing
+hg revert a
+cat a
+hg status
+
+#$ name:
+
+cd ..
+
+#$ name: addremove
+
+hg init addremove-example
+cd addremove-example
+echo a > a
+echo b > b
+hg addremove
+
+#$ name: commit-addremove
+
+echo c > c
+hg commit -A -m 'Commit with addremove'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/daily.rename	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+hg init a
+cd a
+echo a > a
+hg ci -Ama
+
+#$ name: rename
+
+hg rename a b
+
+#$ name: status
+
+hg status
+
+#$ name: status-copy
+
+hg status -C
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/daily.revert	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+hg init a
+cd a
+echo 'original content' > file
+hg ci -Ama
+
+#$ name: modify
+
+cat file
+echo unwanted change >> file
+hg diff file
+
+#$ name: unmodify
+
+hg status
+hg revert file
+cat file
+
+#$ name: status
+
+hg status
+cat file.orig
+
+#$ name:
+
+rm file.orig
+
+#$ name: add
+
+echo oops > oops
+hg add oops
+hg status oops
+hg revert oops
+hg status
+
+#$ name:
+
+rm oops
+
+#$ name: remove
+
+hg remove file
+hg status
+hg revert file
+hg status
+ls file
+
+#$ name: missing
+
+rm file
+hg status
+hg revert file
+ls file
+
+#$ name: copy
+
+hg copy file new-file
+hg revert new-file
+hg status
+
+#$ name:
+
+rm new-file
+
+#$ name: rename
+
+hg rename file new-file
+hg revert new-file
+hg status
+
+#$ name: rename-orig
+hg revert file
+hg status
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/data/check_whitespace.py	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,44 @@
+#!/usr/bin/python
+
+import re
+
+def trailing_whitespace(difflines):
+    added, linenum, header = [], 0, False
+
+    for line in difflines:
+        if header:
+            # remember the name of the file that this diff affects
+            m = re.match(r'(?:---|\+\+\+) ([^\t]+)', line)
+            if m and m.group(1) != '/dev/null':
+                filename = m.group(1).split('/', 1)[-1]
+            if line.startswith('+++ '):
+                header = False
+            continue
+        if line.startswith('diff '):
+            header = True
+            continue
+        # hunk header - save the line number
+        m = re.match(r'@@ -\d+,\d+ \+(\d+),', line)
+        if m:
+            linenum = int(m.group(1))
+            continue
+        # hunk body - check for an added line with trailing whitespace
+        m = re.match(r'\+.*\s$', line)
+        if m:
+            added.append((filename, linenum))
+        if line and line[0] in ' +':
+            linenum += 1
+    return added
+
+if __name__ == '__main__':
+    import os, sys
+    
+    added = trailing_whitespace(os.popen('hg export tip'))
+    if added:
+        for filename, linenum in added:
+            print >> sys.stderr, ('%s, line %d: trailing whitespace added' %
+                                  (filename, linenum))
+        # save the commit message so we don't need to retype it
+        os.system('hg tip --template "{desc}" > .hg/commit.save')
+        print >> sys.stderr, 'commit message saved to .hg/commit.save'
+        sys.exit(1)
Binary file es/examples/data/netplug-1.2.5.tar.bz2 has changed
Binary file es/examples/data/netplug-1.2.8.tar.bz2 has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/data/remove-redundant-null-checks.patch	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,190 @@
+
+From: Jesper Juhl <jesper.juhl@gmail.com>
+
+Remove redundant NULL chck before kfree + tiny CodingStyle cleanup for
+drivers/
+
+Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
+Signed-off-by: Andrew Morton <akpm@osdl.org>
+---
+
+ drivers/char/agp/sgi-agp.c        |    5 ++---
+ drivers/char/hvcs.c               |   11 +++++------
+ drivers/message/fusion/mptfc.c    |    6 ++----
+ drivers/message/fusion/mptsas.c   |    3 +--
+ drivers/net/fs_enet/fs_enet-mii.c |    3 +--
+ drivers/net/wireless/ipw2200.c    |   22 ++++++----------------
+ drivers/scsi/libata-scsi.c        |    4 +---
+ drivers/video/au1100fb.c          |    3 +--
+ 8 files changed, 19 insertions(+), 38 deletions(-)
+
+diff -puN drivers/char/agp/sgi-agp.c~remove-redundant-null-checks-before-free-in-drivers drivers/char/agp/sgi-agp.c
+--- a/drivers/char/agp/sgi-agp.c~remove-redundant-null-checks-before-free-in-drivers
++++ a/drivers/char/agp/sgi-agp.c
+@@ -329,9 +329,8 @@ static int __devinit agp_sgi_init(void)
+ 
+ static void __devexit agp_sgi_cleanup(void)
+ {
+-	if (sgi_tioca_agp_bridges)
+-		kfree(sgi_tioca_agp_bridges);
+-	sgi_tioca_agp_bridges=NULL;
++	kfree(sgi_tioca_agp_bridges);
++	sgi_tioca_agp_bridges = NULL;
+ }
+ 
+ module_init(agp_sgi_init);
+diff -puN drivers/char/hvcs.c~remove-redundant-null-checks-before-free-in-drivers drivers/char/hvcs.c
+--- a/drivers/char/hvcs.c~remove-redundant-null-checks-before-free-in-drivers
++++ a/drivers/char/hvcs.c
+@@ -1320,11 +1320,12 @@ static struct tty_operations hvcs_ops = 
+ static int hvcs_alloc_index_list(int n)
+ {
+ 	int i;
++
+ 	hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
+ 	if (!hvcs_index_list)
+ 		return -ENOMEM;
+ 	hvcs_index_count = n;
+-	for(i = 0; i < hvcs_index_count; i++)
++	for (i = 0; i < hvcs_index_count; i++)
+ 		hvcs_index_list[i] = -1;
+ 	return 0;
+ }
+@@ -1332,11 +1333,9 @@ static int hvcs_alloc_index_list(int n)
+ static void hvcs_free_index_list(void)
+ {
+ 	/* Paranoia check to be thorough. */
+-	if (hvcs_index_list) {
+-		kfree(hvcs_index_list);
+-		hvcs_index_list = NULL;
+-		hvcs_index_count = 0;
+-	}
++	kfree(hvcs_index_list);
++	hvcs_index_list = NULL;
++	hvcs_index_count = 0;
+ }
+ 
+ static int __init hvcs_module_init(void)
+diff -puN drivers/message/fusion/mptfc.c~remove-redundant-null-checks-before-free-in-drivers drivers/message/fusion/mptfc.c
+--- a/drivers/message/fusion/mptfc.c~remove-redundant-null-checks-before-free-in-drivers
++++ a/drivers/message/fusion/mptfc.c
+@@ -305,10 +305,8 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in
+ 	}
+ 
+  out:
+-	if (pp0_array)
+-		kfree(pp0_array);
+-	if (p0_array)
+-		kfree(p0_array);
++	kfree(pp0_array);
++	kfree(p0_array);
+ 	return rc;
+ }
+ 
+diff -puN drivers/message/fusion/mptsas.c~remove-redundant-null-checks-before-free-in-drivers drivers/message/fusion/mptsas.c
+--- a/drivers/message/fusion/mptsas.c~remove-redundant-null-checks-before-free-in-drivers
++++ a/drivers/message/fusion/mptsas.c
+@@ -1378,8 +1378,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
+ 	return 0;
+ 
+  out_free_port_info:
+-	if (hba)
+-		kfree(hba);
++	kfree(hba);
+  out:
+ 	return error;
+ }
+diff -puN drivers/net/fs_enet/fs_enet-mii.c~remove-redundant-null-checks-before-free-in-drivers drivers/net/fs_enet/fs_enet-mii.c
+--- a/drivers/net/fs_enet/fs_enet-mii.c~remove-redundant-null-checks-before-free-in-drivers
++++ a/drivers/net/fs_enet/fs_enet-mii.c
+@@ -431,8 +431,7 @@ static struct fs_enet_mii_bus *create_bu
+ 	return bus;
+ 
+ err:
+-	if (bus)
+-		kfree(bus);
++	kfree(bus);
+ 	return ERR_PTR(ret);
+ }
+ 
+diff -puN drivers/net/wireless/ipw2200.c~remove-redundant-null-checks-before-free-in-drivers drivers/net/wireless/ipw2200.c
+--- a/drivers/net/wireless/ipw2200.c~remove-redundant-null-checks-before-free-in-drivers
++++ a/drivers/net/wireless/ipw2200.c
+@@ -1229,12 +1229,6 @@ static struct ipw_fw_error *ipw_alloc_er
+ 	return error;
+ }
+ 
+-static void ipw_free_error_log(struct ipw_fw_error *error)
+-{
+-	if (error)
+-		kfree(error);
+-}
+-
+ static ssize_t show_event_log(struct device *d,
+ 			      struct device_attribute *attr, char *buf)
+ {
+@@ -1296,10 +1290,9 @@ static ssize_t clear_error(struct device
+ 			   const char *buf, size_t count)
+ {
+ 	struct ipw_priv *priv = dev_get_drvdata(d);
+-	if (priv->error) {
+-		ipw_free_error_log(priv->error);
+-		priv->error = NULL;
+-	}
++
++	kfree(priv->error);
++	priv->error = NULL;
+ 	return count;
+ }
+ 
+@@ -1970,8 +1963,7 @@ static void ipw_irq_tasklet(struct ipw_p
+ 				struct ipw_fw_error *error =
+ 				    ipw_alloc_error_log(priv);
+ 				ipw_dump_error_log(priv, error);
+-				if (error)
+-					ipw_free_error_log(error);
++				kfree(error);
+ 			}
+ #endif
+ 		} else {
+@@ -11693,10 +11685,8 @@ static void ipw_pci_remove(struct pci_de
+ 		}
+ 	}
+ 
+-	if (priv->error) {
+-		ipw_free_error_log(priv->error);
+-		priv->error = NULL;
+-	}
++	kfree(priv->error);
++	priv->error = NULL;
+ 
+ #ifdef CONFIG_IPW2200_PROMISCUOUS
+ 	ipw_prom_free(priv);
+diff -puN drivers/scsi/libata-scsi.c~remove-redundant-null-checks-before-free-in-drivers drivers/scsi/libata-scsi.c
+--- a/drivers/scsi/libata-scsi.c~remove-redundant-null-checks-before-free-in-drivers
++++ a/drivers/scsi/libata-scsi.c
+@@ -222,9 +222,7 @@ int ata_cmd_ioctl(struct scsi_device *sc
+ 	 && copy_to_user(arg + sizeof(args), argbuf, argsize))
+ 		rc = -EFAULT;
+ error:
+-	if (argbuf)
+-		kfree(argbuf);
+-
++	kfree(argbuf);
+ 	return rc;
+ }
+ 
+diff -puN drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers drivers/video/au1100fb.c
+--- a/drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers
++++ a/drivers/video/au1100fb.c
+@@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void)
+ {
+ 	driver_unregister(&au1100fb_driver);
+ 
+-	if (drv_info.opt_mode)
+-		kfree(drv_info.opt_mode);
++	kfree(drv_info.opt_mode);
+ }
+ 
+ module_init(au1100fb_init);
+_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/extdiff	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+echo '[extensions]' >> $HGRC
+echo 'extdiff =' >> $HGRC
+
+hg init a
+cd a
+echo 'The first line.' > myfile
+hg ci -Ama
+echo 'The second line.' >> myfile
+
+#$ name: diff
+
+hg diff
+
+#$ name: extdiff
+
+hg extdiff
+
+#$ name: extdiff-ctx
+
+#$ ignore: ^\*\*\* a.*
+
+hg extdiff -o -NprcC5
+
+#$ name:
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/filenames	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,61 @@
+#!/bin/bash
+
+hg init a
+cd a
+mkdir -p examples src/watcher
+touch COPYING MANIFEST.in README setup.py
+touch examples/performant.py examples/simple.py
+touch src/main.py src/watcher/_watcher.c src/watcher/watcher.py src/xyzzy.txt
+
+#$ name: files
+
+hg add COPYING README examples/simple.py
+
+#$ name: dirs
+
+hg status src
+
+#$ name: wdir-subdir
+
+cd src
+hg add -n
+hg add -n .
+
+#$ name: wdir-relname
+
+hg status
+hg status `hg root`
+
+#$ name: glob.star
+
+hg add 'glob:*.py'
+
+#$ name: glob.starstar
+
+cd ..
+hg status 'glob:**.py'
+
+#$ name: glob.star-starstar
+
+hg status 'glob:*.py'
+hg status 'glob:**.py'
+
+#$ name: glob.question
+
+hg status 'glob:**.?'
+
+#$ name: glob.range
+
+hg status 'glob:**[nr-t]'
+
+#$ name: glob.group
+
+hg status 'glob:*.{in,py}'
+
+#$ name: filter.include
+
+hg status -I '*.in'
+
+#$ name: filter.exclude
+
+hg status -X '**.py' src
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/hook.msglen	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+hg init a
+cd a
+echo '[hooks]' > .hg/hgrc
+echo 'pretxncommit.msglen = test `hg tip --template {desc} | wc -c` -ge 10' >> .hg/hgrc
+
+#$ name: go
+
+cat .hg/hgrc
+echo a > a
+hg add a
+hg commit -A -m 'too short'
+hg commit -A -m 'long enough'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/hook.simple	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+#$ name: init
+
+hg init hook-test
+cd hook-test
+echo '[hooks]' >> .hg/hgrc
+echo 'commit = echo committed $HG_NODE' >> .hg/hgrc
+cat .hg/hgrc
+echo a > a
+hg add a
+hg commit -m 'testing commit hook'
+
+#$ name: ext
+#$ ignore: ^date of commit.*
+
+echo 'commit.when = echo -n "date of commit: "; date' >> .hg/hgrc
+echo a >> a
+hg commit -m 'i have two hooks'
+
+#$ name:
+
+echo '#!/bin/sh' >> check_bug_id
+echo '# check that a commit comment mentions a numeric bug id' >> check_bug_id
+echo 'hg log -r $1 --template {desc} | grep -q "\<bug *[0-9]"' >> check_bug_id
+chmod +x check_bug_id
+
+#$ name: pretxncommit
+
+cat check_bug_id
+
+echo 'pretxncommit.bug_id_required = ./check_bug_id $HG_NODE' >> .hg/hgrc
+
+echo a >> a
+hg commit -m 'i am not mentioning a bug id'
+
+hg commit -m 'i refer you to bug 666'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/hook.ws	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+hg init a
+cd a
+echo '[hooks]' > .hg/hgrc
+echo "pretxncommit.whitespace = hg export tip | (! egrep -q '^\\+.*[ \\t]$')" >> .hg/hgrc
+
+#$ name: simple
+
+cat .hg/hgrc
+echo 'a ' > a
+hg commit -A -m 'test with trailing whitespace'
+echo 'a' > a
+hg commit -A -m 'drop trailing whitespace and try again'
+
+#$ name:
+
+echo '[hooks]' > .hg/hgrc
+echo "pretxncommit.whitespace = .hg/check_whitespace.py" >> .hg/hgrc
+cp $EXAMPLE_DIR/data/check_whitespace.py .hg
+
+#$ name: better
+
+cat .hg/hgrc
+echo 'a ' >> a
+hg commit -A -m 'add new line with trailing whitespace'
+sed -i 's, *$,,' a
+hg commit -A -m 'trimmed trailing whitespace'
+
+#$ name:
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/issue29	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+#$ name: go
+
+hg init issue29
+cd issue29
+echo a > a
+hg ci -Ama
+echo b > b
+hg ci -Amb
+hg up 0
+mkdir b
+echo b > b/b
+hg ci -Amc
+
+#$ ignore: abort: Is a directory: .*
+hg merge
+
+#$ name:
+# This error is expected from the failed merge.
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/mq.dodiff	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+#$ name: diff
+
+echo 'this is my original thought' > oldfile
+echo 'i have changed my mind' > newfile
+
+diff -u oldfile newfile > tiny.patch
+
+cat tiny.patch
+
+patch < tiny.patch
+
+cat oldfile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/mq.guards	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+echo '[extensions]' >> $HGRC
+echo 'hgext.mq =' >> $HGRC
+
+hg init a
+cd a
+
+#$ name: init
+
+hg qinit
+hg qnew hello.patch
+echo hello > hello
+hg add hello
+hg qrefresh
+hg qnew goodbye.patch
+echo goodbye > goodbye
+hg add goodbye
+hg qrefresh
+
+#$ name: qguard
+
+hg qguard
+
+#$ name: qguard.pos
+
+hg qguard +foo
+hg qguard
+
+#$ name: qguard.neg
+
+hg qguard hello.patch -quux
+hg qguard hello.patch
+
+#$ name: series
+
+cat .hg/patches/series
+
+#$ name: qselect.foo
+
+hg qpop -a
+hg qselect
+hg qselect foo
+hg qselect
+
+#$ name: qselect.cat
+
+cat .hg/patches/guards
+
+#$ name: qselect.qpush
+hg qpush -a
+
+#$ name: qselect.error
+
+hg qselect +foo
+
+#$ name: qselect.quux
+
+hg qselect quux
+hg qpop -a
+hg qpush -a
+
+#$ name: qselect.foobar
+
+hg qselect foo bar
+hg qpop -a
+hg qpush -a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/mq.id	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+echo '[extensions]' >> $HGRC
+echo 'hgext.mq =' >> $HGRC
+
+hg init a
+cd a
+hg qinit
+echo 'int x;' > test.c
+hg ci -Ama
+
+hg qnew first.patch
+echo 'float c;' >> test.c
+hg qrefresh
+
+hg qnew second.patch
+echo 'double u;' > other.c
+hg add other.c
+hg qrefresh
+
+#$ name: output
+
+hg qapplied
+hg log -r qbase:qtip
+hg export second.patch
+
+#$ name:
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/mq.qinit-help	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+echo '[extensions]' >> $HGRC
+echo 'hgext.mq =' >> $HGRC
+
+#$ name: help
+hg help qinit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/mq.tarball	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+cp $EXAMPLE_DIR/data/netplug-*.tar.bz2 .
+ln -s /bin/true download
+export PATH=`pwd`:$PATH
+
+#$ name: download
+
+download netplug-1.2.5.tar.bz2
+tar jxf netplug-1.2.5.tar.bz2
+cd netplug-1.2.5
+hg init
+hg commit -q --addremove --message netplug-1.2.5
+cd ..
+hg clone netplug-1.2.5 netplug
+
+#$ name:
+
+cd netplug
+echo '[extensions]' >> $HGRC
+echo 'hgext.mq =' >> $HGRC
+cd ..
+
+#$ name: qinit
+
+cd netplug
+hg qinit
+hg qnew -m 'fix build problem with gcc 4' build-fix.patch
+perl -pi -e 's/int addr_len/socklen_t addr_len/' netlink.c
+hg qrefresh
+hg tip -p
+
+#$ name: newsource
+
+hg qpop -a
+cd ..
+download netplug-1.2.8.tar.bz2
+hg clone netplug-1.2.5 netplug-1.2.8
+cd netplug-1.2.8
+hg locate -0 | xargs -0 rm
+cd ..
+tar jxf netplug-1.2.8.tar.bz2
+cd netplug-1.2.8
+hg commit --addremove --message netplug-1.2.8
+
+#$ name: repush
+
+cd ../netplug
+hg pull ../netplug-1.2.8
+hg qpush -a
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/mq.tools	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+cp $EXAMPLE_DIR/data/remove-redundant-null-checks.patch .
+
+#$ name: tools
+diffstat -p1 remove-redundant-null-checks.patch
+
+filterdiff -i '*/video/*' remove-redundant-null-checks.patch
+
+#$ name: lsdiff
+lsdiff -nvv remove-redundant-null-checks.patch
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/mq.tutorial	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+echo '[extensions]' >> $HGRC
+echo 'hgext.mq =' >> $HGRC
+
+#$ name: qinit
+
+hg init mq-sandbox
+cd mq-sandbox
+echo 'line 1' > file1
+echo 'another line 1' > file2
+hg add file1 file2
+hg commit -m'first change'
+
+hg qinit
+
+#$ name: qnew
+
+hg tip
+hg qnew first.patch
+hg tip
+ls .hg/patches
+
+#$ name: qrefresh
+#$ ignore: \s+200[78]-.*
+
+echo 'line 2' >> file1
+hg diff
+hg qrefresh
+hg diff
+hg tip --style=compact --patch
+
+#$ name: qrefresh2
+
+echo 'line 3' >> file1
+hg status
+hg qrefresh
+hg tip --style=compact --patch
+
+#$ name: qnew2
+
+hg qnew second.patch
+hg log --style=compact --limit=2
+echo 'line 4' >> file1
+hg qrefresh
+hg tip --style=compact --patch
+hg annotate file1
+
+#$ name: qseries
+
+hg qseries
+hg qapplied
+
+#$ name: qpop
+
+hg qapplied
+hg qpop
+hg qseries
+hg qapplied
+cat file1
+
+#$ name: qpush-a
+
+hg qpush -a
+cat file1
+
+#$ name: add
+
+echo 'file 3, line 1' >> file3
+hg qnew add-file3.patch
+hg qnew -f add-file3.patch
+
+#$ name:
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/rename.divergent	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+hg init orig
+cd orig
+echo foo > foo
+hg ci -A -m 'First commit'
+cd ..
+
+#$ name: clone
+
+hg clone orig anne
+hg clone orig bob
+
+#$ name: rename.anne
+
+cd anne
+hg mv foo bar
+hg ci -m 'Rename foo to bar'
+
+#$ name: rename.bob
+
+cd ../bob
+hg mv foo quux
+hg ci -m 'Rename foo to quux'
+
+#$ name: merge
+# See http://www.selenic.com/mercurial/bts/issue455
+
+cd ../orig
+hg pull -u ../anne
+hg pull ../bob
+hg merge
+ls
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/rollback	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+hg init a
+cd a
+echo a > a
+hg ci -A -m 'First commit'
+
+echo a >> a
+
+#$ name: tip
+
+#$ name: commit
+
+hg status
+echo b > b
+hg commit -m 'Add file b'
+
+#$ name: status
+
+hg status
+hg tip
+
+#$ name: rollback
+
+hg rollback
+hg tip
+hg status
+
+#$ name: add
+
+hg add b
+hg commit -m 'Add file b, this time for real'
+
+#$ name: twice
+
+hg rollback
+hg rollback
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/run-example	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,391 @@
+#!/usr/bin/env python
+#
+# This program takes something that resembles a shell script and runs
+# it, spitting input (commands from the script) and output into text
+# files, for use in examples.
+
+import cStringIO
+import errno
+import getopt
+import os
+import pty
+import re
+import select
+import shutil
+import signal
+import stat
+import sys
+import tempfile
+import time
+
+tex_subs = {
+    '\\': '\\textbackslash{}',
+    '{': '\\{',
+    '}': '\\}',
+    }
+
+def gensubs(s):
+    start = 0
+    for i, c in enumerate(s):
+        sub = tex_subs.get(c)
+        if sub:
+            yield s[start:i]
+            start = i + 1
+            yield sub
+    yield s[start:]
+
+def tex_escape(s):
+    return ''.join(gensubs(s))
+        
+def maybe_unlink(name):
+    try:
+        os.unlink(name)
+        return True
+    except OSError, err:
+        if err.errno != errno.ENOENT:
+            raise
+    return False
+
+def find_path_to(program):
+    for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
+        name = os.path.join(p, program)
+        if os.access(name, os.X_OK):
+            return p
+    return None
+        
+class example:
+    shell = '/usr/bin/env bash'
+    ps1 = '__run_example_ps1__ '
+    ps2 = '__run_example_ps2__ '
+    pi_re = re.compile(r'#\$\s*(name|ignore):\s*(.*)$')
+    
+    timeout = 10
+
+    def __init__(self, name, verbose):
+        self.name = name
+        self.verbose = verbose
+        self.poll = select.poll()
+
+    def parse(self):
+        '''yield each hunk of input from the file.'''
+        fp = open(self.name)
+        cfp = cStringIO.StringIO()
+        for line in fp:
+            cfp.write(line)
+            if not line.rstrip().endswith('\\'):
+                yield cfp.getvalue()
+                cfp.seek(0)
+                cfp.truncate()
+        
+    def status(self, s):
+        sys.stdout.write(s)
+        if not s.endswith('\n'):
+            sys.stdout.flush()
+
+    def send(self, s):
+        if self.verbose:
+            print >> sys.stderr, '>', self.debugrepr(s)
+        while s:
+            count = os.write(self.cfd, s)
+            s = s[count:]
+
+    def debugrepr(self, s):
+        rs = repr(s)
+        limit = 60
+        if len(rs) > limit:
+            return ('%s%s ... [%d bytes]' % (rs[:limit], rs[0], len(s)))
+        else:
+            return rs
+            
+    timeout = 5
+
+    def read(self, hint):
+        events = self.poll.poll(self.timeout * 1000)
+        if not events:
+            print >> sys.stderr, ('[%stimed out after %d seconds]' %
+                                  (hint, self.timeout))
+            os.kill(self.pid, signal.SIGHUP)
+            return ''
+        return os.read(self.cfd, 1024)
+        
+    def receive(self, hint):
+        out = cStringIO.StringIO()
+        while True:
+            try:
+                if self.verbose:
+                    sys.stderr.write('< ')
+                s = self.read(hint)
+            except OSError, err:
+                if err.errno == errno.EIO:
+                    return '', ''
+                raise
+            if self.verbose:
+                print >> sys.stderr, self.debugrepr(s)
+            out.write(s)
+            s = out.getvalue()
+            if s.endswith(self.ps1):
+                return self.ps1, s.replace('\r\n', '\n')[:-len(self.ps1)]
+            if s.endswith(self.ps2):
+                return self.ps2, s.replace('\r\n', '\n')[:-len(self.ps2)]
+        
+    def sendreceive(self, s, hint):
+        self.send(s)
+        ps, r = self.receive(hint)
+        if r.startswith(s):
+            r = r[len(s):]
+        return ps, r
+    
+    def run(self):
+        ofp = None
+        basename = os.path.basename(self.name)
+        self.status('running %s ' % basename)
+        tmpdir = tempfile.mkdtemp(prefix=basename)
+
+        # remove the marker file that we tell make to use to see if
+        # this run succeeded
+        maybe_unlink(self.name + '.run')
+
+        rcfile = os.path.join(tmpdir, '.hgrc')
+        rcfp = open(rcfile, 'w')
+        print >> rcfp, '[ui]'
+        print >> rcfp, "username = Bryan O'Sullivan <bos@serpentine.com>"
+        
+        rcfile = os.path.join(tmpdir, '.bashrc')
+        rcfp = open(rcfile, 'w')
+        print >> rcfp, 'PS1="%s"' % self.ps1
+        print >> rcfp, 'PS2="%s"' % self.ps2
+        print >> rcfp, 'unset HISTFILE'
+        path = ['/usr/bin', '/bin']
+        hg = find_path_to('hg')
+        if hg and hg not in path:
+            path.append(hg)
+        def re_export(envar):
+            v = os.getenv(envar)
+            if v is not None:
+                print >> rcfp, 'export ' + envar + '=' + v
+        print >> rcfp, 'export PATH=' + ':'.join(path)
+        re_export('PYTHONPATH')
+        print >> rcfp, 'export EXAMPLE_DIR="%s"' % os.getcwd()
+        print >> rcfp, 'export HGMERGE=merge'
+        print >> rcfp, 'export LANG=C'
+        print >> rcfp, 'export LC_ALL=C'
+        print >> rcfp, 'export TZ=GMT'
+        print >> rcfp, 'export HGRC="%s/.hgrc"' % tmpdir
+        print >> rcfp, 'export HGRCPATH=$HGRC'
+        print >> rcfp, 'cd %s' % tmpdir
+        rcfp.close()
+        sys.stdout.flush()
+        sys.stderr.flush()
+        self.pid, self.cfd = pty.fork()
+        if self.pid == 0:
+            cmdline = ['/usr/bin/env', '-i', 'bash', '--noediting',
+                       '--noprofile', '--norc']
+            try:
+                os.execv(cmdline[0], cmdline)
+            except OSError, err:
+                print >> sys.stderr, '%s: %s' % (cmdline[0], err.strerror)
+                sys.stderr.flush()
+                os._exit(0)
+        self.poll.register(self.cfd, select.POLLIN | select.POLLERR |
+                           select.POLLHUP)
+
+        prompts = {
+            '': '',
+            self.ps1: '$',
+            self.ps2: '>',
+            }
+
+        ignore = [
+            r'\d+:[0-9a-f]{12}', # changeset number:hash
+            r'[0-9a-f]{40}', # long changeset hash
+            r'[0-9a-f]{12}', # short changeset hash
+            r'^(?:---|\+\+\+) .*', # diff header with dates
+            r'^date:.*', # date
+            #r'^diff -r.*', # "diff -r" is followed by hash
+            r'^# Date \d+ \d+', # hg patch header
+            ]
+
+        err = False
+        read_hint = ''
+
+        try:
+            try:
+                # eat first prompt string from shell
+                self.read(read_hint)
+                # setup env and prompt
+                ps, output = self.sendreceive('source %s\n' % rcfile,
+                                              read_hint)
+                for hunk in self.parse():
+                    # is this line a processing instruction?
+                    m = self.pi_re.match(hunk)
+                    if m:
+                        pi, rest = m.groups()
+                        if pi == 'name':
+                            self.status('.')
+                            out = rest
+                            if out in ('err', 'lxo', 'out', 'run', 'tmp'):
+                                print >> sys.stderr, ('%s: illegal section '
+                                                      'name %r' %
+                                                      (self.name, out))
+                                return 1
+                            assert os.sep not in out
+                            if ofp is not None:
+                                ofp.close()
+                                err |= self.rename_output(ofp_basename, ignore)
+                            if out:
+                                ofp_basename = '%s.%s' % (self.name, out)
+                                read_hint = ofp_basename + ' '
+                                ofp = open(ofp_basename + '.tmp', 'w')
+                            else:
+                                ofp = None
+                        elif pi == 'ignore':
+                            ignore.append(rest)
+                    elif hunk.strip():
+                        # it's something we should execute
+                        newps, output = self.sendreceive(hunk, read_hint)
+                        if not ofp:
+                            continue
+                        # first, print the command we ran
+                        if not hunk.startswith('#'):
+                            nl = hunk.endswith('\n')
+                            hunk = ('%s \\textbf{%s}' %
+                                    (prompts[ps],
+                                     tex_escape(hunk.rstrip('\n'))))
+                            if nl: hunk += '\n'
+                        ofp.write(hunk)
+                        # then its output
+                        ofp.write(tex_escape(output))
+                    ps = newps
+                self.status('\n')
+            except:
+                print >> sys.stderr, '(killed)'
+                os.kill(self.pid, signal.SIGKILL)
+                pid, rc = os.wait()
+                raise
+            else:
+                try:
+                    ps, output = self.sendreceive('exit\n', read_hint)
+                    if ofp is not None:
+                        ofp.write(output)
+                        ofp.close()
+                        err |= self.rename_output(ofp_basename, ignore)
+                    os.close(self.cfd)
+                except IOError:
+                    pass
+                os.kill(self.pid, signal.SIGTERM)
+                pid, rc = os.wait()
+                err = err or rc
+                if err:
+                    if os.WIFEXITED(rc):
+                        print >> sys.stderr, '(exit %s)' % os.WEXITSTATUS(rc)
+                    elif os.WIFSIGNALED(rc):
+                        print >> sys.stderr, '(signal %s)' % os.WTERMSIG(rc)
+                else:
+                    open(self.name + '.run', 'w')
+                return err
+        finally:
+            shutil.rmtree(tmpdir)
+
+    def rename_output(self, base, ignore):
+        mangle_re = re.compile('(?:' + '|'.join(ignore) + ')')
+        def mangle(s):
+            return mangle_re.sub('', s)
+        def matchfp(fp1, fp2):
+            while True:
+                s1 = mangle(fp1.readline())
+                s2 = mangle(fp2.readline())
+                if cmp(s1, s2):
+                    break
+                if not s1:
+                    return True
+            return False
+
+        oldname = base + '.out'
+        tmpname = base + '.tmp'
+        errname = base + '.err'
+        errfp = open(errname, 'w+')
+        for line in open(tmpname):
+            errfp.write(mangle_re.sub('', line))
+        os.rename(tmpname, base + '.lxo')
+        errfp.seek(0)
+        try:
+            oldfp = open(oldname)
+        except IOError, err:
+            if err.errno != errno.ENOENT:
+                raise
+            os.rename(errname, oldname)
+            return False
+        if matchfp(oldfp, errfp):
+            os.unlink(errname)
+            return False
+        else:
+            print >> sys.stderr, '\nOutput of %s has changed!' % base
+            os.system('diff -u %s %s 1>&2' % (oldname, errname))
+            return True
+
+def print_help(exit, msg=None):
+    if msg:
+        print >> sys.stderr, 'Error:', msg
+    print >> sys.stderr, 'Usage: run-example [options] [test...]'
+    print >> sys.stderr, 'Options:'
+    print >> sys.stderr, '  -a --all       run all tests in this directory'
+    print >> sys.stderr, '  -h --help      print this help message'
+    print >> sys.stderr, '  -v --verbose   display extra debug output'
+    sys.exit(exit)
+
+def main(path='.'):
+    opts, args = getopt.getopt(sys.argv[1:], '?ahv',
+                               ['all', 'help', 'verbose'])
+    verbose = False
+    run_all = False
+    for o, a in opts:
+        if o in ('-h', '-?', '--help'):
+            print_help(0)
+        if o in ('-a', '--all'):
+            run_all = True
+        if o in ('-v', '--verbose'):
+            verbose = True
+    errs = 0
+    if args:
+        for a in args:
+            try:
+                st = os.lstat(a)
+            except OSError, err:
+                print >> sys.stderr, '%s: %s' % (a, err.strerror)
+                errs += 1
+                continue
+            if stat.S_ISREG(st.st_mode) and st.st_mode & 0111:
+                if example(a, verbose).run():
+                    errs += 1
+            else:
+                print >> sys.stderr, '%s: not a file, or not executable' % a
+                errs += 1
+    elif run_all:
+        names = os.listdir(path)
+        names.sort()
+        for name in names:
+            if name == 'run-example' or name.startswith('.'): continue
+            if name.endswith('.out') or name.endswith('~'): continue
+            if name.endswith('.run'): continue
+            pathname = os.path.join(path, name)
+            try:
+                st = os.lstat(pathname)
+            except OSError, err:
+                # could be an output file that was removed while we ran
+                if err.errno != errno.ENOENT:
+                    raise
+                continue
+            if stat.S_ISREG(st.st_mode) and st.st_mode & 0111:
+                if example(pathname, verbose).run():
+                    errs += 1
+        print >> open(os.path.join(path, '.run'), 'w'), time.asctime()
+    else:
+        print_help(1, msg='no test names given, and --all not provided')
+    return errs
+
+if __name__ == '__main__':
+    try:
+        sys.exit(main())
+    except KeyboardInterrupt:
+        print >> sys.stderr, 'interrupted!'
+        sys.exit(1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/svn-long.txt	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,11 @@
+------------------------------------------------------------------------
+r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
+Changed paths:
+   M /gen2/trunk/src/linux-kernel/infiniband/core/cma.c
+
+On reporting a route error, also include the status for the error,
+rather than indicating a status of 0 when an error has occurred.
+
+Signed-off-by: Sean Hefty <sean.hefty@intel.com>
+
+------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/svn-short.txt	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,9 @@
+------------------------------------------------------------------------
+r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
+
+On reporting a route error, also include the status for the error,
+rather than indicating a status of 0 when an error has occurred.
+
+Signed-off-by: Sean Hefty <sean.hefty@intel.com>
+
+------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/svn.style	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,2 @@
+header = '------------------------------------------------------------------------\n\n'
+changeset = svn.template
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/svn.template	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,5 @@
+r{rev} | {author|user} | {date|isodate} ({date|rfc822date})
+
+{desc|strip|fill76}
+
+------------------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/tag	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+#$ name: init
+
+hg init mytag
+cd mytag
+
+echo hello > myfile
+hg commit -A -m 'Initial commit'
+
+#$ name: tag
+
+hg tag v1.0
+
+#$ name: tags
+
+hg tags
+
+#$ name: log
+
+hg log
+
+#$ name: log.v1.0
+
+echo goodbye > myfile2
+hg commit -A -m 'Second commit'
+hg log -r v1.0
+
+#$ name: remove
+
+hg tag --remove v1.0
+hg tags
+
+#$ name: replace
+
+hg tag -r 1 v1.1
+hg tags
+hg tag -r 2 v1.1
+hg tag -f -r 2 v1.1
+hg tags
+
+#$ name: tip
+
+hg tip
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/template.simple	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,96 @@
+#!/bin/bash
+
+# So many different bits of random output, it would be a nightmare to
+# ignore each individually.
+#$ ignore: .*
+
+hg init myrepo
+cd myrepo
+echo hello > hello
+hg commit -Am'added hello'
+
+echo hello >> hello
+echo goodbye > goodbye
+echo '   added line to end of <<hello>> file.' > ../msg
+echo '' >> ../msg
+echo 'in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.' >> ../msg
+
+hg commit -Al../msg
+
+hg tag mytag
+hg tag v0.1
+
+#$ name: normal
+
+hg log -r1
+
+#$ name: compact
+
+hg log --style compact
+
+#$ name: changelog
+
+hg log --style changelog
+
+#$ name: simplest
+
+hg log -r1 --template 'i saw a changeset\n'
+
+#$ name: simplesub
+
+hg log --template 'i saw a changeset: {desc}\n'
+
+#$ name: keywords
+
+hg log -r1 --template 'author: {author}\n'
+hg log -r1 --template 'desc:\n{desc}\n'
+hg log -r1 --template 'files: {files}\n'
+hg log -r1 --template 'file_adds: {file_adds}\n'
+hg log -r1 --template 'file_dels: {file_dels}\n'
+hg log -r1 --template 'node: {node}\n'
+hg log -r1 --template 'parents: {parents}\n'
+hg log -r1 --template 'rev: {rev}\n'
+hg log -r1 --template 'tags: {tags}\n'
+
+#$ name: datekeyword
+
+hg log -r1 --template 'date: {date}\n'
+hg log -r1 --template 'date: {date|isodate}\n'
+
+#$ name: manyfilters
+
+hg log -r1 --template '{author}\n'
+hg log -r1 --template '{author|domain}\n'
+hg log -r1 --template '{author|email}\n'
+hg log -r1 --template '{author|obfuscate}\n' | cut -c-76
+hg log -r1 --template '{author|person}\n'
+hg log -r1 --template '{author|user}\n'
+
+hg log -r1 --template 'looks almost right, but actually garbage: {date}\n'
+hg log -r1 --template '{date|age}\n'
+hg log -r1 --template '{date|date}\n'
+hg log -r1 --template '{date|hgdate}\n'
+hg log -r1 --template '{date|isodate}\n'
+hg log -r1 --template '{date|rfc822date}\n'
+hg log -r1 --template '{date|shortdate}\n'
+
+hg log -r1 --template '{desc}\n' | cut -c-76
+hg log -r1 --template '{desc|addbreaks}\n' | cut -c-76
+hg log -r1 --template '{desc|escape}\n' | cut -c-76
+hg log -r1 --template '{desc|fill68}\n'
+hg log -r1 --template '{desc|fill76}\n'
+hg log -r1 --template '{desc|firstline}\n'
+hg log -r1 --template '{desc|strip}\n' | cut -c-76
+hg log -r1 --template '{desc|tabindent}\n' | expand | cut -c-76
+
+hg log -r1 --template '{node}\n'
+hg log -r1 --template '{node|short}\n'
+
+#$ name: combine
+
+hg log -r1 --template 'description:\n\t{desc|strip|fill68|tabindent}\n'
+
+#$ name: rev
+
+echo 'changeset = "rev: {rev}\n"' > rev
+hg log -l1 --style ./rev
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/template.svnstyle	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,70 @@
+#!/bin/bash
+
+svn() {
+  cat $EXAMPLE_DIR/svn-short.txt
+}
+
+#$ name: short
+
+svn log -r9653
+
+#$ name:
+
+hg init myrepo
+cd myrepo
+
+echo hello > hello
+hg commit -Am'added hello'
+
+echo hello >> hello
+echo goodbye > goodbye
+echo '   added line to end of <<hello>> file.' > ../msg
+echo '' >> ../msg
+echo 'in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.' >> ../msg
+
+hg commit -Al../msg
+
+hg tag mytag
+hg tag v0.1
+
+echo 'changeset = "{node|short}\n"' > svn.style
+
+#$ name: id
+
+hg log -r0 --template '{node}'
+
+#$ name: simplest
+
+cat svn.style
+hg log -r1 --style svn.style
+
+#$ name:
+
+echo 'changeset =' > broken.style
+
+#$ name: syntax.input
+
+cat broken.style
+
+#$ name: syntax.error
+
+hg log -r1 --style broken.style
+
+#$ name:
+
+cp $EXAMPLE_DIR/svn.style .
+cp $EXAMPLE_DIR/svn.template .
+
+#$ name: template
+
+cat svn.template
+
+#$ name: style
+
+cat svn.style
+
+#$ name: result
+#$ ignore: \| 200[78].*
+
+hg log -r1 --style svn.style
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/tour	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,194 @@
+#!/bin/bash
+
+#$ name: version
+
+hg version
+
+#$ name: help
+
+hg help init
+
+#$ name: clone
+
+hg clone http://hg.serpentine.com/tutorial/hello
+
+#$ name: ls
+#$ ignore: ^drwx.*
+#$ ignore: ^total \d+
+
+ls -l
+ls hello
+
+#$ name: ls-a
+
+cd hello
+ls -a
+
+#$ name: log
+
+hg log
+
+#$ name: log-r
+
+hg log -r 3
+hg log -r 0272e0d5a517
+hg log -r 1 -r 4
+
+#$ name: log.range
+
+hg log -r 2:4
+
+#$ name: log-v
+
+hg log -v -r 3
+
+#$ name: log-vp
+
+hg log -v -p -r 2
+
+#$ name: reclone
+
+cd ..
+hg clone hello my-hello
+cd my-hello
+
+#$ name: sed
+
+sed -i '/printf/a\\tprintf("hello again!\\n");' hello.c
+
+#$ name: status
+
+ls
+hg status
+
+#$ name: diff
+
+hg diff
+
+#$ name:
+
+export HGEDITOR='echo Added an extra line of output >'
+
+#$ name: commit
+
+hg commit
+
+#$ name: merge.dummy1
+
+hg log -r 5 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV5.my-hello
+
+#$ name: tip
+
+hg tip -vp
+
+#$ name: clone-pull
+
+cd ..
+hg clone hello hello-pull
+
+#$ name: incoming
+
+cd hello-pull
+hg incoming ../my-hello
+
+#$ name: pull
+
+hg tip
+hg pull ../my-hello
+hg tip
+
+#$ name: update
+
+grep printf hello.c
+hg update tip
+grep printf hello.c
+
+#$ name: parents
+
+hg parents
+
+#$ name: older
+
+hg update 2
+hg parents
+hg update
+
+#$ name: clone-push
+
+cd ..
+hg clone hello hello-push
+
+#$ name: outgoing
+
+cd my-hello
+hg outgoing ../hello-push
+
+#$ name: push
+
+hg push ../hello-push
+
+#$ name: push.nothing
+
+hg push ../hello-push
+
+#$ name: outgoing.net
+
+hg outgoing http://hg.serpentine.com/tutorial/hello
+
+#$ name: push.net
+
+hg push http://hg.serpentine.com/tutorial/hello
+
+#$ name: merge.clone
+
+cd ..
+hg clone hello my-new-hello
+cd my-new-hello
+sed -i '/printf/i\\tprintf("once more, hello.\\n");' hello.c
+hg commit -m 'A new hello for a new day.'
+
+#$ name: merge.dummy2
+
+hg log -r 5 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV5.my-new-hello
+
+#$ name: merge.cat
+
+cat hello.c
+cat ../my-hello/hello.c
+
+#$ name: merge.pull
+
+hg pull ../my-hello
+
+#$ name: merge.dummy3
+
+hg log -r 6 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV6.my-new-hello
+
+#$ name: merge.heads
+
+hg heads
+
+#$ name: merge.update
+
+hg update
+
+#$ name: merge.merge
+
+hg merge
+
+#$ name: merge.parents
+
+hg parents
+cat hello.c
+
+#$ name: merge.commit
+
+hg commit -m 'Merged changes'
+
+#$ name: merge.dummy4
+
+hg log -r 7 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV7.my-new-hello
+
+#$ name: merge.tip
+
+hg tip
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/examples/tour-merge-conflict	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+hg init scam
+cd scam
+
+#$ name: wife
+
+cat > letter.txt <<EOF
+Greetings!
+
+I am Mariam Abacha, the wife of former
+Nigerian dictator Sani Abacha.
+EOF
+
+hg add letter.txt
+hg commit -m '419 scam, first draft'
+
+#$ name: cousin
+
+cd ..
+hg clone scam scam-cousin
+cd scam-cousin
+
+cat > letter.txt <<EOF
+Greetings!
+
+I am Shehu Musa Abacha, cousin to the former
+Nigerian dictator Sani Abacha.
+EOF
+
+hg commit -m '419 scam, with cousin'
+
+#$ name: son
+
+cd ..
+hg clone scam scam-son
+cd scam-son
+
+cat > letter.txt <<EOF
+Greetings!
+
+I am Alhaji Abba Abacha, son of the former
+Nigerian dictator Sani Abacha.
+EOF
+
+hg commit -m '419 scam, with son'
+
+#$ name: pull
+
+cd ..
+hg clone scam-cousin scam-merge
+cd scam-merge
+hg pull -u ../scam-son
+
+#$ name: merge
+#$ ignore: [<>]{7} /tmp/.*
+
+export HGMERGE=merge
+hg merge
+cat letter.txt
+
+#$ name: commit
+
+cat > letter.txt <<EOF
+Greetings!
+
+I am Bryan O'Sullivan, no relation of the former
+Nigerian dictator Sani Abacha.
+EOF
+
+hg resolve -m letter.txt
+hg commit -m 'Send me your money'
+hg tip
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/fblinks	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1 @@
+../en/fblinks
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/feature-branches.dot	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,8 @@
+digraph feature_branches {
+	maestro -> cripto;
+	maestro -> sistemadearchivos;
+	maestro -> ipc;
+	maestro -> memoria;
+	maestro -> red;
+	maestro -> seguridad;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/filelog.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="filelog.svg"
+   sodipodi:docbase="/home/arun/hgbook/en"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective57" />
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3128"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <linearGradient
+       id="linearGradient2887">
+      <stop
+         style="stop-color:#91cfcf;stop-opacity:1;"
+         offset="0"
+         id="stop2889" />
+      <stop
+         style="stop-color:aqua;stop-opacity:0;"
+         offset="1"
+         id="stop2891" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient2795">
+      <stop
+         style="stop-color:#ccc;stop-opacity:1;"
+         offset="0"
+         id="stop2797" />
+      <stop
+         style="stop-color:#ccc;stop-opacity:0;"
+         offset="1"
+         id="stop2799" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2795"
+       id="linearGradient3170"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(121.2183,94.95434)"
+       x1="81.322357"
+       y1="404.34424"
+       x2="201.52036"
+       y2="373.03967" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2887"
+       id="linearGradient3172"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(0,12)"
+       x1="62.634491"
+       y1="503.3392"
+       x2="248.49242"
+       y2="462.94327" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2795"
+       id="linearGradient3174"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)"
+       x1="81.322357"
+       y1="404.34424"
+       x2="201.52036"
+       y2="373.03967" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2887"
+       id="linearGradient3176"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(0,12)"
+       x1="62.634491"
+       y1="503.3392"
+       x2="248.49242"
+       y2="462.94327" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2795"
+       id="linearGradient3208"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)"
+       x1="81.322357"
+       y1="404.34424"
+       x2="201.52036"
+       y2="373.03967" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2887"
+       id="linearGradient3210"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(0,12)"
+       x1="62.634491"
+       y1="503.3392"
+       x2="248.49242"
+       y2="462.94327" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2795"
+       id="linearGradient3212"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(121.2183,94.95434)"
+       x1="81.322357"
+       y1="404.34424"
+       x2="201.52036"
+       y2="373.03967" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2887"
+       id="linearGradient3214"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(0,12)"
+       x1="62.634491"
+       y1="503.3392"
+       x2="248.49242"
+       y2="462.94327" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2795"
+       id="linearGradient3256"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.2343775,0,0,0.9981848,103.25588,95.681888)"
+       x1="74.301666"
+       y1="431.67441"
+       x2="260.05884"
+       y2="369.95322" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2887"
+       id="linearGradient3258"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.228929,0,0,0.9972824,-62.037003,13.312997)"
+       x1="62.634491"
+       y1="503.3392"
+       x2="248.49242"
+       y2="462.94327" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2795"
+       id="linearGradient3260"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.2300738,0,0,0.6517275,219.97511,153.61527)"
+       x1="74.387527"
+       y1="431.80576"
+       x2="259.97339"
+       y2="369.82224" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient2887"
+       id="linearGradient3262"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.2289272,0,0,0.9972824,-62.036756,13.312985)"
+       x1="62.634491"
+       y1="503.3392"
+       x2="248.49242"
+       y2="462.94327" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4"
+     inkscape:cx="455.8122"
+     inkscape:cy="520"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="1280"
+     inkscape:window-height="800"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     showgrid="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       style="opacity:1;fill:#abadf8;fill-opacity:1;stroke:#595959;stroke-width:0.93760371;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3180"
+       width="273.81375"
+       height="199.06245"
+       x="369.1796"
+       y="351.79019" />
+    <rect
+       style="opacity:1;fill:#a2f69c;fill-opacity:1;stroke:#595959;stroke-width:0.93760341;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3178"
+       width="273.81339"
+       height="199.06233"
+       x="72.699799"
+       y="351.78983" />
+    <g
+       id="g3144"
+       transform="translate(80.467048,0.71578)">
+      <g
+         id="g2940">
+        <rect
+           style="fill:url(#linearGradient3260);fill-opacity:1;stroke:#000000;stroke-width:0.89536202;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect2914"
+           width="227.38896"
+           height="39.500999"
+           x="311.92496"
+           y="395.08627" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="323.72824"
+           y="416.7626"
+           id="text2918"><tspan
+             sodipodi:role="line"
+             id="tspan2920"
+             x="323.72824"
+             y="416.7626"
+             style="font-family:Courier">.hg/store/data/README.i</tspan></text>
+      </g>
+      <g
+         transform="translate(3.79093e-5,-80.1853)"
+         id="g2945">
+        <g
+           id="g2955">
+          <rect
+             y="475.4968"
+             x="15.550935"
+             height="39.500999"
+             width="227.17694"
+             id="rect2947"
+             style="fill:url(#linearGradient3262);fill-opacity:1;stroke:#000000;stroke-width:1.10706258;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+          <text
+             id="text2949"
+             y="498.35123"
+             x="31.230644"
+             style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+             xml:space="preserve"><tspan
+               style="font-family:Courier"
+               y="498.35123"
+               x="31.230644"
+               id="tspan2951"
+               sodipodi:role="line">README</tspan></text>
+        </g>
+      </g>
+      <path
+         inkscape:connector-type="polyline"
+         id="path2960"
+         d="M 242.94685,414.91115 C 242.94685,414.91115 293.61127,415.26754 310.16269,415.38633"
+         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1.02046943px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+         sodipodi:nodetypes="cz" />
+    </g>
+    <g
+       id="g3156"
+       transform="translate(80.467048,0.71578)">
+      <g
+         transform="translate(116,0)"
+         id="g2831">
+        <rect
+           style="fill:url(#linearGradient3256);fill-opacity:1;stroke:#000000;stroke-width:1.11001658;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect1906"
+           width="228.18446"
+           height="60.499123"
+           x="195.52719"
+           y="465.51859" />
+        <g
+           id="g2803"
+           transform="translate(-0.893671,1.833581)">
+          <text
+             id="text1884"
+             y="483.92801"
+             x="208.95944"
+             style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+             xml:space="preserve"><tspan
+               style="font-family:Courier"
+               y="483.92801"
+               x="208.95944"
+               id="tspan1886"
+               sodipodi:role="line">.hg/store/data/src/hello.c.d</tspan></text>
+          <text
+             id="text1888"
+             y="507.79309"
+             x="208.95944"
+             style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+             xml:space="preserve"><tspan
+               style="font-family:Courier"
+               y="507.79309"
+               x="208.95944"
+               id="tspan1890"
+               sodipodi:role="line">.hg/store/data/src/hello.c.i</tspan></text>
+        </g>
+      </g>
+      <g
+         id="g2907">
+        <rect
+           style="fill:url(#linearGradient3258);fill-opacity:1;stroke:#000000;stroke-width:1.10706329;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect2843"
+           width="227.17728"
+           height="39.500999"
+           x="15.550805"
+           y="475.4968" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="31.230644"
+           y="498.35123"
+           id="text2847"><tspan
+             sodipodi:role="line"
+             id="tspan2849"
+             x="31.230644"
+             y="498.35123"
+             style="font-family:Courier">src/hello.c</tspan></text>
+      </g>
+      <path
+         inkscape:connection-end="#g2831"
+         inkscape:connection-start="#g2907"
+         inkscape:connector-type="polyline"
+         id="path2962"
+         d="M 242.4315,495.88043 C 242.4315,495.88043 292.8861,495.99942 310.04102,496.03909"
+         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+         sodipodi:nodetypes="cs" />
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="98.496666"
+       y="373.96353"
+       id="text3216"><tspan
+         sodipodi:role="line"
+         id="tspan3218"
+         x="98.496666"
+         y="373.96353">Directorio de trabajo</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="391.39197"
+       y="373.96353"
+       id="text3228"><tspan
+         sodipodi:role="line"
+         id="tspan3230"
+         x="391.39197"
+         y="373.96353">Repositorio</tspan></text>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/filenames.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,344 @@
+\chapter{Nombres de ficheros y asociación de patrones}
+\label{chap:names}
+
+Mercurial provee mecanismos que le permiten trabajar con nombres de
+ficheros en una manera consistente y expresiva.
+
+\section{Nombrado de ficheros simple}
+
+% TODO traducción literal de "under the hood". revisar
+Mercurial usa un mecanismo unificado ``bajo el capó'' para manejar
+nombres de ficheros. Cada comando se comporta de manera uniforme con
+respecto a los nombres de fichero. La manera en que los comandos
+operan con nombres de fichero es la siguiente.
+
+Si usted especifica explícitamente nombres reales de ficheros en la
+línea de comandos, Mercurial opera únicamente sobre dichos ficheros,
+como usted esperaría.
+\interaction{filenames.files}
+
+Cuando usted provee el nombre de un directorio, Mercurial interpreta
+eso como ``opere en cada fichero en este directorio y sus
+subdirectorios''. Mercurial va por todos los ficheros y subdirectorios
+de un directorio en orden alfabético. Cuando encuentra un
+subdirectorio, lo recorrerá antes de continuar con el directorio
+actual.
+\interaction{filenames.dirs}
+
+\section{Ejecución de comandos sin ningún nombre de fichero}
+
+Los comandos de Mercurial que trabajan con nombres de fichero tienen
+comportamientos por defecto adecuados cuando son utilizados sin pasar
+ningún patrón o nombre de fichero. El tipo de comportamiento depende
+de lo que haga el comando. Aquí presento unas cuantas reglas generales
+que usted puede usar para que es lo que probablemente hará un comando
+si usted no le pasa ningún nombre de fichero con el cual trabajar.
+\begin{itemize}
+\item Muchos comandos operarán sobre el directorio de trabajo
+    completo. Por ejemplo, esto es lo que hace el comando
+    \hgcmd{add},
+\item Si el comando tiene efectos difíciles o incluso imposibles de
+    revertir, se le obligará a usted a proveer explícitamente al menos
+    % TODO revisar ese "lo proteje a usted"
+    un nombre o patrón (ver más abajo). Esto lo proteje a usted de,
+    por ejemplo, borrar ficheros accidentalmente al ejecutar
+    \hgcmd{remove} sin ningún argumento.
+\end{itemize}
+
+
+Es fácil evitar este comportamiento por defecto, si no es el adecuado
+para usted. Si un comando opera normalmente en todo el directorio de
+trabajo, usted puede llamarlo para que trabaje sólo en el directorio
+actual y sus subdirectorio pasándole el nombre ``\dirname{.}''.
+\interaction{filenames.wdir-subdir}
+
+Siguiendo la misma línea, algunos comandos normalmente imprimen las
+rutas de ficheros con respecto a la raíz del repositorio, aún si usted
+los llama dentro de un subdirectorio. Dichos comandos imprimirán las
+rutas de los ficheros respecto al directorio en que usted se encuentra
+si se les pasan nombres explícitos. Vamos a ejecutar el comando
+\hgcmd{status} desde un subdirectorio, y a hacer que opere en el
+directorio de trabajo completo, a la vez que todas las rutas de
+ficheros se imprimen respecto a nuestro subdirectorio, pasándole la
+salida del comando \hgcmd{root}.
+\interaction{filenames.wdir-relname}
+
+\section{Reportar que está pasando}
+
+El ejemplo con el comando \hgcmd{add} en la sección anterior ilustra
+algo más que es útil acerca de los comandos de Mercurial. Si un
+comando opera en un fichero que usted no pasó explícitamente en la
+línea de comandos, usualmente se imprimirá el nombre del fichero, para
+que usted no sea sorprendido por lo que sucede.
+
+Esto es el principio de \emph{mínima sorpresa}. Si usted se ha
+referido explícitamente a un fichero en la línea de comandos, no tiene
+mucho sentido repetir esto de vuelta a usted. Si Mercurial está
+actuando en un fichero \emph{implícitamente}, porque usted no pasó
+nombres, ni directorios, ni patrones (ver más abajo), lo más seguro es
+decirle a usted qué se está haciendo.
+
+Usted puede silenciar a los comandos que se comportan de esta manera
+usando la opción \hggopt{-q}.  También puede hacer que impriman el
+nombre de cada fichero, aún aquellos que usted indicó explícitamente,
+usando la opción \hggopt{-v}.
+
+\section{Uso de patrones para identificar ficheros}
+
+Además de trabajar con nombres de ficheros y directorios, Mercurial le
+permite usar \emph{patrones} para identificar ficheros. El manejo de
+patrones de Mercurial es expresivo.
+
+En sistemas tipo Unix (Linux, MacOS, etc.), el trabajo de asociar
+patrones con nombres de ficheros recae sobre el intérprete de comandos.
+En estos sistemas, usted debe indicarle explícitamente a Mercurial que
+el nombre que se le pasa es un patrón. En Windows, el intérprete no
+expande los patrones, así que Mercurial identificará automáticamente
+los nombres que son patrones, y hará la expansión necesaria.
+
+Para pasar un patrón en vez de un nombre normal en la línea de
+comandos, el mecanismo es simple:
+\begin{codesample2}
+  syntax:patternbody
+\end{codesample2}
+Un patrón es identificado por una cadena de texto corta que indica qué
+tipo de patrón es, seguido por un dos puntos, seguido por el patrón en
+sí.
+
+Mercurial soporta dos tipos de sintaxis para patrones. La que se usa
+con más frecuencia  se denomina \texttt{glob}\ndt{Grupo, colección,
+aglomeración.}; es el mismo tipo de asociación de patrones usado por
+el intérprete de Unix, y también debería ser familiar para los
+usuarios de la línea de comandos de Windows.
+
+Cuando Mercurial hace asociación automática de patrones en Windows,
+usa la sintaxis \texttt{glob}.  Por esto, usted puede omitir el
+prefijo ``\texttt{glob:}'' en Windows, pero también es seguro usarlo.
+
+La sintaxis \texttt{re}\ndt{Expresiones regulares.} es más poderosa;
+le permite especificar patrones usando expresiones regulares, también
+conocidas como regexps.
+
+A propósito, en los ejemplos siguientes, por favor note que yo tengo
+el cuidado de rodear todos mis patrones con comillas sencillas, para
+que no sean expandidos por el intérprete antes de que Mercurial pueda
+verlos.
+
+\subsection{Patrones \texttt{glob} estilo intérprete}
+
+Este es un vistazo general de los tipos de patrones que usted puede
+usar cuando está usando asociación con patrone glob.
+
+La secuencia ``\texttt{*}'' se asocia con cualquier cadena, dentro de
+un único directorio.
+\interaction{filenames.glob.star}
+
+La secuencia ``\texttt{**}'' se asocia con cualquier cadena, y cruza los
+% TODO token
+límites de los directorios. No es una elemento estándar de los tokens
+de glob de Unix, pero es aceptado por varios intérpretes Unix
+populares, y es muy útil.
+\interaction{filenames.glob.starstar}
+
+La secuencia ``\texttt{?}'' se asocia con cualquier caracter sencillo.
+\interaction{filenames.glob.question}
+
+El caracter ``\texttt{[}'' marca el inicio de una \emph{clase de
+caracteres}.  Ella se asocia con cualquier caracter sencillo dentro de
+la clase. La clase se finaliza con un caracter ``\texttt{]}''. Una
+clase puede contener múltiples \emph{rango}s de la forma
+``\texttt{a-f}'', que en este caso es una abreviación para
+``\texttt{abcdef}''.
+\interaction{filenames.glob.range}
+Si el primer caracter en aparecer después de ``\texttt{[}'' en la
+clase de caracteres es un ``\texttt{!}'', se \emph{niega} la clase,
+haciendo que se asocie con cualquier caracter sencillo que no se
+encuentre en la clase.
+
+Un ``\texttt{\{}'' marca el inicio de un grupo de subpatrones, en
+donde todo el grupo es asociado si cualquier subpatrón en el grupo
+puede ser asociado. El caracter ``\texttt{,}'' separa los subpatrones,
+y el ``\texttt{\}}'' finaliza el grupo.
+\interaction{filenames.glob.group}
+
+\subsubsection{Cuidado!}
+
+No olvide que si usted desea asocia un patrón con cualquier
+directorio, no debería usar el elemento para asociar con cualquier
+cadena ``\texttt{*}'', ya que éste sólo generará asociaciones dentro
+de un solo directorio. En vez de eso, use el caracter para asociar con
+cualquier cadena ``\texttt{**}''. Este pequeño ejemplo ilustra la
+diferencia entre los dos.
+\interaction{filenames.glob.star-starstar}
+
+\subsection{Asociación con patrones de expresiones regulares \texttt{re}}
+
+Mercurial acepta la misma sintaxis para expresiones regulares del
+lenguaje de programación Python (internamente se usa el motor de
+expresiones regulares de Python). Esta sintaxis está basada en la
+misma del lenguaje Perl, que es el dialecto más popular en uso
+(por ejemplo, también se usa en Java).
+
+No discutiré el dialecto de expresiones regulares de Mercurial en
+detalle aquí, ya que las mismas no son usadas frecuentemente. Las
+expresiones regulares al estilo Perl se encuentran documentadas
+exhaustivamente en una multitud de sitios web, y en muchos libros.
+En vez de eso, me enfocaré en unas cuantas cosas que usted debería
+conocer si tiene la necesidad de usar expresiones regulares en
+Mercurial.
+
+Una expresión regular es comparada contra un nombre de fichero
+completo, relativo a la raíz del repositorio. En otras palabras, aún
+si usted se encuentra en un subdirectorio \dirname{foo}, si desea
+asociar ficheros en este directorio, su patrón debe empezar con
+``\texttt{foo/}''.
+
+Un detalle a tener en cuenta es que, si le son familiares las
+expresiones regulares al estilo Perl, las de Mercurial están
+\emph{enraízadas}. Esto es, que la asociación de una expresión se hace
+desde el inicio de la cadena; no se buscan coincidencias dentro de la
+cadena. Para buscar coincidencias en cualquier sitio dentro de una
+cadena, empiece su patrón con un ``\texttt{.*}''.
+
+\section{Filtrado de ficheros}
+
+Mercurial no sólo le provee una variedad de formas para especificar
+ficheros; le permite limitar aún más dichos ficheros mediante el uso
+de \emph{filtros}. Los comandos que operan con nombres de fichero
+aceptan dos opciones de filtrado.
+\begin{itemize}
+\item \hggopt{-I}, o \hggopt{--include}, le permite especificar un
+    patrón con el que deben coincidir los ficheros para ser
+    procesados.
+\item \hggopt{-X}, o \hggopt{--exclude}, le brinda una manera de 
+  \emph{evitar} procesar ficheros, si coinciden con este patrón.
+\end{itemize}
+Usted puede pasar múltiples veces las opciones \hggopt{-I} y
+\hggopt{-X} en la línea de comandos, e intercalarlos como desee.
+Por defecto, Mercurial interpreta los patrones que usted pase usando
+la sintaxis glob (pero usted puede usar expresiones regulares si lo
+necesita).
+
+El filtro \hggopt{-I} puede verse como un ``procese todos los ficheros
+que coincidan con este filtro''.
+\interaction{filenames.filter.include}
+El filtro \hggopt{-X} puede verse como ``procese únicamente los
+ficheros que no coincidan con este patrón''.
+\interaction{filenames.filter.exclude}
+
+\section{Ignorar ficheros y directorios no deseados}
+
+XXX.
+
+\section{Sensibilidad a mayúsculas}
+\label{sec:names:case}
+
+Si usted está trabajando en un ambiente de desarrollo mixto que
+contiene tanto sistemas Linux (u otro Unix) y sistemas Mac o Windows,
+debería tener en mente el hecho de que ellos tratan 
+%TODO FIXME seguir desde aqui, no tengo idea de como traducir case
+%sensitivity
+case (``N'' versus ``n'') of file names in incompatible ways.  This is
+not very likely to affect you, and it's easy to deal with if it does,
+but it could surprise you if you don't know about it.
+
+Operating systems and filesystems differ in the way they handle the
+\emph{case} of characters in file and directory names.  There are
+three common ways to handle case in names.
+\begin{itemize}
+\item Completely case insensitive.  Uppercase and lowercase versions
+  of a letter are treated as identical, both when creating a file and
+  during subsequent accesses.  This is common on older DOS-based
+  systems.
+\item Case preserving, but insensitive.  When a file or directory is
+  created, the case of its name is stored, and can be retrieved and
+  displayed by the operating system.  When an existing file is being
+  looked up, its case is ignored.  This is the standard arrangement on
+  Windows and MacOS.  The names \filename{foo} and \filename{FoO}
+  identify the same file.  This treatment of uppercase and lowercase
+  letters as interchangeable is also referred to as \emph{case
+    folding}.
+\item Case sensitive.  The case of a name is significant at all times.
+  The names \filename{foo} and {FoO} identify different files.  This
+  is the way Linux and Unix systems normally work.
+\end{itemize}
+
+On Unix-like systems, it is possible to have any or all of the above
+ways of handling case in action at once.  For example, if you use a
+USB thumb drive formatted with a FAT32 filesystem on a Linux system,
+Linux will handle names on that filesystem in a case preserving, but
+insensitive, way.
+
+\subsection{Almacenamiento portable y seguro de repositorios}
+
+El mecanismo de almacenamiento de los repositorios en Mercurial es
+\emph{robusto frente a sensibilidad/insensibilidad a mayúsculas}. Los nombres de
+fichero son traducidos para que puedan ser almacenados de manera
+segura tanto en sistemas sensibles como insensibles a mayúsculas. Esto
+significa que usted puede usar herramientas normales de copia de
+ficheros para transferir un repositorio Mercurial a, por ejemplo, una
+memoria USB, y trasladar de manera segura la memoria y el repositorio
+de ida y vuelta entre un Mac, un PC ejecutando Windows, y un sistema
+Linux
+
+\subsection{Detección de conflictos de mayúsculas/minúsculas}
+
+Al operar en el directorio de trabajo, Mercurial respeta la política
+de nombrado del sistema de ficheros en que se encuentre el directorio
+de trabajo. Si el sistema de ficheros conserva las diferencias entre
+mayúsculas, pero no es sensible a ellas, Mercurial tratará los nombres
+que sólo difieren en mayúsculas como uno solo y el mismo.
+
+Un aspecto importante de este enfoque es que es posible consignar un
+conjunto de cambios en un sistema de ficheros sensible a mayúsculas
+(típicamente Linux o Unix) que terminará causando problemas para
+usuarios en sistemas insensibles a mayúsculas (usualmente en Windows o
+MacOS). Si un usuario de Linux consigna cambios a dos ficheros, uno de
+ellos llamado \filename{myfile.c} y el otro llamado \filename{MyFile.C},
+ambos serán almacenados correctamente en el repositorio. Y serán
+representados correctamente como ficheros separados, en los
+directorios de trabajo de otros usuarios de Linux.
+
+Si un usuario de Windows o Mac jalan este cambio, no tendrán problemas
+inicialmente, porque el mecanismo de almacenamiento de Mercurial es
+seguro frente a sensibilidad/insensibilidad a mayúsculas. Sin embargo,
+una vez que ellos traten de actualizar (\hgcmd{update}) el directorio
+de trabajo con ese conjunto de cambios, o hagan fusión (\hgcmd{merge})
+con ese conjunto de cambios, Mercurial verá el conflicto entre los dos
+nombres de fichero que el sistema de ficheros trataría como el mismo,
+e impedirá que ocurra la actualización o fusión.
+
+\subsection{Arreglar un conflicto de mayúsculas/minúsculas}
+
+Si usted está usando Windows o Mac en un entorno mixto donde algunos
+de sus colaboradores están usando Linux o Unix, y Mercurial reporta un
+conflicto de mayúsculas/minúsculas cuando usted trata de actualizar
+(\hgcmd{update}) o fusionar (\hgcmd{merge}), el procedimiento para
+arreglar el problema es simple.
+
+Sólo busque un sistema Linux o Unix cercano, clone el repositorio
+problema allí, y use el comando \hgcmd{rename} de Mercurial para
+cambiar los nombres de cualquiera de los ficheros o directorios
+problemáticos para que no causen más conflictos. Consigne este cambio,
+y jálelo (\hgcmd{pull}) o empújelo (\hgcmd{push}) a su sistema Windows
+o MacOS, y actualícelo (\hgcmd{update}) a la revisión con los nombres
+que ya no generan conflictos.
+
+El conjunto de cambios con los nombres con conflictos de
+mayúsculas/minúsculas permanecerá en el historial de su proyecto, y
+usted no podrá actualizar (\hgcmd{update}) su directorio de trabajo a
+dicho conjunto de cambios en un sistema Windows o MacOS, pero puede
+continuar el desarrollo sin impedimentos.
+
+\begin{note}
+  Antes de la versión~0.9.3, Mercurial no usaba un mecanismos seguro
+  frente a sensibilidad/insensibilidad a mayúsculas o minúsculas, y no
+  detectaba los conflictos con nombres de ficheros. Si usted está
+  usando una versión más antigua de Mercurial en Windows o MacOS, le
+  recomiendo enérgicamente que se actualice.
+\end{note}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/fixhtml.py	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1 @@
+../en/fixhtml.py
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/fixsvg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1 @@
+../en/fixsvg
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/hgbook.css	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1 @@
+../en/hgbook.css
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/hgext.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,441 @@
+\chapter{Añadir funcionalidad con extensiones}
+\label{chap:hgext}
+
+A pesar de que el corazón de Mercurial es muy completo desde el punto
+de vista de funcionalidad, carece de características rimbombantes
+deliberadamente.  Esta aproximación de preservar la simplicidad
+mantiene el programa sencillo tanto para mantenedores como para
+usuarios.
+
+Si embargo Mercurial no le cierra las posibilidades a un conjunto
+inflexible de órdenes: usted puede añadir características como
+\emph{extensiones} (aveces llamadas \emph{añadidos}\ndt{plugins}).  Ya
+hemos discutido algunas de estas extensiones en capítulos anteriores:
+\begin{itemize}
+\item La sección~\ref{sec:tour-merge:fetch} cubre la extensión
+  \hgext{fetch}; que combina jalar cambios y fusionarlos con los
+  cambios locales en una sola orden: \hgxcmd{fetch}{fetch}.
+\item En el capítulo~\ref{chap:hook}, cubrimos muchas extensiones que
+  son útiles en funcionalidades relacionadas con ganchos: Los
+  \hgext{acl} añaden listas de control de acceso; \hgext{bugzilla}
+  añade integración con el sistema de seguimiento de fallos Bugzilla; y
+  \hgext{notify} envía notificaciones por correo de nuevos cambios.
+\item La extensión de administración de parches MQ es tan invaluable
+  que amerita dos capítulos y un apéndice por sí misma.
+  El capítulo~\ref{chap:mq} cubre lo básico; el
+  capítulo~\ref{chap:mq-collab} discute temas avanzados; y el
+  apéndice~\ref{chap:mqref} muestra en detalle cada orden.
+\end{itemize}
+
+En este capítulo cubriremos algunas extensiones adicionales
+disponibles para Mercurial, y daremos un vistazo a la maquinaria que
+necesita conocer en caso de que desee escribir una extensión.
+\begin{itemize}
+\item En la sección~\ref{sec:hgext:inotify}, discutiremos la
+  posibilidad de mejorar el desempeño \emph{en gran medida} con la extensión
+  \hgext{inotify}.
+\end{itemize}
+
+\section{Mejorar el desempeño con la extensión \hgext{inotify}}
+\label{sec:hgext:inotify}
+
+¿Desea lograr que las operaciones más comunmente usadas de Mercurial se
+ejecuten centenas de veces más rápido? ¡A leer!
+
+Mercurial tiene gran desempeño bajo circunstancias normales.  Por
+ejemplo, cuando ejecuta la orden \hgcmd{status}, Mercurial tiene que
+revisar casi todos los ficheros y directorios en su repositorio de
+forma que pueda desplegar el estado de los ficheros.  Muchas otras
+órdenes tienen que hacer tal trabajo tras bambalinas;  por ejemplo la
+orden \hgcmd{diff} usa la maquinaria de estado para evitar hacer
+operaciones de comparación costosas en ficheros que obviamente no han
+cambiado.
+
+Dado que obtener el estado de los ficheros es crucial para obtener
+buen desempeño, los autores de Mercurial han optimizado este código en
+la medida de lo posible.  Sin embargo, no puede obviarse el hecho de
+que cuando ejecuta \hgcmd{status}, Mercurial tendrá que hacer por lo
+menos una costosa llamada al sistema por cada fichero administrado
+para determinar si ha cambiado desde la última vez que se consignó.
+Para un repositorio suficientemente grande, puede tardar bastante
+tiempo.
+
+Para mostrar en números la magnitud de este efect, creé un repositorio
+que contenía 150.000 ficheros administrador.  Tardó diez segundos para
+ejecutar \hgcmd{status}, a pesar de que \emph{ninguno} de los ficheros
+había sido modificado.
+
+Muchos sistemas operativos modernos contienen una facilidad de
+notificación de ficheros.  Si un programa se registra con un servicio
+apropiado, el sistema operativo le notificará siempre que un fichero
+de interés haya sido creado, modificado o borrado.  En sistemas Linux,
+el componente del núcleo que lo hace se llama \texttt{inotify}.
+
+La extensión \hgext{inotify} habla con el componente \texttt{inotify}
+del núcleo para optimizar las órdenes de \hgcmd{status}.  La extensión
+tiene dos componentes.  Un daemonio está en el fondo recibiendo
+notificaciones del subsistema \texttt{inotify}.  También escucha
+conexiones de una orden regular de Mercurial.  La extensión modifica
+el comportamiento de Mercurial de tal forma que, en lugar de revisar
+el sistema de ficheros, le pregunta al daemonio.  Dado que el daemonio
+tiene información perfecta acerca del estado del repositorio, puede
+responder instantáneamente con el resultado, evitando la necesidad de
+revisar cada directorio y fichero del repositorio.
+
+Retomando los diez segundos que medí al ejecutar la orden
+\hgcmd{status} de Mercurial sobre un repositorio de 150.000
+ficheros. Con la extensión \hgext{inotify} habilitada, el tiempo se
+disipó a 0.1~seconds, un factor \emph{cien veces} más rápido.
+
+Antes de continuar, tenga en cuenta algunos detalles:
+\begin{itemize}
+\item La extensión \hgext{inotify} es específica de Linux.  Porque se
+  enlaza directamente con el subsistema \texttt{inotify} del núcleo
+  Linux, no funciona en otros sistemas operativos.
+\item Debería funcionar en cualquier distribución Linux a partir de
+  comienzos del 2005.  Las distribuciones más antiguas deben tener un
+  kernel sin \texttt{inotify}, o una versión de \texttt{glibc} que no
+  tiene necesariamente el soporte para la interfaz.
+\item No todos los sistemas de ficheros pueden usarse con la extensión
+  \hgext{inotify}.  Los sistemas de ficheros tales como NFS no lo
+  soportan, por ejemplo, si está corriendo Mercurial en vaios
+  sistemas, montados todos sobre el mismo sistema de ficheros en red.
+  El sistema \texttt{inotify} del kernel no tiene forma de saber
+  acerca de los cambios hechos en otro sistema.  La mayoría de
+  sistemas de ficheros locales (p.e.~ext3, XFS, ReiserFS) deberían
+  funcionar bien.
+\end{itemize}
+
+Hacia mayo de 2007 la extensión \hgext{inotify} no venía de forma
+predeterminada en Mercurial\ndt{Desde el 2008 para kernels 2.6 viene
+  en Mercurial, pero no está activada de forma predeterminada}, y es
+un poco más compleja de activar que otras extensiones.  Pero la mejora
+en el desempeño bien vale la pena!
+
+La extensión venía en dos partes: un conjunto de parches al código
+fuente de Mercurial, y una librería de interfaces de Python hacia el
+subsistema \texttt{inotify}.
+\begin{note}
+  Hay \emph{dos} librerías de enlace de Python hacia \texttt{inotify}.
+  Una de ellas se llama \texttt{pyinotify}, y en algunas
+  distribuciones de Linux se encuentra como \texttt{python-inotify}.
+  Esta es la que \emph{no} necesita, puesto que tiene muchos fallos,
+  y es ineficiente para ser práctica.
+\end{note}
+Para comenzar, es mejor tener una copia de Mercurial funcional
+instalada:
+\begin{note}
+  Si sigue las instrucciones a continuación, estará
+  \emph{reemplazando} y sobreescribiendo cualquier instalación previa
+  de Mercurial que pudiera tener, con el código de Mercurial ``más
+  reciente y peligrosa''.  No diga que no se le advirtio!
+\end{note}
+\begin{enumerate}
+\item Clone el repositorio de interfaz entre Python e
+  \texttt{inotify}. Ármelo e instálelo:
+  \begin{codesample4}
+    hg clone http://hg.kublai.com/python/inotify
+    cd inotify
+    python setup.py build --force
+    sudo python setup.py install --skip-build
+  \end{codesample4}
+\item Clone el repositorio \dirname{crew} de Mercurial.  Clone el
+  repositorio de parches de \hgext{inotify} de forma tal que las colas
+  de Mercurial puedan aplicar los parches sobre el repositorio \dirname{crew}.
+  \begin{codesample4}
+    hg clone http://hg.intevation.org/mercurial/crew
+    hg clone crew inotify
+    hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches
+  \end{codesample4}
+\item Asegúrese de instalar la extensión Colas de Mercurial
+  \hgext{mq} y que estén habilitadas.  Si nunca ha usado MQ, lea la
+  sección~\ref{sec:mq:start} para poder comenzar rápidamente.
+\item Vaya al repositorio de \dirname{inotify} y aplique todos los
+  parches de \hgext{inotify} con la opción \hgxopt{mq}{qpush}{-a} de
+  la orden \hgxcmd{mq}{qpush}.
+  \begin{codesample4}
+    cd inotify
+    hg qpush -a
+  \end{codesample4}
+  Si obtiene un mensaje de error de \hgxcmd{mq}{qpush}, no debería
+  continuar.  Mejor pida ayuda.
+\item Arme e instale la versión parchada de Mercurial.
+  \begin{codesample4}
+    python setup.py build --force
+    sudo python setup.py install --skip-build
+  \end{codesample4}
+\end{enumerate}
+Una vez que haya armado una versión funcional parchada de Mercurial,
+todo lo que necesita es habilitar la extensión \hgext{inotify}
+colocando una entrada en su \hgrc.
+\begin{codesample2}
+  [extensions]
+  inotify =
+\end{codesample2}
+Cuando la extensión \hgext{inotify} esté habilitada, Mercurial
+iniciará transparente y automáticamente el daemonio de estado la
+primera vez que ejecute un comando que requiera estado del
+repositorio.  Ejecuta un daemonio de estado por repositorio.
+
+El daemonio de estado se inicia silenciosamente y se ejecuta en el
+fondo. Si mira a la lista de procesos en ejecución después de
+habilitar la extensión \hgext{inotify} y ejecuta unos pocos comandos
+en diferentes repositorios, verá que hay algunos procesos de
+\texttt{hg} por ahí, esperando actualizaciones del kernel y
+solicitudes de Mercurial.
+
+La primera vez que ejecuta un comando de Mercurial en un repositorio
+cuando tiene la extensión \hgext{inotify} habilitada, correrá casi con
+el mismo desempeño que una orden usual de Mercurial.  Esto es debido a
+que el estado del daemonio necesita aplicar una búsqueda normal sobre
+el estado para poder tener una línea de partida frente a la cual
+aplicar posteriormente actualizaciones del núcleo.  De todas formas,
+\emph{todo} comando posterior que haga cualquier clase de revisión del
+estado debería ser notablemente más rápido en repositorios con incluso
+un tamaño modesto.  Aún mejor, a medida que su repositorio sea más
+grande, mejor desempeño verá.  El daemonio \hgext{inotify} hace
+operaciones de estado de forma casi instantánea en repositorios de
+todos los tamaños!
+
+Si lo desea, puede iniciar manualmente un daemonio de estado con la orden
+\hgxcmd{inotify}{inserve}.  Esto le da un control un poco más fino
+acerca de cómo debería ejecutarse el daemonio.  Esta orden solamente
+estará disponible cuando haya habilitado la extensión \hgext{inotify}.
+
+Cuando esté usando la extensión \hgext{inotify},
+\emph{no debería ver diferencia} en el comportamiento de Mercurial,
+con la única excepción de que los comandos relacionados con el estado
+deberían ejectuarse mucho más rápido que como solían hacerlo.  Debería
+esperar específicamente que las órdenes no deberían ofrecer salidas
+distintas; ni ofrecer resultados diferentes.  Si alguna de estas
+situaciones ocurre, por favor reporte el fallo.
+
+\section{Soporte flexible de diff con la extensión \hgext{extdiff}}
+\label{sec:hgext:extdiff}
+
+La orden predeterminada \hgcmd{diff} de Mercurial despliega diffs en
+texto plano unificadas.
+\interaction{extdiff.diff}
+Si dese emplear una herramienta externa para desplegar las
+modificaciones, querrá usar la extensión \hgext{extdiff}.  Esta le
+permitirá usar por ejemplo una herramienta gráfica de diff.
+
+La extensión \hgext{extdiff} viene con Mercurial, y es fácil
+configurar.  En la sección \rcsection{extensions} de su \hgrc,
+basta con añadir una entrada de una línea para habilitar la extensión.
+\begin{codesample2}
+  [extensions]
+  extdiff =
+\end{codesample2}
+Esto introduce una orden llamada \hgxcmd{extdiff}{extdiff}, que de
+forma predeterminada usa su orden del sistema \command{diff} para
+generar un diff unificado de la misma forma que lo hace el comando
+predeterminado \hgcmd{diff}.
+\interaction{extdiff.extdiff}
+El resultado no será exactamente el mismo que con la orden interna
+\hgcmd{diff}, puesto que la salida de \command{diff} varía de un
+sistema a otro, incluso pasando las mismas opciones.
+
+Como lo indican las líneas``\texttt{making snapshot}'', la orden
+\hgxcmd{extdiff}{extdiff} funciona creando dos instantáneas de su
+árbol de fuentes.  La primera instantánea es la revisión fuente; la
+segunda es la revisión objetivo del directorio de trabajo.  La orden
+\hgxcmd{extdiff}{extdiff} genera estas instantáneas en un directorio
+temporal, pasa el nombre de cada directorio a un visor de diffs
+temporal y borra los directorios temporales.  Por cuestiones de
+eficiencia solamente genera instantáneas de los directorios y ficheros
+que han cambiado entre dos revisiones.
+
+Los nombres de los directorios de instantáneas tienen los mismos
+nombres base de su repositorio.  Si su repositorio tiene por ruta
+\dirname{/quux/bar/foo}, \dirname{foo} será el nombre de cada
+instantánea de directorio.  Cada instantánea de directorio tiene sus
+identificadores de conjuntos de cambios al final del nombre en caso de
+que sea apropiado.  Si una instantánea viene de la revisión
+\texttt{a631aca1083f}, el directorio se llamará
+\dirname{foo.a631aca1083f}.  Una instantánea del directorio de trabajo
+no tendrá el identificador del conjunto de cambios, y por lo tanto
+será solamente \dirname{foo} en este ejemplo.  Para ver cómo luce en
+la práctica, veamos de nuevo el ejemplo \hgxcmd{extdiff}{extdiff}
+antes mencionado.  Tenga en cuenta que los diffs tienen los nombres de
+las instantáneas de directorio dentro de su encabezado.
+
+La orden \hgxcmd{extdiff}{extdiff} acepta dos opciones importantes.
+La opción \hgxopt{extdiff}{extdiff}{-p} le permite elegir un programa
+para ver las diferencias, en lugar de \command{diff}.  Con la opción
+\hgxopt{extdiff}{extdiff}{-o} puede cambiar las opciones que
+\hgxcmd{extdiff}{extdiff} pasa a tal programa (de forma predeterminada
+las opciones son``\texttt{-Npru}'', que tienen sentido únicamente si
+está usando \command{diff}).  En otros aspectos, la orden
+\hgxcmd{extdiff}{extdiff} actúa de forma similar a como lo hace la
+orden \hgcmd{diff} de Mercurial: usted usa los mismos nombres de
+opciones, sintaxis y argumentos para especificar las revisiones y los
+ficheros que quiere, y así sucesivamente.
+
+Por ejemplo, para ejecutar la orden usual del sistema \command{diff},
+para lograr que se generen diferencias de contexto (con la opción
+\cmdopt{diff}{-c}) en lugar de diferencias unificadas, y cinco líneas
+de contexto en lugar de las tres predeterminadas (pasando \texttt{5}
+como argumento a la opción \cmdopt{diff}{-C}).
+\interaction{extdiff.extdiff-ctx}
+
+Es sencillo lanzar unas herramienta usual de diferencias.  Para lanzar
+el visor \command{kdiff3}:
+\begin{codesample2}
+  hg extdiff -p kdiff3 -o ''
+\end{codesample2}
+
+Si su orden para visualizar diferencias no puede tratar con
+directorios, puede usar un poco de scripting para lograrlo.  Un
+ejemplo de un script con la extensión \hgext{mq} junto con la orden
+\command{interdiff} está en la sección~\ref{mq-collab:tips:interdiff}.
+
+\subsection{Definición de alias de comandos}
+
+Acordarse de todas las opciones de las órdenes
+\hgxcmd{extdiff}{extdiff} y el visor de diferencias de su preferencia
+puede ser dispendioso, y por lo tanto la extensión \hgext{extdiff} le
+permite definir \emph{nuevas} órdenes que invocarán su visor de
+diferencias con las opciones exactas.
+
+Basta con editar su fichero \hgrc, y añadir una sección llamada
+\rcsection{extdiff}.  Dentro de esta sección puede definir varias
+órdenes. Mostraremos como añadir la orden \texttt{kdiff3}.  Después de
+definido, puede teclear ``\texttt{hg kdiff3}'' y la extensión a
+\hgext{extdiff} ejecutará la orden \command{kdiff3}.
+\begin{codesample2}
+  [extdiff]
+  cmd.kdiff3 =
+\end{codesample2}
+Si deja vacía la porción derecha de la definición, como en el ejemplo,
+la extensión \hgext{extdiff} usa el nombre de la orden se definirá
+como el nombre del programa externo a ejecutar.  Pero tales nombres no
+tienen por qué ser iguales.  Definimos ahora la orden llamada
+ ``\texttt{hg wibble}'', que ejecuta \command{kdiff3}.
+\begin{codesample2}
+  [extdiff]
+  cmd.wibble = kdiff3
+\end{codesample2}
+
+También puede especificar las opciones predeterminadas con las cuales
+desea invocar el visor de diferencias.  Se usa el prefijo ``\texttt{opts.}'',
+seguido por el nombre de la orden a la cual se aplican las opciones.
+En este ejemplos se define la orden ``\texttt{hg vimdiff}'' que
+ejecuta la extensión \texttt{DirDiff} del editor \command{vim}.
+\begin{codesample2}
+  [extdiff]  
+  cmd.vimdiff = vim
+  opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'
+\end{codesample2}
+
+\section{Uso de la extensión \hgext{transplant} para seleccionar}
+\label{sec:hgext:transplant}
+
+Need to have a long chat with Brendan about this.
+
+\section{Enviar cambios vía correo electrónico con la extensión \hgext{patchbomb}}
+\label{sec:hgext:patchbomb}
+
+Varios proyectos tienen la cultura de ``revisión de cambios'', en la
+cual la gente envía sus modificaciones a una lista de correo para que
+otros las lean y comenten antes de consignar la versión final a un
+repositorio compartido.  Algunos proyectos tienen personas que actúan
+como cancerberos; ellos aplican los cambios de otras personas a un
+repositorio para aquellos que no tienen acceso.
+
+Mercurial facilita enviar cambios por correo para revisión o
+aplicación gracias a su extensión \hgext{patchbomb}.  La extensión es
+tan popular porque los cambios se formatean como parches y es usual
+que se envía un conjunto de cambios por cada correo.  Enviar una gran
+cantidad de cambios por correos se llama por tanto ``bombardear'' el
+buzón de entrada del destinatario, de ahí su nombre ``bombardeo de
+parches''.
+
+Como es usual, la configuración básica de la extensión
+\hgext{patchbomb} consta de una o dos líneas en su \hgrc.
+\begin{codesample2}
+  [extensions]
+  patchbomb =
+\end{codesample2}
+Cuando haya habilitado la extensión, dispondrá de una nueva orden,
+llamada \hgxcmd{patchbomb}{email}.
+
+La forma mejor y más segura para invocar la orden
+\hgxcmd{patchbomb}{email} es ejecutarla \emph{siempre} con la opción
+\hgxopt{patchbomb}{email}{-n}; que le mostrará lo que la orden
+\emph{enviaría}, sin enviar nada.  Una vez que haya dado un vistazo a
+los cambios y verificado que está enviando los correctos, puede volver
+a ejecutar la misma orden, sin la opción \hgxopt{patchbomb}{email}{-n}.
+
+La orden \hgxcmd{patchbomb}{email} acepta la misma clase de sintaxis
+de revisiones como cualquier otra orden de Mercurial.  Por ejemplo,
+enviará todas las revisiones entre la 7 y la \texttt{punta}, inclusive.
+\begin{codesample2}
+  hg email -n 7:tip
+\end{codesample2}
+También puede especificar un \emph{repositorio} para comparar.  Si
+indica un repositoro sin revisiones, la orden \hgxcmd{patchbomb}{email}
+enviará todas las revisiones en el repositorio local que no están
+presentes en el repositorio remoto.  Si especifica revisiones
+adicionalmente o el nombre de una rama (la última con la opción
+\hgxopt{patchbomb}{email}{-b}), respetará las revisiones enviadas.
+
+Ejecutar la orden \hgxcmd{patchbomb}{email} sin los nombres de
+aquellas personas a las cuales desea enviar el correo es completamente
+seguro: si lo hace, solicitará tales valores de forma interactiva.
+(Si está usando Linux o un sistema tipo Unix, tendrá capacidades
+estilo--\texttt{readline} aumentadas cuando ingrese tales encabezados,
+lo cual es sumamente útil.)
+
+Cuando envíe una sola revisión, la orden \hgxcmd{patchbomb}{email}
+de forma predeterminada usará la primera línea de descripción del
+conjunto de cambios como el tema del único mensaje que se enviará.
+
+Si envía varias revisiones, la orden \hgxcmd{patchbomb}{email} enviará
+normalmente un mensaje por conjunto de cambios. Colocará como
+prefacio un mensaje introductorio en el cual usted debería describir
+el propósito de la serie de cambios que está enviando.
+
+\subsection{Cambiar el comportamiento de las bombas de parches}
+
+Cada proyecto tiene sus propias convenciones para enviar cambios en un
+correo electrónico; la extensión \hgext{patchbomb} intenta acomodarse
+a diferentes variaciones gracias a las opciones de la línea de órdenes:
+\begin{itemize}
+\item Puede escribir un tema para el mensaje introductorio en la línea
+  de órdenes con la opciń \hgxopt{patchbomb}{email}{-s}.  Toma un
+  argumento: el tema del mensaje a usar.
+\item Para cambiar el correo electrónico del campo del cual se
+  origina, use la opción \hgxopt{patchbomb}{email}{-f}.  Toma un
+  argumento, el correo electrónico a usar.
+\item El comportamiento predeterminado es enviar diferencias
+  unificadas (consulte la sección~\ref{sec:mq:patch} si desea una
+  descripción del formato), una por mensaje.  Puede enviar un conjunto
+  binario\ndt{binary bundle} con la opción \hgxopt{patchbomb}{email}{-b}.
+\item Las diferencias unificadas están precedidas por un encabezado de
+  metadatos.  Puede omitirlo, y enviar diferencias sin adornos con la
+  opción \hgxopt{patchbomb}{email}{--plain}.
+\item Las diferencias usualmente se envían ``en línea'', como parte
+  del cuerpo del mensaje con la descripción del parche.  Que facilita a
+  a la mayor cantidad de lectores citar y responder partes de un diff,
+  dado que algunos clientes de correo solamente citarán la primera
+  parte MIME del cuerpo de un mensaje.  Si prefiere enviar la
+  descripción y el diff en partes separadas del cuerpo, use la opción
+  \hgxopt{patchbomb}{email}{-a}.
+\item En lugar de enviar mensajes de correo puede escribirlos a un
+  fichero con formato-\texttt{mbox}- con la opción
+  \hgxopt{patchbomb}{email}{-m}.  La opción recibe un argumento, el
+  nombre del fichero en el cual escribir.
+\item Si desea añadir un resumen con formato-\command{diffstat} en
+  cada parche, y uno como mensaje introductorio, use la opción
+  \hgxopt{patchbomb}{email}{-d}.  La orden \command{diffstat}
+  despliega una tabla que contiene el nombre de cada fichero parchado,
+  el número de líneas afectadas, y un historgrama mostrando cuánto ha
+  sido modificado cada fichero.  Lo cual ofrece a los lectores una
+  mirada cuantitativa de cuan complejo es el parche.
+\end{itemize}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/hook.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1568 @@
+\chapter{Manejo de eventos en repositorios mediante ganchos}
+\label{chap:hook}
+
+Mercurial ofrece un poderoso mecanismo para permitirle a usted
+automatizar la ejecución de acciones en respuesta a eventos que
+ocurran en un repositorio. En algunos casos, usted puede controlar
+incluso la respuesta de Mercurial a dichos eventos.
+
+Mercurial usa el término \emph{gancho} para identificar estas
+acciones. Los ganchos son conocidos como ``disparadores'' en algunos
+sistemas de control de revisiones, pero los dos nombres se refieren al
+mismo concepto.
+
+\section{Vistazo general de ganchos en Mercurial}
+
+A continuación se encuentra una breve lista de los ganchos que
+Mercurial soporta. Volveremos a cada uno de estos ganchos con más
+detalle después, en la sección~\ref{sec:hook:ref}.
+
+\begin{itemize}
+\item[\small\hook{changegroup}] Es ejecutado luego de que un grupo de
+    conjuntos de cambios ha sido traído al repositorio desde algún
+    otro sitio.
+\item[\small\hook{commit}] Es ejecutado después de la creación de
+    un conjunto de cambios en el repositorio local.
+\item[\small\hook{incoming}] Es ejecutado una vez por cada conjunto de
+    cambios traído al repositorio desde otra ubicación. Note la
+    diferencia respecto al gancho \hook{changegroup}, que es ejecutado
+    una vez por cada \emph{grupo} de conjuntos de cambios que se
+    traiga.
+\item[\small\hook{outgoing}] Es ejecutado luego de que un grupo de
+    conjuntos de cambios ha sido transmitido desde el repositorio.
+\item[\small\hook{prechangegroup}] Es ejecutado antes de iniciar la
+    recepción de un grupo de conjuntos de cambios en el repositorio.
+\item[\small\hook{precommit}] De control. Es ejecutado antes de
+    iniciar una consignación.
+\item[\small\hook{preoutgoing}] De control. Es ejecutado antes de
+    iniciar la transmisión de un grupo de conjuntos de cambios desde
+    el repositorio.
+\item[\small\hook{pretag}] De control. Es ejecutado antes de crear una
+    etiqueta.
+\item[\small\hook{pretxnchangegroup}] De control. Es ejecutado después
+    de haber recibido un grupo de conjuntos de cambios en el
+    repositorio local, pero antes de que la transacción se complete y
+    los cambios sean permanentes dentro del repositorio.
+\item[\small\hook{pretxncommit}] De control. Es ejecutado luego de la
+    creación de un conjunto de cambios en el repositorio local, pero
+    antes de que la transacción que hace permanente el cambio sea
+    completada.
+\item[\small\hook{preupdate}] De control. Es ejecutado antes de
+    iniciar una actualización o fusión en el directorio de trabajo.
+\item[\small\hook{tag}] Es ejecutado después de la creación de una
+    etiqueta.
+\item[\small\hook{update}] Es ejecutado después de que termina una
+    actualización o una fusión.
+\end{itemize}
+Cada uno de los ganchos cuya descripción empieza con la frase
+``de control'' tiene la facultad de determinar si una actividad puede
+continuar. Si el gancho se ejecuta con éxito, la actividad puede
+continuar; si falla, o bien la actividad no es permitida, o se
+deshacen los cambios que se puedan haber llevado a cabo, dependiendo
+del gancho involucrado.
+
+\section{Ganchos y seguridad}
+
+\subsection{Los ganchos se ejecutan con sus privilegios de usuario}
+
+Cuando usted ejecuta un comando de Mercurial en un repositorio, y el
+comando causa la ejecución de un gancho, dicho gancho se ejecuta en
+\emph{su} sistema, en \emph{su} cuenta de usuario, con \emph{sus}
+privilegios. Ya que los ganchos son elementos arbitrarios de código
+ejecutable, usted debería tratarlos con un nivel adecuado de
+desconfianza. No instale un gancho a menos en que confíe en quien lo
+creó y en lo que el gancho hace.
+
+En algunos casos, usted puede estar expuesto a ganchos que usted no
+%TODO acá introduzco algo de texto por mi cuenta, por claridad
+instaló. Si usted usa Mercurial en un sistema extraño, tenga en cuenta
+que Mercurial ejecutará los ganchos definidos en el fichero \hgrc.
+
+Si está trabajando con un repositorio propiedad de otro usuario,
+Mercurial podrá ejecutar los ganchos definidos en el repositorio de
+dicho usuario, pero los ejecutará como ``usted''. Por ejemplo, si
+usted jala (\hgcmd{pull}) desde ese repositorio, y el
+\sfilename{.hg/hgrc} define un gancho saliente (\hook{outgoing}),
+dicho gancho se ejecuta bajo su cuenta de usuario, aun cuando usted no
+es el propietario del repositorio.
+
+\begin{note}
+  Esto sólo aplica si usted está jalando desde un repositorio en un
+  sistema de ficheros local o de red. Si está jalando a través de http
+  o ssh, cualquier gancho saliente (\hook{outgoing}) se ejecutará bajo
+  la cuenta que está ejecutando el proceso servidor, en el servidor.
+\end{note}
+
+XXX Para ver qué ganchos han sido definidos en un repositorio, use el
+comando \hgcmdargs{config}{hooks}. Si usted está trabajando en un
+repositorio, pero comunicándose con otro que no le pertenece
+(por ejemplo, usando \hgcmd{pull} o \hgcmd{incoming}), recuerde que
+los ganchos que debe considerar son los del otro repositorio, no los
+del suyo.
+
+\subsection{Los ganchos no se propagan}
+
+En Mercurial, no se hace control de revisiones de los ganchos, y no se
+propagan cuando usted clona, o jala de, un repositorio. El motivo para
+esto es simple: un gancho es código ejecutable arbitrario. Se ejecuta
+bajo su identidad, con su nivel de privilegios, en su máquina.
+
+Sería extremadamente descuidado de parte de cualquier sistema
+distribuido de control de revisiones el implementar control de
+revisiones para ganchos, ya que esto ofrecería maneras fácilmente
+%TODO subvertir
+aprovechables de subvertir las cuentas de los usuarios del sistema de
+control de revisiones.
+
+Ya que Mercurial no propaga los ganchos, si usted está colaborando con
+otras personas en un proyecto común, no debería asumir que ellos están
+usando los mismos ganchos para Mercurial que usted usa, o que los de
+ellos están configurado correctamente. Usted debería documentar los
+ganchos que usted espera que la gente use.
+
+En una intranet corporativa, esto es algo más fácil de manejar, ya que
+usted puede, por ejemplo, proveer una instalación ``estándar'' de
+Mercurial en un sistema de ficheros NFS, y usar un fichero \hgrc\
+global para definir los ganchos que verán todos los usuarios. Sin
+embargo, este enfoque tiene sus límites; vea más abajo.
+
+\subsection{Es posible hacer caso omiso de los ganchos}
+
+Mercurial le permite hacer caso omiso de la deficinión de un gancho,
+a través de la redefinición del mismo. Usted puede deshabilitar el
+gancho fijando su valor como una cadena vacía, o cambiar su
+comportamiento como desee.
+
+Si usted instala un fichero \hgrc\ a nivel de sistema o sitio completo
+que define algunos ganchos, debe entender que sus usuarios pueden
+deshabilitar o hacer caso omiso de los mismos.
+
+\subsection{Asegurarse de que ganchos críticos sean ejecutados}
+
+Algunas veces usted puede querer hacer respetar una política, y no
+permitir que los demás sean capaces de evitarla. Por ejemplo, usted
+puede tener como requerimiento que cada conjunto de cambios debe pasar
+un riguroso conjunto de pruebas. Definir este requerimientos a través
+de un gancho en un fichero \hgrc\ global no servirá con usuarios
+remotos en computadoras portátiles, y por supuesto que los usuarios
+locales pueden evitar esto a voluntad haciendo caso omiso del gancho.
+
+En vez de eso, usted puede definir las políticas para usar Mercurial
+de tal forma que se espere que los usuarios propaguen los cambios a
+través de un servidor ``canónico'' bien conocido que usted ha
+asegurado y configurado apropiadamente.
+
+Una manera de hacer esto es a través de una combinación de ingeniería
+social y tecnología. Cree una cuenta de acceso restringido; los
+usuarios pueden empujar cambios a través de la red a los repositorios
+administrados por esta cuenta, pero no podrán ingresar a dicha cuenta
+para ejecutar órdenes en el intérprete de comandos. En este escenario,
+un usuario puede enviar un conjunto de cambios que contenga la
+porquería que él desee.
+
+Cuando alguien empuja un conjunto de cambios al servidor del que todos
+jalan, el servidor probará el conjunto de cambios antes de aceptarlo
+como permanente, y lo rechazará si no logra pasar el conjunto de
+pruebas. Si la gente sólo jala cambios desde este servidor de filtro,
+servirá para asegurarse de que todos los cambios que la gente jala han
+sido examinados automáticamente
+
+\section{Precauciones con ganchos \texttt{pretxn} en un repositorio de
+acceso compartido}
+
+Si usted desea usar ganchos para llevar a cabo automáticamente algún
+trabajo en un repositorio al que varias personas tienen acceso
+compartido, debe tener cuidado con la forma de hacerlo.
+
+Mercurial sólo bloquea un repositorio cuando está escribiendo al
+mismo, y sólo las partes de Mercurial que escriben al repositorio le
+prestan atención a los bloqueos. Los bloqueos de escritura son
+necesarios para evitar que múltiples escritores simultáneos
+interfieran entre sí, corrompiendo el repositorio.
+
+Ya que Mercurial tiene cuidado con el orden en que lee y escribe
+datos, no necesita adquirir un bloqueo cuando desea leer datos del
+repositorio. Las partes de Mercurial que leen del repositorio nunca le
+prestan atención a los bloqueos. Este esquema de lectura libre de
+bloqueos incremententa en gran medida el desempeño y la concurrencia.
+
+Sin embargo, para tener un gran desempeño es necesario hacer
+sacrificios, uno de los cuales tiene el potencial de causarle
+problemas a menos de que usted esté consciente de él. Describirlo
+requiere algo de detalle respecto a cómo Mercurial añade conjuntos de
+cambios al repositorio y cómo lee esos cambios de vuelta.
+
+Cuando Mercurial \emph{escribe} metadatos, los escribe directamente en
+el fichero de destino. Primero escribe los datos del fichero, luego
+los datos del manifiesto (que contienen punteros a los nuevos datos
+del fichero), luego datos de la bitácora de cambios (que contienen
+punteros a los nuevos datos del manifiesto). Antes de la primera
+escritura a cada fichero, se guarda un registro de dónde estaba el
+final de fichero en su registro de transacciones. Si la transacción
+debe ser deshecha, Mercurial simplemente trunca cada fichero de vuelta
+al tamaño que tenía antes de que empezara la transacción.
+
+Cuando Mercurial \emph{lee} metadatos, lee la bitácora de cambios
+primero, y luego todo lo demás. Como un lector sólo accederá a las
+partes del manifiesto o de los metadatos de fichero que él puede ver
+en la bitácora de cambios, nunca puede ver datos parcialmente
+escritos.
+
+Algunos ganchos de control (\hook{pretxncommit} y
+\hook{pretxnchangegroup}) se ejecutan cuando una transacción está casi
+completa. Todos los metadatos han sido escritos, pero Mercurial aún
+puede deshacer la transacción y hacer que los datos recién escritos
+desaparezcan.
+
+Si alguno de estos ganchos permanece en ejecución por mucho tiempo,
+abre una ventana de tiempo en la que un lector puede ver los metadatos
+de conjuntos de cambios que aún no son permanentes y que no debería
+considerarse que estén ``realmante ahí''. Entre más tiempo tome la
+ejecución del gancho, más tiempo estará abierta esta ventana.
+
+\subsection{Ilustración del problema}
+
+En principio, un buen uso del gancho \hook{pretxnchangegroup} sería
+ensamblar y probar automáticamente todos los cambios entrantes antes
+de que sean aceptados en un repositorio central. Esto le permitiría a
+usted garantizar que nadie pueda empujar cambios que ``rompan el
+ensamblaje''. Pero si un cliente puede jalar cambios mientras están
+siendo probados, la utilidad de esta prueba es nula; alguien confiado
+puede jalar cambios sin probar, lo que potencialmente podría romper su
+proceso de ensamblaje.
+
+La respuesta técnica más segura frente a este retos es montar dicho
+repositorio ``guardián'' como \emph{unidireccional}. Permita que
+reciba cambios desde el exterior, pero no permita que nadie jale
+cambios de él (use el gancho \hook{preoutgoing} para bloquear esto).
+Configure un gancho \hook{changegroup} para que si el ensamblaje o
+prueba tiene éxito, el gancho empuje los nuevos cambios a otro
+repositorio del que la gente \emph{pueda} jalar.
+
+En la práctica, montar un cuello de botella centralizado como éste a
+menudo no es una buena idea, y la visibilidad de las transacciones no
+tiene nada que ver con el problema. A medida que el tamaño de un
+proyecto---y el tiempo que toma ensamblarlo y probarlo---crece, usted
+se acerca rápidamente a un límite con este enfoque ``pruebe antes de
+comprar'', en el que tiene más conjuntos de cambios a probar que
+tiempo para ocuparse de ellos. El resultado inevitable es frustración
+para todos los que estén involucrados.
+
+Una aproximación que permite manejar mejor el crecimiento es hacer que
+la gente ensamble y pruebe antes de empujar, y ejecutar el ensamble y
+pruebas automáticas centralmente \emph{después} de empujar, para
+asegurarse de que todo esté bien. La ventaja de este enfoque es que no
+impone un límite a la rata en la que un repositorio puede aceptar
+cambios.
+
+\section{Tutorial corto de uso de ganchos}
+\label{sec:hook:simple}
+
+Escribir un gancho para Mercurial es fácil. Empecemos con un gancho
+que se ejecute cuando usted termine un \hgcmd{commit}, y simplemente
+muestre el hash del conjunto de cambios que usted acaba de crear. El
+gancho se llamará \hook{commit}.
+
+\begin{figure}[ht]
+  \interaction{hook.simple.init}
+  \caption{Un gancho simple que se ejecuta al hacer la consignación de
+  un conjunto de cambios}
+  \label{ex:hook:init}
+\end{figure}
+
+Todos los ganchos siguen el patrón del ejemplo~\ref{ex:hook:init}.
+Usted puede añadir una entrada a la sección \rcsection{hooks} de su
+fichero \hgrc.  A la izquierda está el nombre del evento respecto al
+cual dispararse; a la derecha está la acción a llevar a cabo. Como
+puede ver, es posible ejecutar cualquier orden de la línea de comandos
+en un gancho. Mercurial le pasa información extra al gancho usando
+variables de entorno (busque \envar{HG\_NODE} en el ejemplo).
+
+\subsection{Llevar a cabo varias acciones por evento}
+
+A menudo, usted querrá definir más de un gancho para un tipo de evento
+particular, como se muestra en el ejemplo~\ref{ex:hook:ext}. 
+Mercurial le permite hacer esto añadiendo una \emph{extensión} al
+final del nombre de un gancho. Usted extiende el nombre del gancho
+%TODO Yuk, no me gusta ese "parada completa"
+poniendo el nombre del gancho, seguido por una parada completa (el
+caracter ``\texttt{.}''), seguido de algo más de texto de su elección.
+Por ejemplo, Mercurial ejecutará tanto \texttt{commit.foo} como
+\texttt{commit.bar} cuando ocurra el evento \texttt{commit}.
+
+\begin{figure}[ht]
+  \interaction{hook.simple.ext}
+  \caption{Definición de un segundo gancho \hook{commit}}
+  \label{ex:hook:ext}
+\end{figure}
+
+Para dar un orden bien definido de ejecución cuando hay múltiples
+ganchos definidos para un evento, Mercurial ordena los ganchos de
+acuerdo a su extensión, y los ejecuta en dicho orden. En el ejemplo de
+arribam \texttt{commit.bar} se ejecutará antes que
+\texttt{commit.foo}, y \texttt{commit} se ejecutará antes de ambos.
+
+Es una buena idea usar una extensión descriptiva cuando usted define
+un gancho. Esto le ayudará a recordar para qué se usa el gancho. Si el
+gancho falla, usted recibirá un mensaje de error que contiene el
+nombre y la extensión del gancho, así que usar una extensión
+descriptiva le dará una pista inmediata de porqué el gancho falló (vea
+un ejemplo en la sección~\ref{sec:hook:perm}).
+
+\subsection{Controlar cuándo puede llevarse a cabo una actividad}
+\label{sec:hook:perm}
+
+En los ejemplos anteriores, usamos el gancho \hook{commit}, que es
+ejecutado después de que se ha completado una consignación. Este es
+uno de los varios ganchos que Mercurial ejecuta luego de que una
+actividad termina. Tales ganchos no tienen forma de influenciar la
+actividad como tal.
+
+Mercurial define un número de eventos que ocurren antes de que una
+actividad empiece; o luego de que empiece, pero antes de que termine.
+Los ganchos que se disparan con estos eventos tienen la capacidad
+adicional de elegir si la actividad puede continuar, o si su ejecución
+es abortada.
+
+El gancho \hook{pretxncommit} se ejecuta justo antes de que una
+consignación se ejecute. En otras palabras, los metadatos que
+representan el conjunto de cambios han sido escritos al disco, pero no
+se ha terminado la transacción. El gancho \hook{pretxncommit} tiene la
+capacidad de decidir si una transacción se completa, o debe
+deshacerse.
+
+Si el gancho \hook{pretxncommit} termina con un código de salida de
+cero, se permite que la transacción se complete; la consignación
+termina; y el gancho \hook{commit} es ejecutado. Si el gancho
+\hook{pretxncommit} termina con un código de salida diferente de cero,
+la transacción es revertida; los metadatos representando el conjunto
+de cambios son borrados; y el gancho \hook{commit} no es ejecutado.
+
+\begin{figure}[ht]
+  \interaction{hook.simple.pretxncommit}
+  \caption{Uso del gancho \hook{pretxncommit} para controlar consignaciones}
+  \label{ex:hook:pretxncommit}
+\end{figure}
+
+El gancho en el ejemplo~\ref{ex:hook:pretxncommit} revisa si el
+mensaje de consignación contiene el ID de algún fallo. Si lo contiene,
+la consignación puede continuar. Si no, la consignación es cancelada.
+
+\section{Escribir sus propios ganchos}
+
+Cuando usted escriba un gancho, puede encontrar útil el ejecutar
+Mercurial o bien pasándole la opción \hggopt{-v}, o con el valor de
+configuración \rcitem{ui}{verbose} fijado en ``true'' (verdadero).
+Cuando lo haga, Mercurial imprimirá un mensaje antes de llamar cada
+gancho.
+
+\subsection{Escoger cómo debe ejecutarse su gancho}
+\label{sec:hook:lang}
+
+Usted puede escribir un gancho que funcione como un programa normal
+---típicamente un guión de línea de comandos---o como una función de
+Python que se ejecuta dentro del proceso Mercurial.
+
+Escribir un gancho como un programa externo tiene la ventaja de que no
+requiere ningún conocimiento del funcionamiento interno de Mercurial.
+Usted puede ejecutar comandos Mercurial normales para obtener la
+informción extra que pueda necesitar. La contraparte de esto es que
+los ganchos externos son más lentos que los ganchos internos
+ejecutados dentro del proceso.
+
+Un gancho Python interno tiene acceso completo a la API de Mercurial,
+y no se ``externaliza'' a otro proceso, así que es inherentemente más
+rápido que un gancho externo. Adicionalmente es más fácil obtener la
+mayoría de la información que un gancho requiere a través de llamadas
+directas a la API de Mercurial que hacerlo ejecutando comandos
+Mercurial.
+
+Si se siente a gusto con Python, o requiere un alto desempeño,
+escribir sus ganchos en Python puede ser una buena elección. Sin
+embargo, cuando usted tiene un gancho bastante directo por escribir y
+no le importa el desempeño (el caso de la mayoría de los ganchos), es
+perfectamente admisible un guión de línea de comandos.
+
+\subsection{Parámetros para ganchos}
+\label{sec:hook:param}
+
+Mercurial llama cada gancho con un conjunto de paŕametros bien
+definidos. En Python, un parámetro se pasa como argumento de palabra
+clave a su función de gancho. Para un programa externo, los parámetros
+son pasados como variables de entornos.
+
+Sin importar si su gancho está escrito en Python o como guión de línea
+de comandos, los nombres y valores de los parámetros específicos de
+los ganchos serán los mismos. Un parámetro booleano será representado
+como un valor booleano en Python, pero como el número 1 (para
+``verdadero'') o 0 (para falso) en una variable de entorno para un
+gancho externo. Si un parámetro se llama \texttt{foo}, el argumento de
+palabra clave para un gancho en Python también se llamará
+\texttt{foo}, mientras que la variable de entorno para un gancho
+externo se llamará \texttt{HG\_FOO}.
+
+\subsection{Valores de retorno de ganchos y control de actividades}
+
+Un gancho que se ejecuta exitosamente debe terminar con un código de
+salida de cero, si es externo, o retornar el valor booleano
+``falso'', si es interno. Un fallo se indica con un código de salida
+diferente de cero desde un gancho externo, o un valor de retorno
+booleano ``verdadero''. Si un gancho interno genera una excepción, se
+considera que el gancho ha fallado.
+
+Para los ganchos que controlan si una actividad puede continuar o no,
+cero/falso quiere decir ``permitir'', mientras que
+% TODO me suena mejor "no permitir" que "denegar"
+no-cero/verdadero/excepción quiere decir ``no permitir''.
+
+\subsection{Escribir un gancho externo}
+
+Cuando usted define un gancho externo en su fichero \hgrc\ y el mismo
+es ejecutado, dicha definición pasa a su intérprete de comandos, que
+hace la interpretación correspondiente. Esto significa que usted puede
+usar elementos normales del intérprete en el cuerpo del gancho.
+
+Un gancho ejecutable siempre es ejecutado con su directorio actual
+fijado al directorio raíz del repositorio.
+
+Cada parámetro para el gancho es pasado como una variable de entorno;
+el nombre está en mayúsculas, y tiene como prefijo la cadena
+``\texttt{HG\_}''.
+
+Con la excepción de los parámetros para los ganchos, Mercurial no
+define o modifica ninguna variable de entorno al ejecutar un gancho.
+Es útil recordar esto al escribir un gancho global que podría ser
+ejecutado por varios usuarios con distintas variables de entorno
+fijadas. En situaciones con múltiples usuarios, usted no debería
+asumir la existencia de ninguna variable de entorno, ni que sus
+valores sean los mismos que tenían cuando usted probó el gancho en su
+ambiente de trabajo.
+
+\subsection{Indicar a Mercurial que use un gancho interno}
+
+La sintaxis para definir un gancho interno en el fichero \hgrc\ es
+ligeramente diferente de la usada para un gancho externo. El valor del
+gancho debe comenzar con el texto ``\texttt{python:}'', y continuar
+con el nombre completamente cualificado de un objeto invocable que se
+usará como el valor del gancho.
+
+El módulo en que vive un gancho es importado automáticamente cuando se
+ejecuta un gancho. Siempre que usted tenga el nombre del módulo y la
+variable de entorno \envar{PYTHONPATH} ajustada adecuadamente, todo
+debería funcionar sin problemas.
+
+El siguiente fragmento de ejemplo de un fichero \hgrc\ ilustra la
+sintaxis y significado de los conceptos que acabamos de describir.
+\begin{codesample2}
+  [hooks]
+  commit.example = python:mymodule.submodule.myhook
+\end{codesample2}
+Cuando Mercurial ejecuta el gancho \texttt{commit.example}, importa 
+\texttt{mymodule.submodule}, busca el objeto invocable llamado
+\texttt{myhook}, y lo invoca (llama).
+
+\subsection{Escribir un gancho interno}
+
+El gancho interno más sencillo no hace nada, pero ilustra la
+estructura básica de la API\ndt{\emph{Application Progamming
+Interface}, Interfaz para Programación de Aplicaciones} para ganchos:
+\begin{codesample2}
+  def myhook(ui, repo, **kwargs):
+      pass
+\end{codesample2}
+El primer argumento para un gancho Python siempre es un objeto
+\pymodclass{mercurial.ui}{ui}.  El segundo es un objeto repositorio;
+de momento, siempre es una instancia de 
+\pymodclass{mercurial.localrepo}{localrepository}.  Después de estos
+dos argumentos están los argumentos de palabra clave. Los argumentos
+que se pasen dependerán del tipo de gancho que se esté llamando, pero
+un gancho siempre puede ignorar los argumentos que no le interesen,
+relegándolos a un diccionario de argumentos por palabras clave, como se
+hizo arriba con \texttt{**kwargs}.
+
+\section{Ejemplos de ganchos}
+
+\subsection{Escribir mensajes de consignación significativos}
+
+Es difícil de imaginar un mensaje de consignación útil y al mismo
+tiempo muy corto. El simple gancho \hook{pretxncommit} de la
+figura~\ref{ex:hook:msglen.go} evitará que usted consigne un conjunto
+de cambios con un mensaje de menos de 10 bytes de longitud.
+
+\begin{figure}[ht]
+  \interaction{hook.msglen.go}
+  \caption{Un gancho que prohíbe mensajes de consignación demasiado
+  cortos}
+  \label{ex:hook:msglen.go}
+\end{figure}
+
+\subsection{Comprobar espacios en blanco finales}
+
+Un uso interesante para ganchos relacionados con consignaciones es
+ayudarle a escribir código más limpio. Un ejemplo simple de
+%TODO dictum => regla
+``código más limpio'' es la regla de que un cambio no debe añadir
+líneas de texto que contengan ``espacios en blanco finales''. El
+espacio en blanco final es una serie de caracteres de espacio y
+tabulación que se encuentran al final de una línea de texto. En la
+mayoría de los casos, el espacio en blanco final es innecesario, ruido
+invisible, pero ocasionalmente es problemático, y la gente en general
+prefiere deshacerse de él.
+
+Usted puede usar cualquiera de los ganchos \hook{precommit} o
+\hook{pretxncommit} para revisar si tiene el problema de los espacios
+en blanco finales. Si usa el gancho \hook{precommit}, el gancho no
+sabrá qué ficheros se están consignando, por lo que se tendrá que
+revisar cada fichero modificado en el repositorio para ver si tiene
+espacios en blanco finales. Si usted sólo quiere consignar un cambio
+al fichero \filename{foo}, y el fichero \filename{bar} contiene
+espacios en blanco finales, hacer la revisión en el gancho
+\hook{precommit} evitará que usted haga la consignación de
+\filename{foo} debido al problem en \filename{bar}.  Este no parece el
+enfoque adeucado.
+
+Si usted escogiera el gancho \hook{pretxncommit}, la revisión no
+ocurriría sino hasta justo antes de que la transacción para la
+consignación se complete. Esto le permitirá comprobar por posibles
+problemas sólo en los ficheros que serán consignados. Sin embargo, si
+usted ingresó el mensaje de consignación de manera interactiva y el
+%TODO roll-back
+gancho falla, la transacción será deshecha; usted tendrá que
+reingresar el mensaje de consignación luego de que corrija el problema
+con los espacios en blanco finales y ejecute \hgcmd{commit} de nuevo.
+
+\begin{figure}[ht]
+  \interaction{hook.ws.simple}
+  \caption{Un gancho simple que revisa si hay espacios en blanco
+  finales}
+  \label{ex:hook:ws.simple}
+\end{figure}
+
+La figura~\ref{ex:hook:ws.simple} presenta un gancho
+\hook{pretxncommit} simple que comprueba la existencia de espacios en
+blanco finales. Este gancho es corto, pero no brinda mucha ayuda.
+Termina con un código de salida de error si un cambio añade una línea
+con espacio en blanco final a cualquier fichero, pero no muestra
+ninguna información que pueda ser útil para identificar el fichero o
+la línea de texto origen del problema. También tiene la agradable
+propiedad de no prestar atención a las líneas que no sufrieron
+modificaciones; sólo las líneas que introducen nuevos espacios en
+blanco finales causan problemas.
+
+\begin{figure}[ht]
+  \interaction{hook.ws.better}
+  \caption{Un mejor gancho para espacios en blanco finales}
+  \label{ex:hook:ws.better}
+\end{figure}
+
+El ejemplo de la figura~\ref{ex:hook:ws.better} es mucho más complejo,
+pero también más útil. El gancho procesa un diff unificado para
+revisar si alguna línea añade espacios en blanco finales, e imprime el
+nombre del fichero y el número de línea de cada ocurrencia. Aún mejor,
+si el cambio añade espacios en blanco finales, este gancho guarda el
+mensaje de consignación e imprime el nombre del fichero en el que el
+mensaje fue guardado, antes de terminar e indicarle a Mercurial que
+deshaga la transacción, para que uste pueda usar
+\hgcmdargs{commit}{\hgopt{commit}{-l}~\emph{nombre\_fichero}} para
+reutilizar el mensaje de consignación guardado anteriormente, una vez
+usted haya corregido el problema.
+
+Como anotación final, note en la figura~\ref{ex:hook:ws.better} el
+%TODO on-site => in-situ ?
+uso de la característica de edición \emph{in-situ} de \command{perl}
+para eliminar los espacios en blanco finales en un fichero. Esto es
+lo suficientemente conciso y poderoso para que lo presente aquí.
+% TODO corregí el backslash, y comprobé por mi cuenta un archivo
+% aparte, y el comando hace lo que debe hacer. Favor copiar del pdf el
+% comando perl y comprobar con un archivo con espacios en blanco
+% finales, y si todo está bien (que debería), borrar esta nota
+\begin{codesample2}
+    perl -pi -e 's,\textbackslash{}s+\$,,' nombre\_fichero
+\end{codesample2}
+
+\section{Ganchos adicionales}
+
+Mercurial se instala con varios ganchos adicionales. Usted puede
+encontrarlos en el directorio \dirname{hgext} del árbol de ficheros
+fuente de Mercurial. Si usted está usando un paquete binario de
+Mercurial, los ganchos estarán ubicados en el directorio
+\dirname{hgext} en donde su instalador de paquetes haya puesto a
+Mercurial.
+
+\subsection{\hgext{acl}---control de acceso a partes de un repositorio}
+
+La extensión \hgext{acl} le permite controlar a qué usuarios remotos
+les está permitido empujar conjuntos de cambios a un servidor en red.
+Usted puede proteger cualquier porción de un repositorio (incluyendo
+el repositorio completo), de tal manera que un usuario remoto
+específico pueda empujar cambios que no afecten la porción protegida.
+
+Esta extensión implementa control de acceso basado en la identidad del
+usuario que empuja los conjuntos de cambios, \emph{no} en la identidad
+de quien hizo la consignación de los mismos. Usar este gancho tiene
+sentido sólo si se tiene un servidor adecuadamente asegurado que
+autentique a los usuarios remotos, y si usted desea segurarse de que
+sólo se le permita a ciertos usuarios empujar cambios a dicho
+servidor.
+
+\subsubsection{Configuración del gancho \hook{acl}}
+
+Para administrar los conjuntos de cambios entrantes, se debe usar el
+gancho \hgext{acl} como un gancho de tipo \hook{pretxnchangegroup}.
+Esto le permite ver qué ficheros son modificados por cada conjunto de
+%TODO rollback => "deshacer el efecto"
+cambios entrante, y deshacer el efecto de un grupo de conjuntos de
+cambios si alguno de ellos modifica algún fichero ``prohibido''.
+Ejemplo:
+\begin{codesample2}
+  [hooks]
+  pretxnchangegroup.acl = python:hgext.acl.hook
+\end{codesample2}
+
+La extensión \hgext{acl} es configurada mediante tres secciones.
+
+La sección \rcsection{acl} sólo tiene una entrada,
+\rcitem{acl}{sources}\ndt{Fuentes.}, que lista las fuentes de los
+conjuntos de cambios entrantes a las que el gancho debe prestar
+atención. Usualmente usted no necesita configurar esta sección.
+\begin{itemize}
+  \item[\rcitem{acl}{serve}] Controlar conjuntos de
+    cambios entrantes que están llegando desde un repositorio a
+    través de http o ssh. Este es el valor por defecto de
+  \rcitem{acl}{sources}, y usualmente es el único valor de
+  configuración que necesitará para este ítem.
+\item[\rcitem{acl}{pull}] Controlar conjuntos de cambios entrantes que
+  lleguen vía un pull (jalado) desde un repositorio local.
+\item[\rcitem{acl}{push}] Controlar conjuntos de cambios entrantes que
+  lleguen vía un push (empuje) desde un repositorio local.
+\item[\rcitem{acl}{bundle}] Controlar conjuntos de cambios entrantes
+    %TODO bundle
+  que lleguen desde otro repositorio a través de un paquete.
+\end{itemize}
+
+La sección \rcsection{acl.allow} controla los usuarios a los que les
+está permitido añadir conjuntos de cambios al repositorio. Si esta
+sección no está presente, se le permite acceso a todos los usuarios
+excepto  a los que se les haya negado explícitamente el acceso. Si
+esta sección no está presente, se niega el acceso a todos los usuarios
+excepto a todos a los que se les haya permitido de manera explícita
+(así que una sección vacía implica que se niega el acceso a todos los
+usuarios).
+
+La sección \rcsection{acl.deny} determina a qué usuarios no se les
+permite añadir conjuntos de cambios al repositorio. Si esta sección no
+está presente o está vacía, no se niega el acceso a ningún usuario.
+
+La sintaxis para los ficheros \rcsection{acl.allow} y
+\rcsection{acl.deny} es idéntica. A la izquierda de cada entrada se
+encuentra un patrón glob que asocia ficheros o directorios, respecto a
+la raíz del repositorio; a la derecha, un nombre usuario.
+
+En el siguiente ejemplo, el usuario \texttt{escritordoc} sólo puede
+empujar cambios al directorio \dirname{docs} del repositorio, mientras
+que \texttt{practicante} puede enviar cambios a cualquier fichero o
+directorio excepto \dirname{fuentes/sensitivo}.
+\begin{codesample2}
+  [acl.allow]
+  docs/** = escritordoc
+
+  [acl.deny]
+  fuentes/sensitivo/** = practicante
+\end{codesample2}
+
+\subsubsection{Pruebas y resolución de problemas}
+
+Si usted desea probar el gancho \hgext{acl}, ejecútelo habilitando la
+opción de salida de depuración habilitada. Ya que usted probablemente
+lo estará ejecutando en un servidor donde no es conveniente (o incluso
+posible) pasar la opción \hggopt{--debug}, no olvide que usted puede
+habilitar la salida de depuración en su \hgrc:
+\begin{codesample2}
+  [ui]
+  debug = true
+\end{codesample2}
+Con esto habilitado, el gancho \hgext{acl} imprimirá suficiente
+información para permitirle saber porqué está permitiendo o denegando
+la operación de empujar a usuarios específicos.
+
+\subsection{\hgext{bugzilla}---integración con Bugzilla}
+
+La extensión \hgext{bugzilla} añade un comentario a un fallo Bugzilla
+siempre que encuentre una referencia al ID de dicho fallo en un
+mensaje de consignación. Usted puede instalar este gancho en un
+servidor compartido, para que cada vez que un usuario remoto empuje
+cambios al servidor, el gancho sea ejecutado.
+
+Se añade un comentario al fallo que se ve así (usted puede configurar
+los contenidos del comentario---vea más abajo):
+%TODO traducir?
+\begin{codesample2}
+  Changeset aad8b264143a, made by Joe User <joe.user@domain.com> in
+  the frobnitz repository, refers to this bug.
+
+  For complete details, see
+  http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a
+
+  Changeset description:
+        Fix bug 10483 by guarding against some NULL pointers
+\end{codesample2}
+El valor de este gancho se encuentra en que automatiza el proceso de
+actualizar un fallo cuando un conjunto de cambios se refiera a él. Si
+usted configura este gancho adecuadamente, hará fácil para la gente
+navegar directamente desde un fallo Bugzilla a un conjunto de cambios
+que se refiere a ese fallo.
+
+Usted puede usar el código de este gancho como un punto de partida
+para otras recetas de integración con Bugzilla aún más exóticas. Acá
+hay algunas posibilidades:
+\begin{itemize}
+\item Requerir que cada conjunto de cambios tenga un ID de fallo en su
+  mensaje de consignación. En este caso, usted querrá configurar el
+  gancho como uno de tipo \hook{pretxncommit}.  Esto le permitirá al
+  gancho rechazar cambios que no contiene IDs de fallos.
+\item Permitir a los conjuntos de cambios entrantes modificar
+  automáticamente el \emph{estado} de un fallo, así como simplemente
+  añadir un comentario. Por ejemplo, el gancho podría reconocer la
+  cadena ``corregido fallo 31337'' como la señal de que debería
+  actualizar el estado del fallo 31337 a ``requiere pruebas''.
+\end{itemize}
+
+\subsubsection{Configuración del gancho \hook{bugzilla}}
+\label{sec:hook:bugzilla:config}
+
+Usted debería configurar este gancho en el \hgrc\ de su servidor como
+un gancho \hook{incoming}\ndt{Entrante.}, por ejemplo como sigue:
+\begin{codesample2}
+  [hooks]
+  incoming.bugzilla = python:hgext.bugzilla.hook
+\end{codesample2}
+
+Debido a la naturaleza especializada de este gancho, y porque Bugzilla
+no fue escrito con este tipo de integración en mente, configurar este
+% TODO involved => complejo ? no intarwebs here :(
+gancho es un proceso algo complejo.
+
+Antes de empezar, usted debe instalar la interfaz de Python para MySQL
+en los sistemas en los que se vaya a ejecutar el gancho. Si no está
+disponible como paquete binario para su sistema, usted puede descargar
+el paquete desde~\cite{web:mysql-python}.
+
+La información para configurar este gancho se ubica en la sección 
+\rcsection{bugzilla} de su \hgrc.
+\begin{itemize}
+\item[\rcitem{bugzilla}{version}] La versión de Bugzilla instalada en
+  el servidor. El esquema de base de datos que Bugzilla usa cambia
+  ocasionalmente, así que este gancho debe saber exactamente qué
+  esquema usar. A la fecha, la única versión soportada es la
+  \texttt{2.16}.
+\item[\rcitem{bugzilla}{host}] El nombre de máquina (\emph{hostname})
+  del servidor MySQL que almacena sus datos Bugzilla. La base de datos
+  debe ser configurada para permitir conexiones desde las máquinas en
+  las que usted ejecute el gancho \hook{bugzilla}.
+\item[\rcitem{bugzilla}{user}] El nombre de usuario que se usará para
+  conectarse al servidor MySQL. La base de datos debe ser configurada
+  para permitir a dicho usuario conectarse desde cualquiera de las
+  máquinas en las que se ejecute el gancho \hook{bugzilla}.  Este
+  usuario debe tener acceso y poder modificar las tablas de Bugzilla.
+  El valor por defecto para este ítem es \texttt{bugs}, que es el
+  nombre estándar del usuario para Bugzilla en una base de datos
+  MySQL.
+\item[\rcitem{bugzilla}{password}] La contraseña MySQL para el usuario
+  configurado anteriormente. Ésta es almacenada como texto plano, así
+  que usted deberá asegurarse de que los usuarios no autorizados no
+  puedan leer el fichero \hgrc\ en donde usted guarda esta
+  información.
+\item[\rcitem{bugzilla}{db}] El nombre de la base de datos Bugzilla en
+  el servidor MySQL. El nombre por defecto para este ítem es
+  \texttt{bugs}, que es el nombre estándar de la base de datos MySQL
+  en donde Bugzilla almacena sus datos.
+\item[\rcitem{bugzilla}{notify}] Si usted desea que Bugzilla envíe un
+    %TODO suBscriptores?
+  correo de notificación a los suscriptores después de que el gancho
+  haya añadido un comentario a un fallo, necesitará que este gancho
+  ejecute un comando siempre que actualice la base de datos. El
+  comando que se ejecute depende de en dónde haya sido instalado
+  Bugzilla, pero típicamente se verá así, si usted ha instalado
+  Bugzilla en \dirname{/var/www/html/bugzilla}:
+  \begin{codesample4}
+    cd /var/www/html/bugzilla && ./processmail %s nobody@nowhere.com
+  \end{codesample4}
+  El programa \texttt{processmail} de Bugzilla espera recibir un ID de
+  fallo (el gancho reemplaza ``\texttt{\%s}'' por el ID del fallo) y
+  una dirección de correo. También espera poder escribir a ciertos
+  ficheros en el directorio en que se ejecuta. Si Bugzilla y éste
+  gancho no están instalados en la misma máquina, usted deberá
+  encontrar una manera de ejecutar \texttt{processmail} en el servidor
+  donde está instalado Bugzilla.
+\end{itemize}
+
+\subsubsection{Asociar nombres de consignadores a nombres de usuario
+Bugzilla}
+
+Por defecto, el gancho \hgext{bugzilla} trata de usar la dirección de
+correo electrónico de la persona que hizo la consignación del conjunto
+de cambios como el nombre de usuario Bugzilla con el cual debe
+actualizar el fallo. Si esto no se ajusta a sus necesidades, es
+posible asociar direcciones de correo a nombres de usuario Bugzilla
+usando una sección \rcsection{usermap}.
+
+Cada ítem en la sección \rcsection{usermap} contiene una dirección de
+correo electrónico a la izquierda, y un nombre de usuario Bugzilla a
+la derecha.
+\begin{codesample2}
+  [usermap]
+  jane.user@example.com = jane
+\end{codesample2}
+Usted puede mantener los datos de \rcsection{usermap} en un fichero
+\hgrc, o decirle al gancho \hgext{bugzilla} que lea la información
+desde un fichero \filename{usermap} externo.  En este caso, usted
+puede almacenar los datos de \filename{usermap} en (por ejemplo) un
+repositorio modificable por los usuarios. Esto hace posible para sus
+usuarios mantener sus propias entradas \rcitem{bugzilla}{usermap}.  El
+fichero \hgrc\ principal se vería así:
+\begin{codesample2}
+  # fichero hgrc normal se refiere a un fichero usermap externo
+  [bugzilla]
+  usermap = /home/hg/repos/userdata/bugzilla-usermap.conf
+\end{codesample2}
+Mientras que el fichero \filename{usermap} al que se hace referencia
+se vería así:
+\begin{codesample2}
+  # bugzilla-usermap.conf - dentro de un repositorio hg
+  [usermap]
+  stephanie@example.com = steph
+\end{codesample2}
+
+\subsubsection{Configurar el texto que se añade a un fallo}
+
+Usted puede configurar el texto que este gancho añade como comentario;
+usted los especifica como una plantilla Mercurial. Varias entradas
+\hgrc\ (aún en la sección \rcsection{bugzilla}) controlan este
+comportamiento.
+\begin{itemize}
+\item[\texttt{strip}] La cantidad de elementos iniciales de ruta a
+  remover de un nombre de ruta del repositorio para construir una ruta
+  parcial para una URL. Por ejemplo, si los repositorios en su
+  servidor se ubican en \dirname{/home/hg/repos}, y usted tiene un
+  repositorio cuya ruta es \dirname{/home/hg/repos/app/tests},
+  entonces fijar \texttt{strip} a \texttt{4} resultará en una ruta
+  parcial de \dirname{app/tests}.  El gancho hará disponible esta ruta
+  parcial cuando expanda una plantilla, como \texttt{webroot}.
+\item[\texttt{template}] El texto de la plantilla a usar. En adición a
+  las variables usuales relacionadas con conjuntos de cambios, esta
+  plantilla puede usar \texttt{hgweb} (el valor del ítem de
+  configuración \texttt{hgweb} de arriba) y \texttt{webroot} (la ruta
+  construida usando \texttt{strip} arriba).
+\end{itemize}
+
+Adicionalmente, usted puede añadir un ítem \rcitem{web}{baseurl} a la
+sección \rcsection{web} de su \hgrc.  El gancho \hgext{bugzilla}
+publicará esto cuando expanda una plantilla, como la cadena base a
+usar cuando se construya una URL que le permita a los usuarios navegar
+desde un comentario de Bugzilla a la vista de un conjunto de cambios.
+Ejemplo:
+\begin{codesample2}
+  [web]
+  baseurl = http://hg.domain.com/
+\end{codesample2}
+
+A continuación se presenta un ejemplo completo de configuración para
+el gancho \hgext{bugzilla}.
+%TODO traducir?
+\begin{codesample2}
+  [bugzilla]
+  host = bugzilla.example.com
+  password = mypassword
+  version = 2.16
+  # server-side repos live in /home/hg/repos, so strip 4 leading
+  # separators
+  strip = 4
+  hgweb = http://hg.example.com/
+  usermap = /home/hg/repos/notify/bugzilla.conf
+  template = Changeset \{node|short\}, made by \{author\} in the \{webroot\}
+    repo, refers to this bug.\\nFor complete details, see 
+    \{hgweb\}\{webroot\}?cmd=changeset;node=\{node|short\}\\nChangeset
+    description:\\n\\t\{desc|tabindent\}
+\end{codesample2}
+
+\subsubsection{Pruebas y resolución de problemas}
+
+Los problemas más comunes que aparecen en la configuración del gancho
+\hgext{bugzilla} suelen estar relacionados con la ejecución del guión
+de Bugzilla \filename{processmail} y la asociación de nombres de
+consignadores a nombres de usuario.
+
+Recuerde que en la sección~\ref{sec:hook:bugzilla:config} arriba el
+usuario que ejecuta el proceso Mercurial en el servidor es también 
+el usuario que ejecutará el guión \filename{processmail}. El guión
+\filename{processmail} algunas veces hace que Bugzilla escriba en
+ficheros en su directorio de configuración, y los ficheros de
+configuración de Bugzilla usualmente son propiedad del usuario bajo el
+cual se ejecuta el servidor web.
+
+Usted puede hacer que \filename{processmail} sea ejecutado con la
+identidad del usuario adecuado usando el comando \command{sudo}. A
+continuación se presenta una entrada de ejemplo para un fichero
+\filename{sudoers}.
+\begin{codesample2}
+  hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s
+\end{codesample2}
+Esto permite que el usuario \texttt{hg\_user} ejecute el programa
+\filename{processmail-wrapper} con la identidad del usuario
+\texttt{httpd\_user}.
+
+Esta indirección a través de un guión envoltorio es necesaria, porque
+\filename{processmail} espera que al ser ejecutado su directorio
+actual sea aquel en el cual se instaló Bugzilla; usted no puede
+especificar ese tipo de condición en un fichero \filename{sudoers}.
+Los contenidos del giuón envoltorio son simples:
+\begin{codesample2}
+  #!/bin/sh
+  cd `dirname $0` && ./processmail "$1" nobody@example.com
+\end{codesample2}
+No parece importar qué dirección de correo se le pase a
+\filename{processmail}.
+
+Si su \rcsection{usermap} no es configurada correctamente, los
+usuarios verán un mensaje de error del gancho \hgext{bugzilla} cuando
+empujen cambios al servidor. El mensaje de error se verá así:
+\begin{codesample2}
+  cannot find bugzilla user id for john.q.public@example.com
+\end{codesample2}
+Lo que esto quiere decir es que la dirección del consignador,
+\texttt{john.q.public@example.com}, no es un nombre de usuario
+Bugzilla válido, ni tiene una entrada en su \rcsection{usermap} que lo
+asocie con un nombre de usuario válido Bugzilla.
+
+\subsection{\hgext{notify}---enviar notificaciones de correo
+electrónico}
+
+%TODO feeds => notificaciones: lo más fácil es mirar en wikipedia
+Aunque el servidor web embebido de Mercurial provee notificaciones de
+cambios en cada repositorio, muchas personas prefieren recibir las
+notificaciones de cambios vía correo electrónico. El gancho
+\hgext{notify}\ndt{Notificación.} le permite a usted enviar
+notificaciones a un conjunto de direcciones de correo cuando lleguen
+conjuntos de cambios en los que los subscriptores estén interesados.
+
+De la misma forma que con el gancho \hgext{bugzilla}, el gancho
+\hgext{notify} está orientado a plantillas, así que usted puede
+personalizar los contenidos del mensaje de notificación que se envía.
+
+Por defecto, el gancho \hgext{notify} incluye un diff de cada conjunto
+%TODO que se envía? revisar, pienso que es ``que se recibe''
+de cambios que se envía; usted puede limitar el tamaño del diff, o
+desactivar completamente esta característica. Es útil para permitir a
+los subscriptores revisar los cambios inmediatamente, en vez de tener
+que hacer clic para visitar una URL.
+
+\subsubsection{Configuración del gancho \hgext{notify}}
+
+Usted puede configurar el gancho \hgext{notify} para enviar un mensaje
+de correo por conjunto de cambios entrante, o uno por grupo entrante
+de conjuntos de cambios (todos los que llegaron en un único empuje o
+jalado).
+\begin{codesample2}
+  [hooks]
+  # enviar un correo por grupo de cambios
+  changegroup.notify = python:hgext.notify.hook
+  # enviar un correo por cambio
+  incoming.notify = python:hgext.notify.hook
+\end{codesample2}
+
+La información para configurar este gancho se ubica en la sección
+\rcsection{notify} de un fichero \hgrc.
+\begin{itemize}
+\item[\rcitem{notify}{test}] Por defecto, este gancho no envía correos
+  en absoluto; en vez de eso, imprime el mensaje que se
+  \emph{enviaría}. Fije este ítem en \texttt{false} para permitir el
+  envío de correos. El motivo por el que el envío de correos está
+  desactivado es que hacen falta varios intentos para configurar esta
+  extensión exactamente como usted desea, y sería maleducado enviar a
+  los subscriptores una cantidad de notificaciones ``rotas'' mientras
+  usted depura su configuración.
+\item[\rcitem{notify}{config}] La ruta a un fichero de configuración
+  que contiene información de subscripción. Esto se mantiene separado
+  del \hgrc\ principal para que usted pueda mantenerlo en un
+  repositorio. La gente puede clonar ese repositorio, actualizar sus
+  subscripciones, y empujar los cambios de vuelta a su servidor.
+\item[\rcitem{notify}{strip}] La cantidad de caracteres iniciales de
+  separación de ruta a remover de la ruta del repositorio, al decidir
+  si un repositorio tiene subscriptores. Por ejemplo, si los
+  repositorios en su servidor están en \dirname{/home/hg/repos}, y
+  \hgext{notify} está trabajando con un repositorio llamado
+  \dirname{/home/hg/repos/shared/test}, fijar \rcitem{notify}{strip} a
+  \texttt{4} hará que \hgext{notify} elimine las partes iniciales de
+  la ruta hasta \dirname{shared/test}, y asociará los subscriptores
+  frente a dicha ruta.
+\item[\rcitem{notify}{template}] El texto de plantilla a usar cuando
+  se envíen mensajes. Especifica los contenidos de la cabecera del
+  mensaje y el cuerpo del mismo.
+\item[\rcitem{notify}{maxdiff}] El número máximo de líneas de datos de
+  diff a añadir al final de un mensaje. Si la longitud de un diff es
+  mayor a eso, se trunca. Por defecto, está fijado en 300. Fije esto a 
+  \texttt{0} para omitir los diffs en los correos de notificación.
+\item[\rcitem{notify}{sources}] Una lista de fuentes de conjuntos de
+  cambios a considerar. Esto le permite a usted indicar a
+  \hgext{notify} para que sólo envíe correos acerca de cambios que
+  usuarios remotos hayan empujado al repositorio vía un servidor, por
+  ejemplo.  Vea la sección~\ref{sec:hook:sources} para las fuentes que
+  usted puede especificar aquí.
+\end{itemize}
+
+Si usted fija el ítem \rcitem{web}{baseurl} en la sección
+\rcsection{web}, usted lo puede usar en una plantilla; estará
+disponible como \texttt{webroot}.
+
+A continuación se presenta un ejemplo completo de configuración para
+el gancho \hgext{notify}.
+\begin{codesample2}
+  [notify]
+  # enviar correo
+  test = false
+  # datos de subscriptores están en el repositorio notify
+  config = /home/hg/repos/notify/notify.conf
+  # repos están en /home/hg/repos on server, así que elimine 4
+  # caracteres"/"
+  strip = 4
+  template = X-Hg-Repo: \{webroot\}
+    Subject: \{webroot\}: \{desc|firstline|strip\}
+    From: \{author\}
+
+    changeset \{node|short\} in \{root\}
+    details: \{baseurl\}\{webroot\}?cmd=changeset;node=\{node|short\}
+    description:
+      \{desc|tabindent|strip\}
+
+  [web]
+  baseurl = http://hg.example.com/
+\end{codesample2}
+
+Esto producirá un mensaje que se verá como el siguiente:
+\begin{codesample2}
+  X-Hg-Repo: tests/slave
+  Subject: tests/slave: Handle error case when slave has no buffers
+  Date: Wed,  2 Aug 2006 15:25:46 -0700 (PDT)
+
+  changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave
+  details: http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5
+  description:
+          Handle error case when slave has no buffers
+  diffs (54 lines):
+
+  diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h
+  --- a/include/tests.h      Wed Aug 02 15:19:52 2006 -0700
+  +++ b/include/tests.h      Wed Aug 02 15:25:26 2006 -0700
+  @@ -212,6 +212,15 @@ static __inline__ void test_headers(void *h)
+  [...snip...]
+\end{codesample2}
+
+\subsubsection{Pruebas y resolución de problemas}
+
+No olvide que por defecto, la extensión \hgext{notify} \emph{no
+enviará ningún correo electrónico} hasta que usted la configure
+explícitamente para hacerlo, fijando el valor de \rcitem{notify}{test}
+a \texttt{false}.  Hasta que usted haga eso, simplemente se imprimirá
+el mensaje que se \emph{enviaría}.
+
+\section{Información para escritores de ganchos}
+\label{sec:hook:ref}
+
+\subsection{Ejecución de ganchos internos}
+
+Un gancho interno es llamado con argumentos de la siguiente forma:
+\begin{codesample2}
+  def myhook(ui, repo, **kwargs):
+      pass
+\end{codesample2}
+El parámetro \texttt{ui} es un objeto \pymodclass{mercurial.ui}{ui}.
+El parámetro \texttt{repo} es un objeto
+\pymodclass{mercurial.localrepo}{localrepository}. Los nombres y
+valores de los parámetros en \texttt{**kwargs} dependen del gancho que
+se invoque, con las siguientes características en común:
+\begin{itemize}
+\item Si hay un parámetro llamado \texttt{node} o
+  \texttt{parent\emph{N}}, contendrá un ID hexadecimal de un conjunto
+  de cambios. La cadena vacía es usada para representar un
+  ``ID de conjunto de cambios nulo'' en vez de una cadena de ceros.
+\item Si hay un parámetro llamado \texttt{url}, contendrá la URL de un
+  repositorio remoto, si puede ser determinada.
+\item Los parámetros booleanos son representados como objetos
+    \texttt{bool} de Python.
+\end{itemize}
+
+Un gancho interno es ejecutado sin cambiar el directorio de trabajo
+del proceso (a diferencia de los ganchos externos, que son ejecutados
+desde la raíz del repositorio). El gancho no debe cambiar el
+directorio de trabajo del proceso, porque esto haría que falle
+cualquier llamada que se haga a la API de Mercurial.
+
+Si un gancho retorna el valor booleano ``false''\ndt{Falso.}, se
+considera que éste tuvo éxito. Si retorna
+``true''\ndt{Verdadero.} o genera una excepción, se considera que
+ha fallado. Una manera útil de pensar en esta convención de llamado es
+``dígame si usted falló''.
+
+Note que los IDs de conjuntos de cambios son pasados a los ganchos de
+Python como cadenas hexadecimales, no como los hashes binarios que la
+API de Mercurial usa normalmente. Para convertir un hash de
+hexadecimal a binario, use la función \pymodfunc{mercurial.node}{bin}.
+
+\subsection{Ejecución de ganchos externos}
+
+Un gancho externo es pasado al intérprete de comandos del usuario bajo
+el cual se ejecuta Mercurial. Las características del intérprete, como
+sustitución de variables y redirección de comandos, están disponibles.
+El gancho es ejecutado desde el directorio raíz del repositorio
+(a diferencia de los ganchos internos, que se ejecutan desde el mismo
+directorio en que Mercurial fue ejecutado).
+
+Los parámetros para el gancho se pasan como variables de entorno. El
+nombre de cada variable de entorno se pasa a mayúsculas y se le añade
+el prefijo ``\texttt{HG\_}''.  Por ejemplo, si el nombre de un
+parámetro es ``\texttt{node}'', el nombre de la variable de entorno
+que almacena el parámetro se llamará ``\texttt{HG\_NODE}''.
+
+Un parámetro booleano se representa con la cadena ``\texttt{1}'' para
+``true'', ``\texttt{0}'' para ``false''.  Si una variable se llama
+\envar{HG\_NODE}, \envar{HG\_PARENT1} o \envar{HG\_PARENT2},  
+contendrá un ID de conjunto de cambios representado como una cadena
+hexadecimal. La cadena vacía es usada para representar un ``ID de
+conjunto de cambios nulo'' en vez de una cadena de ceros. Si una
+variable de entorno se llama \envar{HG\_URL}, contendrá la URL de un
+repositorio remoto, si puede ser determinada.
+
+Si un gancho termina con un código de salida de cero, se considera que
+tuvo éxito. Si termina con un código de salida diferente de cero, se
+considera que falló.
+
+\subsection{Averiguar de dónde vienen los conjuntos de cambios}
+%TODO los trae la cigüeña. De París. Y quedan debajo de una col.
+
+Un gancho que involucra la transferencia de conjuntos de cambios entre
+un repositorio local y otro puede ser capaz de averiguar información
+acerca de ``el otro lado''. Mercurial sabe \emph{cómo} son
+transferidos los conjuntos de cambios, y en muchos casos también desde
+o hacia donde están siendo transferidos.
+
+\subsubsection{Fuentes de conjuntos de cambios}
+\label{sec:hook:sources}
+
+Mercurial le indicará a un gancho cuáles son, o fueron, los medios
+usados para transferir los conjuntos de cambios entre repositorios.
+Esta información es provista por Mercurial en un parámetro Python
+llamado \texttt{source}\ndt{Fuente.}, o una variable de entorno
+llamada \envar{HG\_SOURCE}.
+
+\begin{itemize}
+\item[\texttt{serve}] Los conjuntos de cambios son transferidos desde
+  o hacia un repositorio remoto a través de http o ssh.
+\item[\texttt{pull}] Los conjuntos de cambios son transferidos vía una
+  operación de jalado de un repositorio a otro.
+\item[\texttt{push}] Los conjuntos de cambios son transferidos vía un
+  empuje de un repositorio a otro.
+\item[\texttt{bundle}] Los conjuntos de cambios son transferidos desde
+    %TODO bundle
+  o hacia un paquete.
+\end{itemize}
+
+\subsubsection{A dónde van los cambios---URLs de repositorios remotos}
+\label{sec:hook:url}
+%TODO al cielo? no, ésos son los perros
+
+Cuando es posible, Mercurial le indicará a los ganchos la ubicación de
+``el otro lado'' de una actividad que transfiera datos de conjuntos de
+cambios entre repositorios. Esto es provisto por Mercurial en un
+parámetro Python llamado \texttt{url}, o en una variable de entorno
+llamada \envar{HG\_URL}.
+
+No siempre esta información está disponible. Si un gancho es invocado
+un repositorio que es servido a través de http o ssh, Mercurial no
+puede averiguar dónde está el repositorio remoto, pero puede saber
+desde dónde se conecta el cliente. En esos casos, la URL tendrá una de
+las siguientes formas:
+\begin{itemize}
+\item \texttt{remote:ssh:\emph{ip-address}}---cliente ssh remoto, en
+  la dirección IP dada.
+\item \texttt{remote:http:\emph{ip-address}}---cliente remoto http, en
+  la dirección IP dada. Si el cliente está usando SSL, tendrá la forma
+  \texttt{remote:https:\emph{ip-address}}.
+\item Vacío---no se pudo descubrir información acerca del cliente
+  remoto.
+\end{itemize}
+
+\section{Referencia de ganchos}
+
+\subsection{\hook{changegroup}---luego de añadir conjuntos de cambios
+remotos}
+\label{sec:hook:changegroup}
+
+Este gancho es ejecutado luego de que un grupo de conjuntos de cambios
+preexistentes ha sido añadido al repositorio, por ejemplo vía un
+\hgcmd{pull} o \hgcmd{unbundle}.  Este gancho es ejecutado una vez por
+cada operación que añade uno o más conjuntos de cambios. Este gancho
+se diferencia del gancho \hook{incoming}, que es ejecutado una vez por
+cada conjunto de cambios, sin importar si los cambios llegan en grupo.
+
+Algunos usos posibles para este gancho includen el probar o ensamblar
+los conjuntos de cambios añadidos, actualizar una base de datos de
+fallos, o notificar a subscriptores de que el repositorio contiene
+nuevos cambios.
+
+Parámetros para este gancho:
+\begin{itemize}
+\item[\texttt{node}] Un ID de conjunto de cambios. El ID del primer conjunto
+  de cambios que fue añadido en el grupo. Todos los conjuntos de
+  cambios entre éste y la punta
+  %TODO mirar qué hacer con el índice
+  \index{tags!\texttt{tip}}(\texttt{tip}), inclusive, fueron añadidos
+  %TODO unbundle
+  por un único jalado (\hgcmd{pull}), empuje (\hgcmd{push}) o \hgcmd{unbundle}.
+\item[\texttt{source}] Una cadena. La fuente de estos cambios. Vea la
+  sección~\ref{sec:hook:sources} para más detalles.
+\item[\texttt{url}] Una URL. La ubicación del repositorio remoto, si
+  es conocida. Vea la sección~\ref{sec:hook:url} para más información.
+\end{itemize}
+
+Veta también: \hook{incoming} (sección~\ref{sec:hook:incoming}),
+\hook{prechangegroup} (sección~\ref{sec:hook:prechangegroup}),
+\hook{pretxnchangegroup} (sección~\ref{sec:hook:pretxnchangegroup})
+
+\subsection{\hook{commit}---luego de la creación de un nuevo conjunto
+de cambios}
+\label{sec:hook:commit}
+
+Este gancho es ejecutado luego de la creación de un nuevo conjunto de
+cambios.
+
+Parámetros para este gancho:
+\begin{itemize}
+\item[\texttt{node}] Un ID de conjunto de cambios. El ID de conjunto
+  de cambios del conjunto de cambios que acabó de ser consignado.
+\item[\texttt{parent1}] Un ID de conjunto de cambios. El ID de
+  conjunto de cambios del primer padre del conjunto de cambios que
+  acaba de ser consignado.
+\item[\texttt{parent2}] Un ID de conjunto de cambios. El ID de
+  conjunto de cambios del segundo padre del conjunto de cambios que
+  acaba de ser consignado.
+\end{itemize}
+
+Vea también: \hook{precommit} (sección~\ref{sec:hook:precommit}),
+\hook{pretxncommit} (sección~\ref{sec:hook:pretxncommit})
+
+\subsection{\hook{incoming}---luego de que un conjunto de cambios
+remoto es añadido}
+\label{sec:hook:incoming}
+
+Este gancho es ejecutado luego de que un conjunto de cambios
+preexistente ha sido añadido al repositorio, por ejemplo, vía un
+\hgcmd{push}.  Si un grupo de conjuntos de cambios fue añadido en una
+sola operación, este gancho es ejecutado una vez por cada conjunto de
+cambios añadido.
+
+Usted puede usar este gancho para los mismos fines que el gancho
+\hook{changegroup} (sección~\ref{sec:hook:changegroup}); simplemente
+algunas veces es más conveniente ejecutar un gancho una vez por cada
+grupo de conjuntos de cambios, mientras que otras es más útil correrlo
+por cada conjunto de cambios.
+
+Parámetros para este gancho:
+\begin{itemize}
+\item[\texttt{node}] Un ID de conjunto de cambios. El ID del conjunto
+  de cambios recién añadido.
+\item[\texttt{source}] Una cadena. La fuente de estos cambios. Vea la
+  sección~\ref{sec:hook:sources} para más detalles.
+\item[\texttt{url}] Una URL. La ubicación del repositorio remoto, si
+  es conocida. Vea la sección~\ref{sec:hook:url} para más información.
+\end{itemize}
+
+Vea también: \hook{changegroup} (sección~\ref{sec:hook:changegroup})
+\hook{prechangegroup} (sección~\ref{sec:hook:prechangegroup}),
+\hook{pretxnchangegroup} (sección~\ref{sec:hook:pretxnchangegroup})
+
+\subsection{\hook{outgoing}---luego de la propagación de los conjuntos
+de cambios}
+\label{sec:hook:outgoing}
+
+Este gancho es ejecutado luego de que un grupo de conjuntos de cambios
+ha sido propagado fuera de éste repositorio, por ejemplo por un
+comando \hgcmd{push} o \hgcmd{bundle}.
+
+Un uso posible para este gancho es notificar a los administradores que
+los cambios han sido jalados.
+
+Parámetros para este gancho:
+\begin{itemize}
+\item[\texttt{node}] Un ID de conjunto de cambios. El ID del primer conjunto
+  de cambios del grupo que fue enviado.
+\item[\texttt{source}] Una cadena. La fuente de la operación (vea la
+  sección~\ref{sec:hook:sources}).  Si un cliente remoto jaló cambios
+  de este repositorio, \texttt{source} será \texttt{serve}.  Si el
+  cliente que obtuvo los cambios desde este repositorio era local,
+  \texttt{source} será \texttt{bundle}, \texttt{pull}, o
+  \texttt{push}, dependiendo de la operación que llevó a cabo el
+  cliente.
+\item[\texttt{url}] Una URL. La ubicación del repositorio remoto, si
+  es conocida. Vea la sección~\ref{sec:hook:url} para más información.
+\end{itemize}
+
+Vea también: \hook{preoutgoing} (sección~\ref{sec:hook:preoutgoing})
+
+\subsection{\hook{prechangegroup}---antes de empezar la adición de
+conjuntos de cambios remotos}
+\label{sec:hook:prechangegroup}
+
+Este gancho de control es ejecutado antes de que Mercurial empiece a
+añadir un grupo de conjuntos de cambios de otro repositorio.
+
+Este gancho no tiene ninguna información acerca de los conjuntos de
+cambios que van a ser añadidos, porque es ejecutado antes de que se
+permita que empiece la transmisión de dichos conjuntos de cambios. Si
+este gancho falla, los conjuntos de cambios no serán transmitidos.
+
+Un uso para este gancho es prevenir que se añadan cambios externos a un
+repositorio. Por ejemplo, usted podría usarlo para ``congelar''
+temporal o permanentemente una rama ubicada en un servidor para que
+los usuarios no puedan empujar cambios a ella, y permitiendo al mismo
+tiempo modificaciones al repositorio por parte de un administrador
+local.
+
+Parámetros para este gancho:
+\begin{itemize}
+\item[\texttt{source}] Una cadena. La fuente de estos cambios. Vea la
+  sección~\ref{sec:hook:sources} para más detalles.
+\item[\texttt{url}] Una URL. La ubicación del repositorio remoto, si
+  es conocida. Vea la sección~\ref{sec:hook:url} para más información.
+\end{itemize}
+
+Vea también: \hook{changegroup} (sección~\ref{sec:hook:changegroup}),
+\hook{incoming} (sección~\ref{sec:hook:incoming}), ,
+\hook{pretxnchangegroup} (sección~\ref{sec:hook:pretxnchangegroup})
+
+\subsection{\hook{precommit}---antes de iniciar la consignación de un
+conjunto de cambios}
+\label{sec:hook:precommit}
+
+Este gancho es ejecutado antes de que Mercurial inicie la consignación
+de un nuevo conjunto de cambios. Es ejecutado antes de que Mercurial
+tenga cualquier de los metadatos para la consignación, como los
+ficheros a ser consignados, el mensaje de consignación, o la fecha de
+consignación.
+
+Un uso para este gancho es deshabilitar la capacidad de consignar
+nuevos conjuntos de cambios, pero permitiendo conjuntos de cambios
+entrantes. Otro es ejecutar un proceso de ensamble/compilación o
+prueba, y permitir la consignación sólo si el ensamble/compilación o
+prueba tiene éxito.
+
+Parámetros para este gancho:
+\begin{itemize}
+  \item[\texttt{parent1}] Un ID de conjunto de cambios. El ID de
+  conjunto de cambios del primer padre del directorio de trabajo.
+\item[\texttt{parent2}] Un ID de conjunto de cambios. El ID de
+  conjunto de cambios del segundo padre del directorio de trabajo.
+\end{itemize}
+Si la consignación continúa, los padres del directorio de trabajo se
+convertirán en los padres del nuevo conjunto de cambios.
+
+Vea también: \hook{commit} (sección~\ref{sec:hook:commit}),
+\hook{pretxncommit} (sección~\ref{sec:hook:pretxncommit})
+
+\subsection{\hook{preoutgoing}---antes de empezar la propagación de
+conjuntos de cambios}
+\label{sec:hook:preoutgoing}
+
+Este gancho es ejecutado antes de que Mercurial conozca las
+identidades de los conjuntos de cambios que deben ser transmitidos.
+
+Un uso para este gancho es evitar que los cambios sean transmitidos a
+otro repositorio.
+
+Parámetros para este gancho:
+\begin{itemize}
+  \item[\texttt{source}] Una cadena. La fuente la operación que está
+    tratando de obtener cambios de éste repositorio (vea
+    la sección~\ref{sec:hook:sources}).  Revise la documentación para
+    el parámetro \texttt{source} del gancho \hook{outgoing}, en la
+    sección~\ref{sec:hook:outgoing}, para ver los posibles valores de
+    este parámetro.
+\item[\texttt{url}] Una URL. La ubicación del repositorio remoto, si
+    es conocida. Vea la sección~\ref{sec:hook:url} para más información.
+\end{itemize}
+
+Vea también: \hook{outgoing} (sección~\ref{sec:hook:outgoing})
+
+\subsection{\hook{pretag}---antes de etiquetar un conjunto de cambios}
+\label{sec:hook:pretag}
+
+Este gancho de control es ejecutado antes de la creación de una
+etiqueta. Si el gancho termina exitosamente, la creación de la
+etiqueta continúa. Si el gancho falla, no se crea la etiqueta.
+
+Parámetros para este gancho:
+\begin{itemize}
+\item[\texttt{local}] Un booleano. Indica si la etiqueta es local a
+  ésta instancia del repositorio (p.e.~almacenado en
+  \sfilename{.hg/localtags}) o administrado por Mercurial (almacenado
+  en \sfilename{.hgtags}).
+\item[\texttt{node}] Un ID de conjunto de cambios. El ID del conjunto
+  de cambios a etiquetar.
+\item[\texttt{tag}] Una cadena. El nombre de la etiqueta por crear.
+\end{itemize}
+
+Si la etiqueta que se va a crear se encuentra bajo control de
+revisiones, los ganchos \hook{precommit} y \hook{pretxncommit}
+(secciones~\ref{sec:hook:commit} y~\ref{sec:hook:pretxncommit})
+también serán ejecutados.
+
+Vea también: \hook{tag} (sección~\ref{sec:hook:tag})
+
+\subsection{\hook{pretxnchangegroup}---antes de completar la adición
+de conjuntos de cambios remotos}
+\label{sec:hook:pretxnchangegroup}
+
+Este gancho de control es ejecutado antes de una transacción---la que
+maneja la adición de un grupo de conjuntos de cambios nuevos desde
+fuera del repositorio---se complete.  Si el gancho tiene éxito, la
+transacción se completa, y todos los conjuntos de cambios se vuelven
+permanentes dentro de este repositorio. Si el gancho falla, la
+transacción es deshecha, y los datos para los conjuntos de cambios son
+eliminados.
+
+Este gancho puede acceder a los metadatos asociados con los conjuntos
+de cambios casi añadidos, pero no debe hacer nada permanente con estos
+datos. Tampoco debe modificar el directorio de trabajo.
+
+Mientras este gancho está corriendo, si otro proceso Mercurial accesa
+el repositorio, podrá ver los conjuntos de cambios casi añadidos como
+si fueran permanentes. Esto puede llevar a condiciones de carrera si
+usted no toma precauciones para evitarlas.
+
+Este gancho puede ser usado para examinar automáticamente un grupo de
+conjuntos de cambios. Si el gancho falla, todos los conjuntos de
+cambios son ``rechazados'' cuando la transacción se deshace.
+
+Parámetros para este gancho:
+\begin{itemize}
+  \item[\texttt{node}] Un ID de conjunto de cambios. El ID del primer
+  conjunto de cambios que fue añadido en el grupo. Todos los
+  conjuntos de cambios entre éste y el
+  \index{tags!\texttt{tip}}\texttt{tip}, inclusive, fueron añadidos
+  por un único \hgcmd{pull}, \hgcmd{push} o \hgcmd{unbundle}.
+\item[\texttt{source}] Una cadena. La fuente de estos cambios. Vea la
+  sección~\ref{sec:hook:sources} para más detalles.
+\item[\texttt{url}] Una URL. La ubicación del repositorio remoto, si
+  es conocida. Vea la sección~\ref{sec:hook:url} para más información.
+\end{itemize}
+
+Vea también: \hook{changegroup} (sección~\ref{sec:hook:changegroup}),
+\hook{incoming} (sección~\ref{sec:hook:incoming}),
+\hook{prechangegroup} (sección~\ref{sec:hook:prechangegroup})
+
+\subsection{\hook{pretxncommit}---antes de completar la consignación
+de un nuevo conjunto de cambios}
+\label{sec:hook:pretxncommit}
+
+Este gancho de control es ejecutado antes de que una transacción---que
+maneja una nueva consignación---se complete. Si el gancho tiene éxito,
+la transacción se completa y el conjunto de cambios se hace permanente
+dentro de éste repositorio. Si el gancho falla, la transacción es
+deshecha, y los datos de consignación son borrados.
+
+Este gancho tiene acceso a los metadatos asociados con el
+prácticamente nuevo conjunto de cambios, pero no debería hacer nada
+permanente con estos datos. Tampoco debe modificar el directorio de
+trabajo.
+
+Mientras este gancho está corriendo, si otro proceso Mercurial accesa
+éste repositorio, podrá ver el prácticamente nuevo conjunto de cambios
+como si fuera permanente. Esto puede llevar a condiciones de carrera si
+usted no toma precauciones para evitarlas.
+
+Parámetros para este gancho:
+\begin{itemize}
+  \item[\texttt{node}] Un ID de conjunto de cambios. El ID del
+    conjunto de cambios recién consignado.
+\item[\texttt{parent1}] Un ID de conjunto de cambios. El ID de
+  conjunto de cambios del primer padre del conjunto de cambios que
+  acaba de ser consignado.
+\item[\texttt{parent2}] Un ID de conjunto de cambios. El ID de
+  conjunto de cambios del segundo padre del conjunto de cambios que
+  acaba de ser consignado.
+\end{itemize}
+
+Vea también: \hook{precommit} (sección~\ref{sec:hook:precommit})
+
+\subsection{\hook{preupdate}---antes de actualizar o fusionar el
+directorio de trabajo}
+\label{sec:hook:preupdate}
+
+Este gancho de control es ejecutado antes de actualizar o fusionar el
+directorio de trabajo. Es ejecutado sólo si las revisiones usuales de
+Mercurial antes de las actualizaciones determinan que la actualización
+o fusión pueden proceder. Si el gancho termina exitosamente, la
+actualización o fusión pueden proceder.; si falla, la actualización o
+fusión no empiezan.
+
+Parámetros para este gancho:
+\begin{itemize}
+\item[\texttt{parent1}] Un ID de conjunto de cambios. El ID del
+  padre al que el directorio de trabajo será actualizado. Si se está
+  fusionando el directorio de trabajo, no cambiará este padre.
+\item[\texttt{parent2}] Un ID de conjunto de cambios. Sólo está
+  definido si se está fusionando el directorio de trabajo. El ID de la
+  revisión con la cual está siendo fusionado el directorio de trabajo.
+\end{itemize}
+
+Vea también: \hook{update} (sección~\ref{sec:hook:update})
+
+\subsection{\hook{tag}---luego de etiquetar un conjunto de cambios}
+\label{sec:hook:tag}
+
+Este gancho es ejecutado luego de la creación de una etiqueta.
+
+Parámetros para este gancho:
+\begin{itemize}
+\item[\texttt{local}] Un booleano. Indica si la etiqueta es local a
+  ésta instancia del repositorio (p.e.~almacenado en
+  \sfilename{.hg/localtags}) o administrado por Mercurial (almacenado
+  en \sfilename{.hgtags}).
+\item[\texttt{node}] Un ID de conjunto de cambios. El ID del
+  conjunto de cambios que fue etiquetado.
+\item[\texttt{tag}] Una cadena. El nombre de la etiqueta que fue
+  creada.
+\end{itemize}
+
+Si la etiqueta creada está bajo control de revisiones, el gancho
+\hook{commit} (sección~\ref{sec:hook:commit}) es ejecutado antes de
+este gancho.
+
+Vea también: \hook{pretag} (sección~\ref{sec:hook:pretag})
+
+\subsection{\hook{update}---luego de actualizar o fusionar el
+directorio de trabajo}
+\label{sec:hook:update}
+
+Este gancho es ejecutado después de una actualización o fusión en el
+directorio de trabajo. Ya que una fusión puede fallar (si el comando
+externo \command{hgmerge} no puede resolver los conflictos en un
+fichero), este gancho indica si la actualización o fusión fueron
+completados adecuadamente.
+
+\begin{itemize}
+\item[\texttt{error}] Un booleano. Indica si la actualización o fusión
+  fue completada exitosamente.
+\item[\texttt{parent1}] Un ID de conjunto de cambios. El ID del padre
+  al cual fue actualizado el directorio de trabajo. Si se fusionó el
+  directorio de trabajo, no se habrá cambiado este padre.
+\item[\texttt{parent2}] Un ID de conjunto de cambios. Sólo está
+  definido si se fusionó el directorio de trabajo. El ID de la
+  revisión con la que fue fusionado el directorio de trabajo.
+\end{itemize}
+
+Vea también: \hook{preupdate} (sección~\ref{sec:hook:preupdate})
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/htlatex.book	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1 @@
+../en/htlatex.book
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/intro.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,621 @@
+\chapter{Introducción}
+\label{chap:intro}
+
+\section{Acerca del control de revisiones}
+
+El control de revisiones es el proceso de administrar diferentes
+versiones de una pieza de información. En su forma más simple es algo
+que la mayoría de gente hace a mano: cada vez que usted modifica un
+fichero, lo graba con un nuevo nombre que contiene un número, cada uno
+mayor que el anterior.
+
+Administrar manualmente muchas versiones de incluso sólo un fichero es una tarea
+propensa a errores, a pesar de que hace bastante tiempo hay
+herramientas que ayudan en este proceso.  Las primeras herramientas
+para automatizar el control de revisiones fueron pensadas para que un
+usuario administrara un solo fichero.  En las décadas pasadas, el
+alcance de las herramientas de control de revisiones ha ido aumentando
+considerablemente; ahora manejan muchos ficheros y facilitan el
+trabajo en conjunto de varias personas. Las mejores herramientas de
+control de revisiones de la actualidad no tienen problema con miles de
+personas trabajando en proyectos que consisten de cientos de miles de
+ficheros.
+
+\subsection{¿Por qué usar control de revisiones?}
+
+Hay muchas razones por las cuales usted o su equipo desearía usar una
+herramienta automática de control de revisiones para un proyecto.
+\begin{itemize}
+\item Llevar registro del historial y la evolución de su proyecto, para
+  evitar hacer la tarea manualmente. Por cada cambio, tendrá una
+  bitácora de \emph{quién} lo hizo; \emph{por qué} se hizo;
+  \emph{cuándo} se hizo; y de \emph{qué} se trataba el cambio.
+\item Cuando trabaja con más personas, los programas de control de
+  revisiones facilitan la colaboración.  Por ejemplo, cuando varias
+  personas hacen cambios potencialmente incompatibles de forma casi
+  simultánea, el programa le ayudará a identificar y resolver tales
+  conflictos.
+\item Puede ayudarle a recuperarse de equivocaciones. Si aplica un
+  cambio que posteriormente se evidencia como un error, puede
+  revertirlo a una versión previa a uno o muchos ficheros. De hecho,
+  una herramienta \emph{realmente} buena, incluso puede ayudarle
+  efectivamente a darse cuenta exactamente cuándo se introdujo el
+  error (para más detalles ver la sección~\ref{sec:undo:bisect}).
+\item Le ayudará a trabajar simultáneamente, y a manejar las diferencias
+  entre múltiples versiones de su proyecto.
+\end{itemize}
+La mayoría de estas razones son igualmente válidas ---por lo menos en
+teoría--- así esté trabajando en un proyecto solo usted, o con mucha gente.
+
+Algo fundamental acerca de lo práctico de un sistema de control de
+revisiones en estas dos escalas (``un hacker solitario'' y ``un equipo
+gigantesco'') es cómo se comparan los \emph{beneficios} con los
+\emph{costos}.  Una herramienta de control de revisiones que sea
+difícil de entender o usar impondrá un costo alto.
+
+Un proyecto de quinientas personas es muy propenso a colapsar
+solamente con su peso inmediatamente sin una herramienta y un proceso
+de control de versiones. En este caso, el costo de usar control de
+revisiones ni siquiera se tiene en cuenta, puesto que \emph{sin} él,
+el fracaso está casi garantizado.
+
+Por otra parte, un ``arreglo rápido'' de una sola persona, excluiría
+la necesidad de usar una herramienta de control de revisiones, porque
+casi seguramente, el costo de usar una estaría cerca del costo del
+proyecto. ¿No es así?
+
+Mercurial soporta \emph{ambas} escalas de de desarrollo de manera
+única. Puede aprender lo básico en pocos minutos, y dado su bajo
+sobrecosto, puede aplicar el control de revisiones al proyecto más
+pequeño con facilidad. Su simplicidad significa que no tendrá que
+preocuparse por conceptos obtusos o secuencias de órdenes compitiendo
+por espacio mental con lo que sea que \emph{realmente} esté tratando
+de hacer.  Al mismo tiempo, Mercurial tiene alto desempeño y su
+%TODO distribuida? en vez de p2p
+naturaleza peer-to-peer le permite escalar indoloramente para manejar
+grandes proyectos.
+
+Ninguna herramienta de control de revisiones puede salvar un
+proyecto mal administrado, pero la elección de herramientas puede
+hacer una gran diferencia en la fluidez con la cual usted puede
+trabajar en un proyecto.
+
+\subsection{La cantidad de nombres del control de revisiones}
+
+El control de revisiones es un campo amplio, tan amplio que no hay un
+acrónimo o nombre único. A continuación presentamos un listado de
+nombres comunes y acrónimos que se podrían encontrar:
+\begin{itemize}
+\item Control de revisiones (RCS)
+\item Manejo de Configuraciones de Programas (SCM), o administracón de
+  configuraciones
+\item Administración de código fuente
+\item Control de Código Fuente, o Control de Fuentes
+\item Control de Versiones (VCS)
+\end{itemize}
+Algunas personas aducen que estos términos tienen significados
+diversos, pero en la práctica se sobreponen tanto que no hay una
+forma acordada o incluso adecuada de separarlos.
+
+\section{Historia resumida del control de revisiones}
+
+La herramienta de control de revisiones más antigua conocida es SCCS 
+(Sistema de Control de Código), escrito por Marc Rochkind en Bell
+Labs, a comienzos de los setentas (1970s).  SCCS operaba sobre ficheros
+individuales, y requería que cada persona que trabajara en el proyecto
+tuviera acceso a un espacio compartido en un solo sistema.  Solamente
+una persona podía modificar un fichero en un momento dado; el
+arbitramiento del acceso a los ficheros se hacía con candados. Era
+común que la gente pusiera los candados a los ficheros, y que
+posteriormente olvidara quitarlos, impidiendo que otro pudiera
+modificar los ficheros en cuestión sin la intervención del
+administrador.
+
+Walter Tichy desarrolló una alternativa gratuita a SCCS a comienzos
+de los ochentas (1980s); llamó a su programa RCS (Sistema de Control de
+Revisiones).  Al igual que SCCS, RCS requería que los desarrolladores
+trabajaran en un único espacio compartido y colocaran candados a los
+ficheros para evitar que varias personas los modificaran
+simultáneamente.
+
+Después en los ochenta, Dick Grune usó RCS como un bloque de
+construcción para un conjunto de guiones de línea de comando, que
+inicialmente llamó cmt, pero que renombró a CVS (Sistema Concurrente de
+Versiones).  La gran innovación de CVS era que permitía a los
+desarrolladores trabajar simultáneamente de una forma más o menos
+independiente en sus propios espacios de trabajo. Los espacios de
+trabajo personales impedían que los desarrolladores se pisaran las
+mangueras todo el tiempo, situación común con SCCS y RCS.  Cada
+desarrollador tenía una copia de todos los ficheros del proyecto y podía
+modificar sus copias independientemente, Tenían que fusionar sus
+ediciones antes de consignar los cambios al repositorio central.
+
+Brian Berliner tomó los scripts originales de Grune y los reescribió
+en~C, publicando en 1989 el código sobre el cual se ha
+desarrollado la versión moderna de CVS.  CVS adquirió posteriormente 
+la habilidad de operar sobre una conexión de red, dotándolo de una
+arquitectura, cliente/servidor. La arquitectura de CVS es
+centralizada; el historial del proyecto está únicamente en el
+repositorio central.  Los espacios de trabajo de los clientes
+contienen únicamente copias recientes de las versiones de los
+ficheros, y pocos metadatos para indicar dónde está el servidor. CVS
+ha tenido un éxito enorme; Es probablemente el sistema de control de
+revisiones más extendido del planeta.
+
+A comienzos de los noventa~(1990s), Sun MicroSystems desarrollo un
+temprano sistema distribuido de control de revisiones llamado
+TeamWare.
+Un espacio de trabajo TeamWare contiene una copia completa del
+historial del proyecto. TeamWare no tiene la noción de repositorio
+central. (CVS se basaba en RCS para el almacenamiento de su historial;
+TeamWare usaba SCCS.)
+
+A medida que avanzaba la decada de los noventa, se empezó a
+evidenciar los problemas de CVS.  Almacena cambios simultáneos a muchos
+ficheros de forma individual, en lugar de agruparlos como una
+operación única y atómica lógicamente.  No maneja bien su jerarquía de
+ficheros; es fácil desordenar un repositorio al renombrar ficheros
+y directorios. Peor aún, su código fuente es difícil de leer y
+mantener, lo que hizo que su ``umbral de dolor'' para arreglar sus
+problemas arquitecturales fuera algo prohibitivo.
+
+En 2001, Jim Blandy y Karl Fogel, dos desarrolladores que habían
+trabajado en CVS, comenzaron un proyecto para reemplazarlo con una
+herramienta con mejor arquitectura y código más limpio.  El resultado,
+Subversion, no se separó del modelo centralizado cliente/servidor de
+CVS, pero añadió consignaciones atómicas de varios ficheros, mejor
+manejo de espacios de nombres , y otras características que lo hacen
+mejor que CVS. Desde su versión inicial, ha ido creciendo en
+popularidad rápidamente.
+
+Más o menos en forma simultánea Graydon Hoare comenzó a trabajar en un
+ambicioso sistema distribuido de control de versiones que llamó
+Monotone. Mientras que Monotone se enfocaba a evitar algunas fallas de
+diseño de CVS con una arquitectura peer-to-peer, fue mucho más
+allá de las herramientas anteriores (y posteriores) de
+control de revisiones en varios aspectos innovadores. Usa hashes
+criptográficos como identificadores, y tiene una noción integral de 
+``confianza'' para código de diversas fuentes.
+
+Mercurial nació en el 2005.  Algunos de sus aspectos de de diseño
+fueron influenciados por Monotone, pero Mercurial se enfoca en la
+facilidad de uso, gran rendimiento y escalabilidad para proyectos muy
+grandes.
+
+\section{Tendencias en el control de revisiones}
+
+Ha habido una tendencia inconfundible en el desarrollo y uso de las herramientas
+de control de revisiones en las cuatro décadas pasadas, mientras la
+gente se ha hecho familiar con las capacidades de sus herramientas y
+se ha visto restringida por sus limitaciones.
+
+La primera generación comenzó administrando ficheros individuales en
+computadores por persona. A pesar de que tales herramientas
+representaron un avance importante frente al control de revisiones
+manual, su modelo de candados y la dependencia a un sólo computador
+los limitó a equipos de trabajo pequeños y acoplados.
+
+La segunda generación dejó atrás esas limitaciones moviéndose a
+arquitecturas centradas en  redes, y administrando proyectos completos
+a la vez. A medida que los proyectos crecían, nacieron nuevos
+problemas. Con la necesidad de comunicación frecuente con los
+servidores, escalar estas máquinas se convirtió en un problema en
+proyectos realmente grandes. Las redes con poca estabilidad podrían
+impedir que usuarios remotos se conectaran al servidor. A medida que
+los
+proyectos de código abierto comenzaron a ofrecer acceso de sólo lectura
+de forma anónima a cualquiera, la gente sin permiso para consignar
+vio que no podían usar tales herramientas para interactuar en un
+proyecto de forma natural, puesto que no podían guardar sus cambios.
+
+La generación actual de herramientas de control de revisiones es
+peer-to-peer por naturaleza.  Todos estos sistemas han eliminado la
+dependencia de un único servidor central, y han permitido que la
+gente distribuya sus datos de control de revisiones donde realmente se
+necesita. La colaboración a través de Internet ha cambiado las
+limitantes tecnológicas por la cuestión de elección y consenso. Las
+herramientas modernas pueden operar sin conexión indefinidamente y
+autónomamente, necesitando una conexión de red solamente para
+sincronizar los cambios con otro repositorio.
+
+\section{Algunas ventajas del control distribuido de revisiones}
+
+A pesar de que las herramientas para el control distribuido de
+revisiones lleva varios años siendo tan robustas y usables como la
+generación previa de sus contrapartes, algunas personas que usan las
+herramientas más antiguas no se han percatado de sus ventajas.  Hay
+gran cantidad
+de situaciones en las cuales las herramientas distribuidas brillan
+frente a las centralizadas.
+
+Para un desarrollador individual, las herramientas distribuidas casi
+siempre son más rápidas que las centralizadas. Por una razón sencilla:
+Una herramienta centralizada necesita comunicarse por red para las
+operaciones más usuales, debido a que los metadatos se almacenan en
+una sola copia en el servidor central. Una herramienta distribuida
+almacena todos sus metadatos localmente.  Con todo lo demás de la
+misma forma, comunicarse por red tiene un sobrecosto en una
+herramienta centralizada. No subestime el valor de una herramienta de
+respuesta rápida: Usted empleará mucho tiempo interactuando con su
+programa de control de revisiones.
+
+Las herramientas distribuidas son indiferentes a los caprichos de su
+infraestructura de servidores, de nuevo, debido a la replicación de
+metadatos en tantos lugares. Si usa un sistema centralizado y su
+servidor explota, ojalá los medios físicos de su copia de seguridad
+sean confiables, y que su última copia sea reciente y además
+funcione. Con una herramienta distribuida tiene tantas copias de
+seguridad disponibles como computadores de contribuidores.
+
+La confiabilidad de su red afectará las herramientas distribuidas de
+una forma mucho menor que a las herramientas centralizadas. Usted no puede
+siquiera usar una herramienta centralizada sin conexión de red,
+excepto por algunas órdenes muy limitadas. Con herramientas
+distribuidas, si sus conexión cae mientras usted está trabajando,
+podría nisiquiera darse cuenta. Lo único que que no podrá hacer es
+comunicarse  con repositorios en otros computadores, algo que es
+relativamente raro comparado con las operaciones locales. Si tiene
+colaboradores remotos en su equipo, puede ser importante.
+
+\subsection{Ventajas para proyectos de código abierto}
+
+Si descubre un proyecto de código abierto y decide que desea comenzar
+a trabajar en él, y ese proyecto usa una herramienta de control
+distribuido de revisiones, usted es de inmediato un par con la gente que se
+considera el ``alma'' del proyecto.  Si ellos publican sus
+repositorios, usted puede copiar inmediatamente el historial del proyecto,
+hacer cambios y guardar su trabajo, usando las mismas herramientas de
+la misma forma que ellos. En contraste, con una herramienta
+centralizada, usted debe usar el programa en un modo ``sólo lectura'' a
+menos que alguien le otorgue permisos para consignar cambios en el
+repositorio central. Hasta entonces, no podrá almacenar sus cambios y
+sus modificaciones locales correrán el riesgo de dañarse cuando trate
+de actualizar su vista del repositorio.
+
+\subsubsection{Las bifurcaciones (forks) no son un problema}
+
+Se ha mencionado que las herramientas de control distribuido de
+versiones albergan un riesgo a los proyectos de código abierto, puesto
+que se vuelve muy sencillo hacer una ``bifurcación''\ndt{fork.} del
+desarrollo del proyecto.  Una bifurcación sucede cuando hay diferencias
+de opinión o actitud entre grupos de desarrolladores que desemboca en
+la decisión de la imposibilidad de continuar trabajando juntos. Cada
+parte toma una copia más o menos completa del código fuente del
+proyecto y toma su propio rumbo.
+
+En algunas ocasiones los líderes de las bifurcaciones reconcilian sus
+diferencias. Con un sistema centralizado de control de revisiones, el
+proceso \emph{técnico} de reconciliarse es doloroso, y se hace de
+forma muy manual.  Usted tiene que decidir qué historial de revisiones va a
+``ganar'', e injertar los cambios del otro equipo en el árbol de alguna
+manera. Con esto usualmente se pierde algo o todo del historial de la
+revisión de alguna de las partes.
+
+Lo que las herramientas distribuidas hacen con respecto a las
+bifurcaciones, es que las bifurcaciones son la \emph{única} forma de
+desarrollar un proyecto. Cada cambio que usted hace es potencialmente
+un punto de bifurcación. La gran fortaleza de esta aproximación es que
+las herramientas distribuidas de control de revisiones tiene que ser
+bueno al \emph{fusionar} las bifurcaciones, porque las bifurcaciones
+son absolutamente fundamentales: pasan todo el tiempo.
+
+Si todas las porciones de trabajo que todos hacen, todo el tiempo, se
+enmarcan en términos de bifurcaciones y fusiones, entonces a aquello a
+lo que se refiere en el mundo del código abierto a una ``bifurcación''
+se convierte \emph{puramente} en una cuestión social. Lo que hacen las
+herramientas distribuidas es \emph{disminuir} la posibilidad de una
+bifurcación porque:
+\begin{itemize}
+\item Eliminan la distinción social que imponen las herramientas
+  centralizadas: aquélla entre miembros (personas con permiso de
+  consignar) y forasteros (los que no tienen el permiso).
+\item Facilitan la reconciliación después de una bifurcación social,
+  porque todo lo que concierne al programa de control de revisiones es
+  una fusión.
+\end{itemize}
+
+Algunas personas se resisten a las herramientas distribuidas porque
+desean mantener control completo sobre sus proyectos, y creen que las
+herramientas centralizadas les dan tal control. En todo caso, si este
+es su parecer, y usted publica sus repositorios de CVS o Subversion, hay
+muchas herramientas disponibles que pueden obtener el historial
+completo (aunque sea lentamente) y recrearlo en otro sitio que usted no
+controla. Siendo así un control ilusorio, puesto que está impidiendo
+la fluidez de colaboración en lugar de prevenir que alguien se sienta
+impulsado a obtener una copia y hacer una bifurcación con su historial.
+
+\subsection{Ventajas para proyectos comerciales}
+
+Muchos proyectos comerciales tienen grupos de trabajo distribuidos
+alrededor del globo.  Quienes contribuyen y están lejos de un
+repositorio central verán una ejecución más lenta de los comandos y tal
+vez menos confiabilidad. Los sistemas de control de revisión
+comerciales intentan amortiguar estos problemas con adiciones de
+replicación remota que usualmente son muy costosos y complicados de
+administrar. Un sistema distribuido no padece estos problemas. Mejor
+aún, puede colocar varios servidores autorizados, por ejemplo, uno por
+sitio, de tal forma que no haya comunicación redundante entre
+repositorios sobre enlaces de conexión costosos.
+
+Los sistemas de control de revisiones distribuidos tienden a ser poco
+escalables. No es inusual que costosos sistemas centralizados caigan
+ante la carga combinada de unas cuantas docenas de usuarios
+concurrentes. De nuevo, las respuestas típicas de replicación tienden
+a ser costosas y complejas de instalar y administrar. Dado que la
+carga en un servidor central---si es que tiene uno---es muchas veces
+menor con una herramienta distribuida (debido a que los datos están
+replicados en todas partes), un solo servidor económico puede tratar
+las necesidades de equipos mucho más grandes, y la replicación para
+balancear la carga se vuelve cosa de guiones.
+
+Si tiene un empleado en el campo, se beneficiará grandemente de un
+sistema distribuido de control de versiones al resolver problemas en
+el sitio del cliente. La herramienta le permitirá generar
+construcciones a la medida, probar diferentes arreglos de forma
+independiente y buscar de forma eficiente las fuentes de fallos en el
+historial y regresiones en los ambientes de los clientes, todo sin
+necesidad de conectarse al servidor de su compañía.
+
+\section{¿Por qué elegir Mercurial?}
+
+Mercurial cuenta con un conjunto único de propiedades que lo hacen
+una elección particularmente buena como sistema de control de
+revisiones, puesto que:
+\begin{itemize}
+\item Es fácil de aprender y usar.
+\item Es liviano.
+\item Escala de forma excelente.
+\item Es fácil de acondicionar.
+\end{itemize}
+
+Si los sistemas de control de revisiones le son familiares, debería
+estar listo para usar Mercurial en menos de cinco minutos. Si no, sólo va a
+tomar unos pocos minutos más. Las órdenes de Mercurial y su conjunto
+de características son uniformes y consistentes generalmente, y basta
+con que siga unas pocas reglas generales en lugar de un montón de
+excepciones.
+
+En un proyecto pequeño, usted puede comenzar a trabajar con Mercurial en
+pocos momentos. Crear nuevos cambios y ramas, transferir cambios (localmente
+o por la red); y las operaciones relacionadas con el estado y el
+historial son rápidas. Mercurial buscar ser ligero y no incomodar en su
+camino combinando poca sobrecarga cognitiva con operaciones
+asombrosamente rápidas.
+
+La utilidad de Mercurial no se limita a proyectos pequeños: está
+siendo usado por proyectos con centenas de miles de contribuyentes,
+cada uno conteniendo decenas de miles de ficheros y centenas de
+megabytes de código fuente
+
+Si la funcionalidad básica de Mercurial no es suficiente para usted,
+es muy fácil extenderlo. Mercurial se comporta muy bien con tareas de
+scripting y su limpieza interna junto con su implementación en Python
+permiten añadir características fácilmente en forma de extensiones.
+Hay un buen número de extensiones útiles y populares en este momento,
+desde ayudar a identificar fallos hasta mejorar su desempeño.
+
+\section{Comparación de Mercurial con otras herramientas}
+
+Antes de leer, por favor tenga en cuenta que esta sección
+necesariamente refleja mis propias experiencias, intereses y (tengo que
+decirlo) mis preferencias. He usado cada una de las herramientas de
+control de versiones listadas a continuación, y en muchos casos por
+varios años.
+
+
+\subsection{Subversion}
+
+Subversion es una herramienta de control de revisiones muy popular,
+desarrollada para reemplazar a CVS.  Tiene una arquitectura
+centralizada tipo cliente/servidor.
+
+Subversion y Mercurial tienen comandos con nombres similares para hacer
+las mismas operaciones, por lo que si le son familiares en una, será
+sencillo aprender a usar la otra. Ambas herramientas son portables en
+todos los sistemas operativos populares.
+
+Antes de la versión 1.5, Subversion no tenía soporte para fusiones. En
+el momento de la escritura, sus capcidades para llevar cuenta de las
+funciones son nuevas,
+\href{http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword}{complicadas
+  y poco estables\ndt{buggy}}.
+
+Mercurial tiene una ventaja considerable en desempeño sobre
+Subversion en cualquier operación de control de revisiones que yo haya
+medido. He medido sus ventajas con factores desde dos hasta seis veces
+comparando con almacenamiento de ficheros \emph{ra\_local}
+Subversion~1.4.3, el cual es el método de acceso más rápido.  En los
+escenarios más realistas incluyendo almacenamiento con la red de por
+medio, Subversion se encuentra en desventaja aún mayor. Dado que casi
+todas las órdenes de Subversion deben tratar con el servidor y
+Subversion no tiene utilidades de replicación adecuadas, la capacidad
+del servidor y el ancho de banda se convierten en cuellos de botella
+para proyectos modestamente grandes.
+
+Adicionalmente, Subversion tiene un sobrecosto considerable en
+almacenamiento para evitar transacciones por red en algunas
+operaciones,
+tales como encontrar ficheros modificados (\texttt{status}) y desplegar
+información frente a la revisión actual (\texttt{diff}).  Como
+resultado, la copia de trabajo de Subversion termina siendo del mismo
+tamaño o más grande que un repositorio de Mercurial y el directorio de
+trabajo, a pesar de que el repositorio de Mercurial contiene el
+historial completo  del proyecto.
+
+Subversion tiene soporte amplio de otras herramientas. Mercurial por
+ahora está bastante atrás en este aspecto.  Esta diferencia está
+disminuyendo, y algunas de las herramientas GUI\ndt{Interfaz de
+  Usuario Gráfica}, eclipsan sus equivalentes de Subversion. Al igual
+que Mercurial, Subversion tiene un excelente manual de usuario.
+
+Dado que Subversion no almacena el historial de revisiones en el
+cliente, es muy bueno para administrar proyectos que tienen muchos
+ficheros binarios grandes y opacos. Si consigna cincuenta revisiones
+de un fichero de 10MB que no es comprimible, el esapacio en el cliente
+de Subversion se mantendrá constante mientras que el espacio usado por
+cualquier Sistema Distribuido de Control de Revisiones crecerá
+rápidamente en proporción con el número de revisiones, debido a que
+las diferencias entre cada revisión es grande.
+
+Adicionalmente, generalmente es difícil o más bien, imposible mezclar
+diferentes versiones de un fichero binario. La habilidad de Subversion
+para permitirle al usuario poner una cerradura  a un fichero, de modo
+que tenga un permiso exclusivo para consignar cambios, puede ser una
+ventaja significativa en un proyecto donde los ficheros binarios sean
+usados ampliamente.
+
+Mercurial puede importar el historial de revisiones de un repositorio
+de Subversion. También puede exportar el historial de revisiones a un
+repositorio de Subversion.  De esta forma es sencillo ``dar un
+vistazo'' y usar Mercurial y Subversion en paralelo antes de decidirse
+a dar el paso. La conversión del historial es incremental, de modo
+que puede aplicar una conversión inicial, y después conversiones
+pequeñas y adicionales posteriormente para traer nuevos cambios.
+
+\subsection{Git}
+
+Git es una herramienta distribuida de control de revisiones
+desarrollada para administrar el arbol del kernel de Linux.  Al igual
+que Mercurial los principios de su diseño fueron influenciados por 
+Monotone.
+
+Git tiene un conjunto de órdenes muy grande; en la versión~1.5.0
+ofrece~139 órdenes individuales.  Tiene cierta reputación de ser
+difícil de aprender. Comparado con Git, Mercurial tiene un fuerte
+enfoque hacia la facilidad.
+
+En términos de rendimiento, Git es extremadamente rápido. En muchos
+casos, es más rápido que Mercurial, por lo menos en Linux, mientras
+que Mercurial se comporta mejor en otras operaciones.  De todas
+maneras en Windows, el desempeño y el nivel general de soporte que
+ofrece Git, al momento de la escritura, está bastante atrás de
+Mercurial.
+
+Mientras que el repositorio de Mercurial no requiere mantenimiento, el
+repositorio de Git requiere frecuentes ``reempaquetados'' de sus metadatos.
+Sin estos, el desempeño se degrada y el uso de espacio crece rápidamente. Un
+servidor que contenga repositorios de Git que no sean reempacados
+rigurosa y frecuentemente requerirá trabajo intenso de disco durante
+las copias de seguridad, y ha habido situaciones en copias de
+seguridad diaria que toman más de~24 horas como resultado. Un
+repositorio recién reempacado de Git es un poco más pequeño que un
+repositorio de Mercurial, pero un repositorio sin reempacar es varios
+órdenes de magnitud más grande.
+
+El corazón de Git está escrito en C.  Muchas órdenes de Git están
+implementadas como guiones de línea de comandos o de Perl y la calidad de esos
+guiones varía ampliamente. He encontrado muchas situaciones en las
+cuales los guiones no tuvieron en cuenta la presencia de errores que
+podrían haber sido fatales.
+
+Mercurial puede importar el historial de revisiones de un repositorio
+de Git.
+
+\subsection{CVS}
+
+CVS es probablemente la herramienta de control de revisiones más
+ampliamente usada en el planeta.  Debido a su edad y su poca pulcritud
+interna, ha sido ligeramente mantenida en muchos años.
+
+Tiene una arquitectura centralizada cliente/servidor. No agrupa
+cambios relacionados en consignaciones atómicas, pemitiendo que con
+facilidad la gente ``rompa la construcción'': una persona puede
+consignar exitósamente parte del cambio y estar bloqueada por la
+necesidad de una mezcla, forzando a otras personas a ver solamente una
+porción del trabajo que estaban buscando hacer.  Esto afecta también
+la forma como usted trabaja con el historial del proyecto. Si quiere
+ver todas las modificaciones que alguien hizo como parte de una tarea,
+necesitará inspeccionar manualmente las descripciones y las marcas de
+tiempo de cambio de cada fichero involucrado (esto, si usted saber
+cuáles eran tales ficheros).
+
+CVS tiene una noción confusa de etiquetas y ramas que yo no trataría
+incluso de describir.  No soporta renombramiento de ficheros o
+directorios adecuadamente, facilitando el corromper un
+repositorio. Casi no tiene chequeo de consistencia interna, por lo
+tanto es casi imposible identificar por que o cómo se corrompió un
+repositorio. Yo no recomendaría un repositorio de CVS para proyecto
+alguno, ni existente ni nuevo.
+
+Mercurial puede importar el historial de revisiones de CVS.  De todas
+maneras hay ciertas precauciones que aplican; las cuales también son
+necesarias para cualquier herramienta importadora de historial de
+CVS. Debido a la falta de atomicidad de cambios y el no versionamiento
+de la jerarquía del sistema de ficheros, es imposible reconstruir
+completamente el historial de CVS con precisión; hay cierto trabajo de
+conjetura involucrado y los renombramientos tampoco se
+mostrarán. Debido a que gran parte de la administración avanzada de
+CVS tiene que hacerse manualmente y por lo tanto es proclive al error,
+es común que los importadores de CVS encuentren muchos problemas con
+repositorios corruptos (marcas de tiempo totalmente desubicadas y
+ficheros que han permanecido con candados por más de una década son
+dos de los problemas menos interesantes de los que puedo retomar de mi
+experiencia personal).
+
+Mercurial puede importar el historial de revisiones de un repositorio
+CVS.
+
+\subsection{Herramientas comerciales}
+
+Perforce tiene una arquitectura centralizada cliente/servidor sin
+almacenamiento de dato alguno de caché en el lado del cliente. A diferencia de
+las herramientas modernas de control de revisiones, Perforce requiere
+que un usuario ejecute un comando para informar al servidor acerca de
+todo fichero que se vaya a editar.
+
+El rendimiento de Perforce es muy bueno para equipos pequeños, pero se
+degrada rápidamente cuando el número de usuarios va más allá de pocas
+docenas. Instalaciones modestamente grandes de Perforce requiere la
+organización de proxies para soportar la carga que sus usuarios generan.
+
+\subsection{Elegir una herramienta de control de revisiones}
+
+Con la excepción de CVS, toda las herramientas que se han listado
+anteriormente tienen fortalezas únicas que las hacen valiosas de acuerdo al
+tipo de trabajo. No hay una única herramienta de control de revisiones
+que sea la mejor en todas las situaciones.
+
+Por ejemplo, Subversion es una buena elección para trabajar con
+edición frecuente de ficheros binarios, debido a su naturaleza
+centralizada y soporte para poner candados a ficheros.
+
+Personalmente encuentro las propiedades de simplicidad, desempeño, y
+buen soporte de fusiones de Mercurial una combinación llamativa que ha
+dado buenos frutos por varios años.
+
+
+\section{Migrar de otra herramienta hacia Mercurial}
+
+Mercurial viene con una extensión llamada \hgext{convert}, que puede
+importar historiales de revisiones de forma incremental desde varias
+herramientas de control de revisiones. Por ``incremental'', quiero
+decir que puede migrar toda el historial de un proyecto en una primera
+instancia y después volver a ejecutar la migración posteriormente para
+obtener los nuevos cambios que han sucedido después de la migración
+inicial.
+
+A continuación presentamos las herramientas de revisiones que soporta
+el comando \hgext{convert}:
+\begin{itemize}
+\item Subversion
+\item CVS
+\item Git
+\item Darcs
+\end{itemize}
+
+Adicionalmente, \hgext{convert} puede exportar cambios de Mercurial
+hacia Subversion.  Lo que hace posible probar Subversion y Mercurial
+en paralelo antes de lanzarse a un migración total, sin arriesgarse a
+perder trabajo alguno.
+
+El comando \hgxcmd{conver}{convert} es sencillo de usar. Basta con
+apuntarlo hacia la ruta o el URL del repositorio fuente, opcionalmente
+darle el nombre del nombre del repositorio destino y comenzará a hacer
+su trabajo. Después de la conversión inicial, basta con invocar de
+nuevo el comando para importar cambios nuevos.
+
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
Binary file es/kdiff3.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/license.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,142 @@
+\chapter{Licencia de Publicación Abierta}
+\label{cha:opl}
+
+Versión 1.0, 8 Junio de 1999
+
+\section{Requerimientos en versiones modificadas y no modificadas}
+
+Los trabajos bajo Publicación Abierta pueden reproducirse y
+distribuirse enteros o en porciones, en cualquier medio físico o
+electrónico, siempre y cuando se respeten los términos de esta 
+licencia, y se incorpore esta licencia o su referencia (con cualquiera
+de las opciones elegidas por el autor y el editor) en la reproducción.
+
+A continuación mostramos la forma correcta de incorporar por referencia:
+
+\begin{quote}
+  Copyright (c) \emph{año} por \emph{nombre del autor o designado}.
+  Este material puede distribuirse solamente bajo los términos y
+  condiciones especificados por la Licencia de Publicación Abierta,
+  v\emph{x.y} o  posterior (la última versión disponible está en
+  \url{http://www.opencontent.org/openpub/}).
+\end{quote}
+
+La referencia debe estar seguida inmediatamente por cualquier opción
+elegida por el(os) autor(es) y/o editor(es) del documento (consulte la
+sección~\ref{sec:opl:options}).
+
+Se permite la redistribución comercial de los materiales sujetos a la
+Publicación Abierta.
+
+Cualquier publicación en forma estándar de libro (papel) requerirá
+citar al editor y autor original.  Los nombres del editor y el autor
+aparecerán en todas las superficies externas del libro.  En todas las
+superficies externas el nombre del editor deberá aparecer en tamaño de
+la misma medida que el título del trabajo y será citado como poseedor
+con respecto al título.
+
+\section{Derechos de reproducción}
+
+El derecho de reproducción de cada Publicación Abierta pertenece
+al(os) autor(es) o designados.
+
+\section{Alcance de la licencia}
+
+Los términos de licencia dsecritos aplican a todos los trabajos bajo
+licencia de publicación abierta a menos que se indique de otra forma
+en este documento.
+
+La simple agregación de trabajos de Publicación Abierta o una porción
+de trabajos de Publicación Abierta con otros trabajos o programas en
+el mismo medio no causarán que esta licencia se aplique a los otros
+trabajos.  Los agregados deberán contener una nota que especifique la
+inclusión de matrial de Publicación Abierta y una nota de derechos de
+reproducción acorde.
+
+\textbf{Separabilidad}. Si cualquier porción de esta licencia no es
+aplicable en alguna jurisdicción, las porciones restantes se
+mantienen.
+
+\textbf{Sin garantía}.  Los trabajos de Publicación Abierta se
+licencian y ofrecen ``como están'' sin garantía de ninguna clase,
+expresa o implícita, incluyendo, pero no limitados a las garantías de
+mercabilidad y adaptabilidad para un propósito particular o garantía
+de no infracción.
+
+\section{Requerimientos sobre trabajos modificados}
+
+Todas las versiones modificadas de documentos cubiertos por esta
+licencia, incluyendo traducciones, antologías, compilaciones y
+documentos parciales, deben seguir estos requerimientos:
+
+\begin{enumerate}
+\item La versión modificada debe estar etiquetada como tal.
+\item La persona que hace la modificación debe estar identificada y la
+  modificación con fecha.
+\item El dar crédito al autor original y al editor si se requiere de
+  acuerdo a las prácticas académicas de citas.
+\item Debe identificarse el lugar del documento original sin
+  modificación.
+\item No puede usarse el(os) nombre(s) del autor (de los autores) para
+  implicar relación alguna con el documento resultante sin el permiso
+  explícito del autor (o de los autores).
+\end{enumerate}
+
+\section{Recomendaciones de buenas prácticas}
+
+Adicional a los requerimientos de esta licencia, se solicita a los
+redistribuidores y se recomienda en gran medida que:
+
+\begin{enumerate}
+\item Si está distribuyendo trabajaos de Publicación Abierta en copia
+  dura o CD-ROM, envíe una notificación por correo a los autores
+  acerca de su intención de redistribuir por lo menos con treinta días
+  antes de que su manuscrito o el medio se congelen, para permitir a
+  los autores tiempo para proveer documentos actualizados.  Esta
+  notificación debería describir las modificaciones, en caso de que
+  haya, al documento.
+\item Todas las modificaciones sustanciales (incluyendo eliminaciones)
+  deben estar marcadas claramente en el documento o si no descritas en
+  un adjunto del documento.
+\item Finalmente, aunque no es obligatorio bajo esta licencia, se
+  considera de buenos modales enviar una copia gratis de cualquier
+  expresión en copia dura o CD-ROM de un trabajo licenciado con
+  Publicación Abierta a el(os) autor(es).
+\end{enumerate}
+
+\section{Opciones de licencia}
+\label{sec:opl:options}
+
+El(os) autor(es) y/o editor de un documento licenciado con Publicación
+Abierta pueden elegir ciertas opciones añadiendo información a la
+referencia o a la copia de la licencia.  Estas opciones se consideran
+parte de la instancia de la licencia y deben incluirse con la
+licencia (o su incorporación con referencia) en trabajos derivados.
+
+\begin{enumerate}[A]
+\item Prohibir la distribución de versiones substancialmente
+  modificadas sin el permiso explícito del(os) autor(es).  Se definen
+  ``modificaciones substanciales'' como cambios en el contenido
+  semántico del documento, y se excluyen simples cambios en el formato
+  o correcciones tipográficas.
+
+  Para lograr esto, añada la frase ``Se prohibe la distribución de
+  versiones substancialmente modificadas de este documento sin el
+  permiso explícito del dueño de los derechos de reproducción.'' a la
+  referencia de la licencia o a la copia.
+
+\item Está prohibido prohibir cualquier publicación de este trabajo o
+  derivados como un todo o una parte en libros estándar (de papel) con
+  propósitos comerciales a menos que se obtenga un permiso previo del
+  dueño de los derechos de reproducción.
+
+  Para lograrlo, añada la frase ``La distribución del trabajo o
+  derivados en cualquier libro estándar (papel) se prohibe a menos que
+  se obtenga un permiso previo del dueño de los derechos de
+  reproducción.'' a la referencia de la licencia o la copia.
+\end{enumerate}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/metadata.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,337 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="metadata.svg"
+   sodipodi:docbase="/home/bos/hg/hgbook/en"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective2479" />
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path2944"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.98994949"
+     inkscape:cx="232.14286"
+     inkscape:cy="519.03485"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="181"
+     inkscape:window-y="58"
+     showgrid="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#a7a7a7;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:4.5, 1.5;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 326.94646,467.18359 L 326.94646,510.98123"
+       id="path1910"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#rect2962"
+       inkscape:connection-start="#rect2764" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#a7a7a7;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:4.5, 1.5;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 326.94646,531.98123 L 326.94646,591.77887"
+       id="path1912"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect2962"
+       inkscape:connection-end="#rect3000" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#a7a7a7;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:4.5, 1.5;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 316.1622,531.98123 L 192.30212,652.57648"
+       id="path1916"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#rect3038"
+       inkscape:connection-start="#rect2962" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#484848;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:4.5, 1.5;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 254.23217,467.18359 L 254.23216,510.98123"
+       id="path3088"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect1872"
+       inkscape:connection-end="#rect2960" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#484848;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:4.5, 1.5;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 254.23215,531.98123 L 254.23215,591.77887"
+       id="path3090"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect2960"
+       inkscape:connection-end="#rect2998" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#484848;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:4.5, 1.5;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 248.84002,531.98123 L 186.90999,652.57648"
+       id="path3092"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect2960"
+       inkscape:connection-end="#rect3038" />
+    <rect
+       style="fill:#7b7df5;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect1872"
+       width="51.42857"
+       height="20"
+       x="228.51788"
+       y="446.68359" />
+    <rect
+       style="fill:#cacbfb;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2764"
+       width="51.42857"
+       height="20"
+       x="301.23218"
+       y="446.68359" />
+    <rect
+       style="fill:#cacbfb;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2766"
+       width="51.42857"
+       height="20"
+       x="155.80359"
+       y="446.68359" />
+    <rect
+       style="fill:#cacbfb;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2768"
+       width="51.42857"
+       height="20"
+       x="83.089294"
+       y="446.68359" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 135.01786,456.68359 L 155.30359,456.68359"
+       id="path2770"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect2768"
+       inkscape:connection-end="#rect2766" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 207.73216,456.68359 L 228.01788,456.68359"
+       id="path2772"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect2766"
+       inkscape:connection-end="#rect1872" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 280.44645,456.68359 L 300.73218,456.68359"
+       id="path2774"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect1872"
+       inkscape:connection-end="#rect2764" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 62.303571,456.68359 L 82.589294,456.68359"
+       id="path2778"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#rect2768" />
+    <rect
+       style="fill:#84f57b;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2960"
+       width="51.42857"
+       height="20"
+       x="228.51787"
+       y="511.48123" />
+    <rect
+       style="fill:#cefbca;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2962"
+       width="51.42857"
+       height="20"
+       x="301.23218"
+       y="511.48123" />
+    <rect
+       style="fill:#cefbca;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2964"
+       width="51.42857"
+       height="20"
+       x="155.80357"
+       y="511.48123" />
+    <rect
+       style="fill:#cefbca;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2966"
+       width="51.42857"
+       height="20"
+       x="83.089287"
+       y="511.48123" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 135.01786,521.48121 L 155.30359,521.48121"
+       id="path2968"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 207.73216,521.48121 L 228.01788,521.48121"
+       id="path2970"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 280.44645,521.48121 L 300.73218,521.48121"
+       id="path2972"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 62.30358,521.48121 L 82.5893,521.48121"
+       id="path2974"
+       inkscape:connector-type="polyline" />
+    <rect
+       style="fill:#f57b8f;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2998"
+       width="51.42857"
+       height="20"
+       x="228.51787"
+       y="592.27887" />
+    <rect
+       style="fill:#fbcad2;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3000"
+       width="51.42857"
+       height="20"
+       x="301.23218"
+       y="592.27887" />
+    <rect
+       style="fill:#fbcad2;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3002"
+       width="51.42857"
+       height="20"
+       x="155.80357"
+       y="592.27887" />
+    <rect
+       style="fill:#fbcad2;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3004"
+       width="51.42857"
+       height="20"
+       x="83.089287"
+       y="592.27887" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 135.01786,602.27884 L 155.30359,602.27884"
+       id="path3006"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 207.73216,602.27884 L 228.01788,602.27884"
+       id="path3008"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 280.44645,602.27884 L 300.73218,602.27884"
+       id="path3010"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 62.30358,602.27884 L 82.5893,602.27884"
+       id="path3012"
+       inkscape:connector-type="polyline" />
+    <rect
+       style="fill:#ffced6;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3034"
+       width="51.42857"
+       height="20"
+       x="228.51787"
+       y="653.07648" />
+    <rect
+       style="fill:#f57b8f;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3038"
+       width="51.42857"
+       height="20"
+       x="155.80357"
+       y="653.07648" />
+    <rect
+       style="fill:#fbcad2;fill-opacity:1;stroke:#595959;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3040"
+       width="51.42857"
+       height="20"
+       x="83.089287"
+       y="653.07648" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 135.01786,663.07646 L 155.30359,663.07646"
+       id="path3042"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 207.73216,663.07646 L 228.01788,663.07646"
+       id="path3044"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#747474;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 62.30358,663.07646 L 82.5893,663.07646"
+       id="path3048"
+       inkscape:connector-type="polyline" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="82.072548"
+       y="432.64789"
+       id="text3094"><tspan
+         sodipodi:role="line"
+         id="tspan3096"
+         x="82.072548"
+         y="432.64789">Bitácora de cambios</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="82.306923"
+       y="498.97327"
+       id="text3098"><tspan
+         sodipodi:role="line"
+         id="tspan3100"
+         x="82.306923"
+         y="498.97327">Manifiesto</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="82.14286"
+       y="580.08569"
+       id="text3102"><tspan
+         sodipodi:role="line"
+         id="tspan3104"
+         x="82.14286"
+         y="580.08569">Bitácora de archivos</tspan></text>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/mq-collab.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,428 @@
+\chapter{Usos avanzados de las Colas de Mercurial}
+\label{chap:mq-collab}
+
+Auunque es fácil aprender los usos más directos de las Colas de
+Mercurial, tener algo de disciplina junto con algunas de las
+capacidadees menos usadas de MQ hace posible trabajar en entornos de
+desarrollo complejos.
+
+En este capítulo, usaré como ejemplo una técnica que he usado para
+administrar el desarrollo de un controlador de dispositivo Infiniband
+para el kernel de Linux. El controlador en cuestión es grande
+(al menos en lo que se refiere a controladores), con 25,000 líneas de
+código esparcidas en 35 ficheros fuente. Es mantenido por un equipo
+pequeño de desarrolladores. 
+
+Aunque mucho del material en este capítulo es específico de Linux, los
+mismos principios aplican a cualquier base de código de la que usted
+no sea el propietario principal, y sobre la que usted necesita hacer
+un montón de desarrollo.
+
+\section{El problema de múltiples objetivos}
+
+El kernel de Linux cambia con rapidez, y nunca ha sido estable
+internamente; los desarrolladores hacen cambios drásticos entre
+%TODO no encontré una traducción adecuada para "release". Por eso el
+%cambio
+versiones frecuentemente. Esto significa que una versión del
+controlador que funciona bien con una versión particular del kernel ni
+siquiera \emph{compilará} correctamente contra, típicamente, cualquier
+otra versión.
+
+Para mantener un controlador, debemos tener en cuenta una buena
+cantidad de versiones de Linux en mente.
+\begin{itemize}
+\item Un objetivo es el árbol de desarrollo principal del kernel de
+  Linux. En este caso el mantenimiento del código es compartido
+  parcialmente por otros desarrolladores en la comunidad del kernel, 
+  %TODO drive-by. 
+  quienes hacen modificaciones ``de-afán'' al controlador a medida que 
+  desarrollan y refinan subsistemas en el kernel.
+  %TODO backport
+\item También mantenemos algunos ``backports'' para versiones antiguas
+  del kernel de Linux, para dar soporte a las necesidades de los
+  clientes que están corriendo versiones antiguas de Linux que no
+  incorporan nuestros controladores. (Hacer el \emph{backport} de un
+  pedazo de código es modificarlo para que trabaje en una versión
+  de su entorno objetivo anterior a aquella para la cual fue escrito.)
+\item Finalmente, nosotros liberamos nuestro software de acuerdo a un
+  cronograma que no necesariamente está alineado con el que usan los
+  distribuidores de Linux y los desarrolladores del kernel, así que
+  podemos entregar nuevas características a los clientes sin forzarlos
+  a actualizar kernels completos o distribuciones.
+\end{itemize}
+
+\subsection{Aproximaciones tentadoras que no funcionan adecuadamente}
+
+Hay dos maneras estándar de mantener una porción de software que debe
+funcionar en muchos entornos diferentes.
+
+La primera es mantener varias ramas, cada una pensada para un único
+entorno. El problema de esta aproximación es que usted debe tener una
+disciplina férrea con el flujo de cambios entre repositorios. Una
+nueva característica o un arreglo de fallo deben empezar su vida en un
+repositorio ``prístino'', y luego propagarse a cada repositorio de
+backport. Los cambios para backports están más limitados respecto a
+las ramas a las que deberían propagarse; un cambio para backport que
+es aplicado a una rama en la que no corresponde probablemente hará que
+el controlador no compile.
+
+La segunda es mantener un único árbol de código fuente lleno de
+declaraciones que activen o desactiven secciones de código dependiendo
+del entorno objetivo. Ya que estos ``ifdefs'' no están permitidos en
+el árbol del kernel de Linux, debe seguirse algún proceso manual o
+automático para eliminarlos y producir un árbol limpio. Una base de
+código mantenida de esta manera se convierte rápidamente en un nido de
+ratas de bloques condicionales que son difíciles de entender y
+mantener.
+
+%TODO canónica?
+Ninguno de estos enfoques es adecuado para situaciones en las que
+usted no es ``dueño'' de la copia canónica de un árbol de fuentes. En
+el caso de un controlador de Linux que es distribuido con el kernel
+estándar, el árbol de Linux contiene la copia del código que será
+considerada por el mundo como la canónica. La versión oficial de
+``mi'' controlador puede ser modificada por gente que no conozco, sin
+que yo siquiera me entere de ello hasta después de que los cambios
+aparecen en el árbol de Linus.
+
+Estos enfoques tienen la debilidad adicional de dificultar la
+%TODO upstream. no no es río arriba
+generación de parches bien formados para enviarlos a la versión
+oficial.
+
+En principio, las Colas de Mercurial parecen ser un buen candidato
+para administrar un escenario de desarrollo como el de arriba. Aunque
+este es de hecho el caso, MQ tiene unas cuantas características
+adicionales que hacen el trabajo más agradable.
+
+\section{Aplicar parches condicionalmente mediante guardias}
+
+Tal vez la mejor manera de conservar la cordura con tantos entornos
+objetivo es poder escoger parches específicos para aplicar para cada
+situación. MQ provee una característica llamada ``guardias''
+(que se origina del comando \texttt{guards} de Quilt) que hace
+precisamente ésto. Para empezar, creemos un repositorio sencillo para
+experimentar.
+\interaction{mq.guards.init}
+Esto nos brinda un pequeño repositorio que contiene dos parches que no
+tienen ninguna dependencia respecto al otro, porque tocan ficheros
+diferentes.
+
+La idea detrás de la aplicación condicional es que usted puede
+``etiquetar'' un parche con un \emph{guardia}, que simplemente es una
+cadena de texto de su elección, y luego decirle a MQ que seleccione
+guardias específicos para usar cuando aplique parches. MQ entonces
+aplicará, u omitirá, un parche vigilado, dependiendo de los guardias
+que usted haya seleccionado.
+
+Un parche puede tener una cantidad arbitraria de guardias; cada uno es
+\emph{positivo} (``aplique el parche si este guardia es
+seleccionado'') o \emph{negativo} (``omita este parche si este guardia
+es seleccionado''). Un parche sin guardias siempre es aplicado.
+
+\section{Controlar los guardias de un parche}
+
+%TODO tal vez no decir determinar, sino definir?
+El comando \hgxcmd{mq}{qguard} le permite determinar qué guardias
+deben aplicarse a un parche, o mostrar los guardias que están en
+efecto. Sin ningún argumento, el comando muestra los guardias del
+parche actual de la parte más alta de la pila.
+\interaction{mq.guards.qguard}
+Para poner un guardia positivo en un parche, prefije el nombre del
+guardia con un ``\texttt{+}''.
+\interaction{mq.guards.qguard.pos}
+Para poner un guardia negativo en un parche, prefije el nombre del
+guardia con un ``\texttt{-}''.
+\interaction{mq.guards.qguard.neg}
+
+\begin{note}
+  El comando \hgxcmd{mq}{qguard} \emph{pone} los guardias en un
+  parche; no los \emph{modifica}. Esto significa que si usted ejecuta
+  \hgcmdargs{qguard}{+a +b} sobre un parche, y luego
+  \hgcmdargs{qguard}{+c} en el mismo parche, el único guardia sobre el
+  parche después del comando será \texttt{+c}.
+\end{note}
+
+Mercurial almacena los guardias en el fichero \sfilename{series}; la
+forma en que son almacenados es fácil tanto de entender como de editar
+a mano. (En otras palabras, usted no tiene que usar el comando
+\hgxcmd{mq}{qguard} si no lo desea; está bien simplemente editar el
+fichero \sfilename{series})
+\interaction{mq.guards.series}
+
+\section{Selecccionar los guardias a usar}
+
+%TODO tal vez no decir determinar, sino definir?
+El comando \hgxcmd{mq}{qselect} determina qué guardias están activos
+en cualquier momento. El efecto de esto es determinar qué parches
+aplicará MQ la próxima vez que usted ejecute \hgxcmd{mq}{qpush}.  No
+tiene ningún otro efecto; en particular, no hace nada a los parches
+que ya han sido aplicados.
+
+Sin argumentos, el comando \hgxcmd{mq}{qselect} lista los guardias en
+efecto actualmente, uno por cada línea de salida. Cada argumento es
+tratado como el nombre de un guardia a aplicar.
+\interaction{mq.guards.qselect.foo}
+Si está interesado, los guardias seleccionados actualmente están
+almacenados en el fichero \sfilename{guards}.
+\interaction{mq.guards.qselect.cat}
+Podemos ver el efecto que tienen los guardias seleccionados cuando
+ejecutamos \hgxcmd{mq}{qpush}.
+\interaction{mq.guards.qselect.qpush}
+
+Un guardia no puede empezar con un  caracter ``\texttt{+}'' o
+``\texttt{-}''. El nombre del guardia no debe contener espacios en
+blanco, pero muchos otros caracteres son aceptables. Si usted trata de
+usar un guardia con un nombre inválido, MQ se quejará:
+\interaction{mq.guards.qselect.error} 
+Cambiar los guardias seleccionados cambia los parches que son
+aplicados.
+\interaction{mq.guards.qselect.quux} 
+Usted puede ver en el ejemplo de abajo que los guardias negativos
+tienen precedencia sobre los guardias positivos.
+\interaction{mq.guards.qselect.foobar}
+
+\section{Reglas de MQ para aplicar parches}
+
+Las reglas que MQ usa para decidir si debe aplicar un parche son las
+siguientes.
+\begin{itemize}
+\item Un parche sin guardias es aplicado siempre.
+\item Si el parche tiene algún guardia negativo que corresponda con
+  cualquiera de los guardias seleccionados, se salta el parche.
+\item Si el parche tiene algún guardia positivo que corresponda con
+  cualquiera de los guardias seleccionados, se aplica el parche.
+\item Si el parche tiene guardias positivos o negativos, pero ninguno
+  corresponde con cualquiera de los guardias seleccionados, se salta
+  el parche.
+\end{itemize}
+
+\section{Podar el entorno de trabajo}
+
+En el trabajo del controlador de dispositivo que mencioné
+anteriormente, yo no aplico los parches a un árbol normal del kernel
+de Linux. En cambio, uso un repositorio que sólo contiene una
+instantánea de los ficheros fuente y de cabecera que son relevantes
+para el desarrollo de Infiniband. Este repositorio tiene un~1\% del
+tamaño del repositorio del kernel, por lo que es más fácil trabajar
+con él.
+
+Luego escojo una versión ``base'' sobre la cual son aplicados los
+parches. Es una instantánea del árbol del kernel de Linux en una
+revisión de mi elección. Cuando tomo la instantánea, almaceno el ID de
+conjunto de cambios en el mensaje de consignación. Ya que la
+instantánea preserva la ``forma'' y el contenido de las partes
+relevantes del árbol del kernel, puedo aplicar mis parches sobre mi
+pequeño repositorio o sobre un árbol normal del kernel.
+
+Normalmente, el árbol base sobre el que se aplican los parches debería
+ser una instantánea de un árbol de desarrollo muy reciente. Esto
+facilita mucho el desarrollo de parches que puedan ser enviados al
+árbol oficial con pocas o ninguna modificación.
+
+\section{Dividir el fichero \sfilename{series}}
+
+Yo categorizo los parches en el fichero \sfilename{series} en una
+serie de grupos lógicos. Cada sección de parches similares empieza con
+un bloque de comentarios que describen el propósito de los parches que
+le siguen.
+
+La secuencia de grupos de parches que mantengo se muestra a
+continuación. El orden de los grupos es importante; explicaré porqué
+luego de que presente los grupos.
+\begin{itemize}
+\item El grupo ``aceptado''. Son parches que el equipo de desarrollo
+  ha enviado al mantenedor del subsistema Infiniband, y que él ha
+  aceptado, pero que no están presentes en la instantánea en la cual
+  está basada el repositorio pequeño. Estos son parches de
+  ``sólo lectura'', presentes únicamente para transformar el árbol en
+  un estado similar al del repositorio del mantenedor oficial.
+\item El grupo ``revisar''. Parches que yo he enviado, pero sobre los
+  que que el mantenedor oficial ha solicitado modificaciones antes de
+  aceptarlos.
+\item El grupo ``pendiente''. Parches que no he enviado al mantenedor
+  oficial, pero que ya están terminados. Estos parches serán de
+  ``sólo lectura'' por un buen tiempo. Si el mantenedor oficial los
+  acepta cuando los envíe, los moveré al final del grupo ``aceptado''.
+  Si él solicita que modificaciones en alguno de ellos, los moveré al
+  principio del grupo ``revisar''.
+\item El grupo ``en proceso''. Parches que están siendo activamente
+  desarrollados, y no deberían ser enviados a ninguna parte aún.
+\item El grupo ``backport''. Parches que adaptan el árbol de fuentes a
+    versiones antiguas del árbol del kernel.
+\item El grupo ``no enviar''. Parches que por alguna razón nunca deben
+  ser enviados al mantenedor oficial del kernel. Por ejemplo, alguno
+  de esos parches podría cambiar las cadenas de identificación
+  embebidas del controlador para hacer más fácil la distinción, en
+  pruebas de campo, entre una versión del controlador de
+  salida-del-árbol  y una versión entregada por un vendedor de alguna
+  distribución.
+\end{itemize}
+
+Ahora volvemos a las razones para ordenar los grupos de parches en
+esta manera. Quisiéramos que los parches del fondo de la pila sean tan
+estables como sea posible, para no tener que revisar parches más
+arriba debido a cambios de contexto. Poner los parches que nunca
+cambiarán en el primer lugar del fichero \sfilename{series} sirve a
+este propósito.
+
+También desearíamos que los parches que sabemos que debemos modificar
+sean aplicados sobre un árbol de fuentes que se parezca al oficial
+tanto como sea posible. Es por esto que mantenemos los parches
+aceptados disponibles por una buena cantidad de tiempo.
+
+Los parches ``backport'' y ``no enviar'' flotan al final del fichero
+\sfilename{series}. Los parches de backport deben ser aplicados encima
+de todos los otros parches, y los parches ``no enviar'' pueden
+perfectamente quedarse fuera del camino.
+
+\section{Mantener la serie de parches}
+
+En mi trabajo, uso varios guardias para controlar qué parches deben
+ser aplicados.
+
+\begin{itemize}
+\item Los parches ``aceptados'' son vigilados con
+  \texttt{accepted}. Yo habilito este guardia la mayoría de las veces.
+  Cuando aplico los parches sobre un árbol donde los parches ya están
+  %TODO no será ``desactivar este guardia''? si sí, corregir versión
+  %en inglés también
+  presentes, puedo desactivar este parche, y los parches que lo siguen
+  se aplicarán sin problemas.
+\item Los parches que están ``terminados'', pero no han sido enviados,
+  no tienen guardias. Si estoy aplicando la pila de parches a una
+  copia del árbol oficial, no necesito habilitar ningún guardia para
+  obtener un árbol de fuentes razonablemente seguro.
+\item Los parches que necesitan revisión antes de ser reenviados
+  tienen el guardia \texttt{rework}.
+\item Para aquellos parches que aún están bajo desarrollo, uso
+  \texttt{devel}.
+\item Un parche de backport puede tener varios guardias, uno para cada
+  versión del kernel a la que aplica. Por ejemplo, un parche que hace
+  backport de un segmento de código a~2.6.9 tendrá un guardia~\texttt{2.6.9}.
+\end{itemize}
+La variedad de guardias me brinda una flexibilidad considerable para
+determinar qué tipo de árbol de fuentes acabaré por obtener. En la
+mayoría de las situaciones, la selección de guardias apropiados es
+automatizada durante el proceso de compilación, pero puedo ajustar
+manualmente los guardias a usar para circunstancias poco comunes.
+
+\subsection{El arte de escribir parches de backport}
+
+Al usar MQ, escribir un parche de backport es un proceso simple. Todo
+lo que dicho parche debe hacer es modificar una sección de código que
+usa una característica del kernel que no está presente en la versión
+anterior del kernel, para que el controlador siga funcionando
+correctamente en esa versión anterior.
+
+Una meta útil al escribir un buen parche de backport es hacer parecer
+que el código hubiera sido escrito para la versión vieja del kernel
+que usted tiene como objetivo. Entre menos intrusivo el parche, más
+fácil será entenderlo y mantenerlo. Si usted está escribiendo una
+colección de parches de backport para evitar el efecto de ``nido de
+ratas'' de tener muchos \texttt{\#ifdef}s (secciones de código fuente
+que sólo son usados condicionalmente) en su código, no introduzca
+\texttt{\#ifdef}s dependientes de versiones específicas en los
+parches. En vez de eso, escriba varios parches, cada uno de ellos
+haciendo cambios incondicionales, y controle su aplicación usando
+guardias.
+
+Hay dos razones para ubicar los parches de backport en un grupo
+diferente, aparte de los parches ``regulares'' cuyos efectos son
+modificados por ellos. La primera es que mezclar los dos hace más
+difícil usar herramientas como la extensión \hgext{patchbomb} para
+automatizar el proceso de enviar los parches a un mantenedor oficial.
+La segunda es que un parche de backport puede perturbar el contexto en
+el que se aplica un parche regular subsecuente, haciendo imposible
+aplicar el parche normal limpiamente \emph{sin} que el parche de
+backport sea aplicado antes.
+
+\section{Consejos útiles para hacer desarrollo con MQ}
+
+\subsection{Organizar parches en directorios}
+
+Si está trabajando en un proyecto grande con MQ, no es difícil
+acumular un gran número de parches. Por ejemplo, tengo un repositorio
+de parches que contiene más de 250 parches.
+
+Si usted puede agrupar estos parches en categorías lógicas separadas,
+usted puede almacenarlos en diferentes directorios si lo desea; MQ no
+tiene problemas manejando nombres de parches que contienen separadores
+de ruta.
+
+\subsection{Ver el historial de un parche}
+\label{mq-collab:tips:interdiff}
+
+Si usted está desarrollando un conjunto de parches en un período de
+tiempo grande, es una buena idea mantenerlos en un repositorio, como
+se discutió en la sección~\ref{sec:mq:repo}.  Si lo hace, notará
+rápidamente que usar el comando \hgcmd{diff} para mirar el historial
+del repositorio no es viable. Esto es debido en parte a que usted está
+mirando la segunda derivada del código real (el diff de un diff), pero
+también porque MQ añade ruido al proceso al modificar las marcas de
+tiempo y los nombres de directorio cuando actualiza un parche.
+
+Sin embargo, usted puede usar la extensión \hgext{extdiff}, que es
+provisto junto con Mercurial, para convertir un diff de dos versiones
+de un parche en algo legible. Para hacer esto, usted necesitará un
+paquete de un tercero llamado
+\package{patchutils}~\cite{web:patchutils}.  Éste paquete provee un
+comando llamado \command{interdiff}, que muestra las diferencias entre
+dos diffs como un diff. Al usarlo en dos versiones del mismo diff,
+genera un diff que representa el diff de la primera a la segunda
+versión.
+
+Usted puede habilitar la extensión \hgext{extdiff} de la manera usual,
+añadiendo una línea a la sección \rcsection{extensions} de su \hgrc.
+\begin{codesample2}
+  [extensions]
+  extdiff =
+\end{codesample2}
+El comando  \command{interdiff} espera recibir los nombres de dos
+ficheros, pero la extensión \hgext{extdiff} le pasa un par de
+directorios al programa que ejecuta, cada uno de los cuales puede
+contener una cantidad arbitraria de ficheros. Por esto necesitamos un
+programa pequeño que ejecute \command{interdiff} en cada par de
+ficheros de estos dos directorios. Este programa está disponible como
+\sfilename{hg-interdiff} en el directorio \dirname{examples} del
+repositorio de código fuente que acompaña a este libro.
+\excode{hg-interdiff}
+
+Con el programa \sfilename{hg-interdiff} en la ruta de búsqueda de su
+intérprete de comandos, puede ejecutarlo como sigue, desde dentro de
+un directorio de parches MQ:
+\begin{codesample2}
+  hg extdiff -p hg-interdiff -r A:B my-change.patch
+\end{codesample2}
+Ya que usted seguramente querrá usar este comando tan largo a menudo,
+puede hacer que \hgext{hgext} lo haga disponible como un comando
+normal de Mercurial, editando de nuevo su \hgrc.
+\begin{codesample2}
+  [extdiff]
+  cmd.interdiff = hg-interdiff
+\end{codesample2}
+Esto le indica a \hgext{hgext} que ponga a disposición un comando
+\texttt{interdiff}, con lo que usted puede abreviar la invocación
+anterior de \hgxcmd{extdiff}{extdiff} a algo un poco más manejable.
+\begin{codesample2}
+  hg interdiff -r A:B my-change.patch
+\end{codesample2}
+
+\begin{note}
+    %TODO revisar redacción
+  El comando \command{interdiff} trabaja bien sólo si los ficheros
+  contra los cuales son generadas las versiones de un parche se
+  mantienen iguales. Si usted crea un parche, modifica los ficheros
+  subyacentes, y luego regenera el parche, \command{interdiff} podría
+  no producir ningún resultado útil.
+\end{note}
+
+La extensión \hgext{extdiff} es útil para más que solamente mejorar la
+presentación de los parches~MQ. Para leer más acerca de esto, vaya a
+la sección~\ref{sec:hgext:extdiff}.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/mq-ref.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,378 @@
+\chapter{Referencia de las Colas de Mercurial}
+\label{chap:mqref}
+
+\section{Referencia de órdenes MQ}
+\label{sec:mqref:cmdref}
+
+Si desea dar un vistazo a las órdenes que ofrece MQ, use la orden
+\hgcmdargs{help}{mq}.
+
+\subsection{\hgxcmd{mq}{qapplied}---imprimir los parches aplicados}
+
+La orden \hgxcmd{mq}{qapplied} imprime la pila actual de parches
+aplicados.  Los parches se imprimen en orden de antigüedad, primero
+los más antiguos y después los más recientes, por lo tanto el último
+parche de la lista es el que está en el ``tope''.
+
+\subsection{\hgxcmd{mq}{qcommit}---consignar cambios en la cola del repositorio}
+
+La orden \hgxcmd{mq}{qcommit} consigna cualquier cambio sobresaliente
+en el repositorio \sdirname{.hg/patches}.  Esta orden solamente
+funciona si el directorio \sdirname{.hg/patches} es un repositorio,
+p.e.~usted creó el directorio con
+\hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} o ejecutó
+\hgcmd{init} en el directorio después de correr \hgxcmd{mq}{qinit}.
+
+Esta orden es un atajo para \hgcmdargs{commit}{--cwd .hg/patches}.
+
+\subsection{\hgxcmd{mq}{qdelete}---eliminar un parche del fichero
+  \sfilename{series}}
+
+La orden \hgxcmd{mq}{qdelete} elimina la entrada del fichero
+\sfilename{series} para el parche en el directorio
+\sdirname{.hg/patches}.  No sca el parche si ha sido aplicado.  De
+forma predeterminada no borra el fichero del parche; use la opción
+\hgxopt{mq}{qdel}{-f} para hacerlo.
+
+Opciones:
+\begin{itemize}
+\item[\hgxopt{mq}{qdel}{-f}] Elimina el fichero del parche.
+\end{itemize}
+
+\subsection{\hgxcmd{mq}{qdiff}---imprimir la diferencia del último
+  parche aplicado}
+
+La orden \hgxcmd{mq}{qdiff} imprime un diff del parche más
+recientemente aplicado.  Es equivalente a \hgcmdargs{diff}{-r-2:-1}.
+
+\subsection{\hgxcmd{mq}{qfold}---fusionar (``integrar'') varios parches en
+  uno solo}
+
+La orden \hgxcmd{mq}{qfold} fusiona muchos parches en el último parche
+aplicado, de tal forma que el último parche aplicado es la unión de
+todos los cambios de los parches en cuestión.
+
+Los parches a fusionar no deben haber sido aplicados;
+\hgxcmd{mq}{qfold} saldrá indicando un error si alguno ha sido
+aplicado.  El orden en el cual los parches se pliegan es
+significativo; \hgcmdargs{qfold}{a b} significa ``aplique el parche
+más reciente, seguido de \texttt{a}, y seguido de \texttt{b}''.
+
+Los comentarios de los parches integrados se colocan al final de los
+comentarios del parche destino, con cada bloque de comentarios
+separado con tres asteriscos (``\texttt{*}'').  Se usa la opción
+\hgxopt{mq}{qfold}{-e} para editar el mensaje de consignación para el
+conjunto de cambios/parches después de completarse el pliegue.
+
+Opciones:
+\begin{itemize}
+\item[\hgxopt{mq}{qfold}{-e}] Edita el mensaje de consignación y la
+  descripción del parche del parche que se ha integrado.
+\item[\hgxopt{mq}{qfold}{-l}] Usa los contenidos del fichero dado como
+  el nuevo mensaje de consignación y descripción del parche para el
+  parche a integrar.
+\item[\hgxopt{mq}{qfold}{-m}] Usa el texto dado como el mensaje de
+  consignación y descripción del parche para el parche integrado.
+\end{itemize}
+
+\subsection{\hgxcmd{mq}{qheader}---desplegar el encabezado/descripción
+  de un parche}
+
+La orden \hgxcmd{mq}{qheader} imprime el encabezado o descripción de
+un parche.  De forma predeterminada, imprime el encabezado del último
+parche aplicado. Si se da un argumento, imprime el encabezado del
+parche referenciado.
+
+\subsection{\hgxcmd{mq}{qimport}---importar el parche de un tercero en
+  la cola}
+
+La orden \hgxcmd{mq}{qimport} añade una entrada de un parche externo
+al fichero \sfilename{series} y copia el parche en el directorio
+\sdirname{.hg/patches}.  Añade la entrada inmediatamente después del
+último parche aplicado, pero no introduce el parche.
+
+Si el directorio \sdirname{.hg/patches} es un repositorio, 
+\hgxcmd{mq}{qimport} automáticamente hace un \hgcmd{add} del parche
+importado.
+
+\subsection{\hgxcmd{mq}{qinit}---preparar un repositorio para trabajar
+  con MQ}
+
+La orden \hgxcmd{mq}{qinit} prepara un repositorio para trabajar con
+MQ.  Crea un directorio llamado \sdirname{.hg/patches}.
+
+Opciones:
+\begin{itemize}
+\item[\hgxopt{mq}{qinit}{-c}] Crea \sdirname{.hg/patches} como un
+  repositorio por sí mismo.  También crea un fichero
+  \sfilename{.hgignore} que ignorará el fichero \sfilename{status}.
+\end{itemize}
+
+Cuando el directorio \sdirname{.hg/patches} es un repositorio, las órdenes
+\hgxcmd{mq}{qimport} y \hgxcmd{mq}{qnew} hacen \hgcmd{add}
+automáticamente a los parches nuevos.
+
+\subsection{\hgxcmd{mq}{qnew}---crear un parche nuevo}
+
+La orden \hgxcmd{mq}{qnew} crea un parche nuevo.  Exige un argumento,
+el nombre que se usará para tal parche.  El parche recién creado está
+vacío inicialmente.   Se añade al fichero \sfilename{series} después
+del último parche aplicado, y se introduce en el tope de ese parche.
+
+Si \hgxcmd{mq}{qnew} encuentra ficheros modificados en el directorio
+de trabajo, rehusará crear un parche nuevo a meos que se emplee
+\hgxopt{mq}{qnew}{-f} la opción (ver más adelante).  Este
+comportamiento le permite hacer \hgxcmd{mq}{qrefresh} al último parche
+aplicado antes de aplicar un parche nuevo encima de este.
+
+Opciones:
+\begin{itemize}
+\item[\hgxopt{mq}{qnew}{-f}] Crea un parche nuevo si los contenidos
+  del directorio actual han sido modificados.  Cualquier modificación
+  significativa se añade al parche recientemente creado,  de tal forma
+  que al finalizar la orden, el directorio de trabajo no lucirá
+  modificado.
+\item[\hgxopt{mq}{qnew}{-m}] Usa el texto dado como el mensaje de
+  consignación.  Este texto se almacenará al principio del fichero del
+  parche, antes de los datos del parche.
+\end{itemize}
+
+\subsection{\hgxcmd{mq}{qnext}---imprimir el nombre del próximo parche}
+
+La orden \hgxcmd{mq}{qnext} imprime el nombre del siguiente parche en
+el fichero \sfilename{series} a continuación del último parche
+aplicado.  Este parche sería el próximo parche a aplicar si se
+ejecutara la orden \hgxcmd{mq}{qpush}.
+
+\subsection{\hgxcmd{mq}{qpop}---sustraer parches de la pila}
+
+La orden \hgxcmd{mq}{qpop} elimina los parches aplicados del tope de
+la pila de parches aplicados.  De forma predeterminada solamente
+remueve un parche.
+
+Esta orden elimina los conjuntos de cambios que representan los
+parches sustraídos del repositorio, y actualiza el directorio de
+trabajo para deshacer los efectos de los parches.
+
+Esta orden toma un argumento opcional, que usa como el nombre o el
+índice del parche que desea sustraer.  Si se da el nombre, sustraerá
+los parches hasta que el parche nombrado sea el último parche
+aplicado.  Si se da un número, \hgxcmd{mq}{qpop} lo trata como un
+índice dentro del fichero \sfilename{series},  contando desde
+cero (no cuenta las líneas vacías o aquellas que sean únicamente
+comentarios).  Sustrae los parches hasta que el parche identificado
+por el índice sea el último parche aplicado.
+
+La orden \hgxcmd{mq}{qpop} no lee o escribe parches en el fichero
+\sfilename{series}.  \hgxcmd{mq}{qpop} se constituye por tanto en una
+forma segura de sustraer un parche del fichero \sfilename{series} o un
+parche que ha eliminado o renombrado completamente.  En los dos
+últimos casos, use el nombre del parche tal como lo hizo cuando lo
+aplicó.
+
+De forma predeterminada, la orden \hgxcmd{mq}{qpop} no sustraerá
+parche alguno si el directorio de trabajo ha sido modificado.  Puede
+modificar este comportamiento con la opción \hgxopt{mq}{qpop}{-f}, que
+revierte todas las modificaciones del directorio de trabajo.
+
+Opciones:
+\begin{itemize}
+\item[\hgxopt{mq}{qpop}{-a}] Sustrae todos los parches aplicados.
+  Restaura el repositorio al estado antes de haber aplicado parche alguno.
+\item[\hgxopt{mq}{qpop}{-f}] Revertir forzadamente cualquier
+  modificación del directorio de trabajo cuando se hace sustracciones.
+\item[\hgxopt{mq}{qpop}{-n}] Sustraer un parche de la cola dado un nombre.
+\end{itemize}
+
+La orden \hgxcmd{mq}{qpop} elimina una línea del final del fichero
+\sfilename{status} por cada parche que se sustrae.
+
+\subsection{\hgxcmd{mq}{qprev}---imprimir el nombre del parche anterior}
+
+La orden \hgxcmd{mq}{qprev} imprime el nombre del parche en el fichero
+\sfilename{series} que está antes del último parche aplicado.   Este
+se volverá el último parche aplicado si ejecuta \hgxcmd{mq}{qpop}.
+
+\subsection{\hgxcmd{mq}{qpush}---introducir parches a la pila}
+\label{sec:mqref:cmd:qpush}
+
+La orden \hgxcmd{mq}{qpush} añade parches a la pila.  De forma
+predeterminada añade solamente un parche.
+
+Esta orden crea un conjunto de cambios que representa cada parche
+aplicado y actualiza el directorio de trabajo aplicando los efectos de
+los parches.
+
+Los datos predeterminados cuando se crea un conjunto de cambios
+corresponde a:
+\begin{itemize}
+\item La fecha de consignación y zona horaria corresponden a la hora
+  actual de la zona.  Dado que tales datos se usan para computar la
+  identidad de un conjunto de cambios, significa que si hace
+  \hgxcmd{mq}{qpop} a un parche y \hgxcmd{mq}{qpush} de nuevo, el
+  conjunto de cambios que introduzca tendrá una identidad distinta a
+  la del conjunto de cambios que sustrajo.
+\item El autor es el mismo que el predeterminado usado por la orden
+  \hgcmd{commit}.
+\item El mensaje de consignación es cualquier texto del fichero del
+  parche que viene antes del primer encabezado del diff.  Si no hay
+  tal texto, un mensaje predeterminado se sua para identificar el
+  nombre del parche.
+\end{itemize}
+Su un parche contiene un encabezado de parche de Mercurial (XXX add
+link), la información en el encabezado del parche tiene precedencia
+sobre el predeterminado.
+
+Opciones:
+\begin{itemize}
+\item[\hgxopt{mq}{qpush}{-a}] Introduce todos los parches que no han
+  sido aplicados del fichero \sfilename{series} hasta que no haya nada
+  más para introducir.
+\item[\hgxopt{mq}{qpush}{-l}] Añade el nombre del parche al final del
+  mensaje de consignación
+\item[\hgxopt{mq}{qpush}{-m}] Si un parche no se aplica limpiamente,
+  usa la entrada para un parche en otra cola almacenada para computar
+  los parámetros en una fusión de tres, y aplica una fusión de tres
+  fuentes usando la maquinaria usual de Mercurial.  Usa la resolución
+  de la fusión como el contenido del parche nuevo.
+\item[\hgxopt{mq}{qpush}{-n}] Usa la cola mencionada si se está
+  fusionando en la introducción.
+\end{itemize}
+
+La orden \hgxcmd{mq}{qpush} lee, pero no modifica el fichero
+\sfilename{series}.  Añade al final del fichero \hgcmd{status} una
+línea por cada parche que se introduce.
+
+\subsection{\hgxcmd{mq}{qrefresh}---actualiza el último parche aplicado}
+
+La orden \hgxcmd{mq}{qrefresh} actualiza el último parche aplicado.
+Modifica el parche, elimina el último conjunto de cambios que
+representó el parche, y crea un nuevo conjunto de cambios para
+representar el parche modificado.
+
+La orden \hgxcmd{mq}{qrefresh} busca las siguientes modificaciones:
+\begin{itemize}
+\item Los cambios al mensaje de consignación, p.e.~el texto antes del
+  primer encabezado de diff en el fichero del parche, se replejan en
+  el nuevo conjunto de cambios que representa el parche.
+\item Las modificaciones a los ficheros a los que se les da
+  seguimiento en el directorio de trabajo se añade al parche.
+\item Los cambios a los ficheros a los que se les da seguimiento con
+  \hgcmd{add}, \hgcmd{copy}, \hgcmd{remove}, o \hgcmd{rename}.  Se
+  añaden al parche los ficheros añadidos, copiados y renombrados,
+  mientras que los ficheros eliminados y las fuentes renombradas se
+  eliminan.
+\end{itemize}
+
+Incluso si \hgxcmd{mq}{qrefresh} no detecta cambios, de todas maneras
+recrea el conjunto de cambios que representa el cambio.  Esto causa
+que la identidad del conjunto de cambios difiera del conjunto de
+cambios previo que identificó al parche.
+
+Opciones:
+\begin{itemize}
+\item[\hgxopt{mq}{qrefresh}{-e}] Modificar la descripción de la
+  consignación y el parche con el editor de texto preferido.
+\item[\hgxopt{mq}{qrefresh}{-m}] Modificar el mensaje de consignación
+  y la descripción del parche con el texto dado.
+\item[\hgxopt{mq}{qrefresh}{-l}] Modificar el mensaje de consignación
+  y la descripción del parche con el texto del fichero dado.
+\end{itemize}
+
+\subsection{\hgxcmd{mq}{qrename}---renombrar un parche}
+
+La orden \hgxcmd{mq}{qrename} renombra un parche y cambia la entrada
+del parche en el fichero \sfilename{series}.
+
+Con un argumento sencillo, \hgxcmd{mq}{qrename} renombra el último
+parche aplicado.  Con dos argumentos, renombra el primer argumento con
+el segundo.
+
+\subsection{\hgxcmd{mq}{qrestore}---restaurar el estado almacenado de
+  la cola}
+
+XXX No idea what this does.
+
+\subsection{\hgxcmd{mq}{qsave}---almacena el estado actual de la cola}
+
+XXX Likewise.
+
+\subsection{\hgxcmd{mq}{qseries}---imprime la serie completa de parches}
+
+La orden \hgxcmd{mq}{qseries} imprime la serie completa de parches del
+fichero \sfilename{series}.  Imprime solamente los nombres de los
+parches sin las líneas en blanco o comentarios.  Imprime primero el
+primero y de último, el último aplicado.
+
+\subsection{\hgxcmd{mq}{qtop}---imprime el nombre del parche actual}
+
+\hgxcmd{mq}{qtop} imprime el nombre del último parche aplicado.
+
+\subsection{\hgxcmd{mq}{qunapplied}---imprimir los parches que aún no
+  se han aplicado}
+
+La orden \hgxcmd{mq}{qunapplied} imprime los nombres de los parches
+del fichero \sfilename{series} que todavía no han sido aplicados.  Los
+imprime de acuerdo al orden en el cual serían introducidos.
+
+\subsection{\hgcmd{strip}---remover una revisión y sus descendientes}
+
+La orden \hgcmd{strip} remueve una revisión, y todos sus descendientes
+del repositorio.  Deshace los efectos de las revisiones removidas del
+repositorio, y actualiza el directorio de trabajo hasta el primer
+padre de la revisión removida.
+
+La orden \hgcmd{strip} almacena una copia de segurida de los conjuntos
+de cambios en un agrupamiento, de forma tal que puedan ser reaplicados
+en caso de que se hayan removido por equivocación.
+
+Opciones:
+\begin{itemize}
+\item[\hgopt{strip}{-b}] Almacenar conjuntos de cambios no
+  relacionados que se han mezclado con los conjuntos de cambios que
+  están en franjas con el agrupamiento de copia de seguridad.
+\item[\hgopt{strip}{-f}] Si una rama tiene varias ramas principales
+  remueve todos los frentes. XXX This should be renamed, y usa
+  \texttt{-f} para desagrupar revisiones cuando hay cambios pendientes.
+\item[\hgopt{strip}{-n}] No almacene la copia de seguridad agrupada.
+\end{itemize}
+
+\section{Referencia de ficheros de MQ}
+
+\subsection{El fichero \sfilename{series}}
+
+El fichero \sfilename{series} contiene una lista de los nombres de
+todos los parches que MQ puede aplicar.  Se representa como una lista
+de nombres, uno por línea.  Se ignora el espacio en blanco al
+principio y al final.
+
+Las líneas pueden contener comentario.  Un comentario comienza con el
+caracter ``\texttt{\#}'', y va hasta el final de la línea.  Se ignoran
+las líneas vacías y las que solamente contengan comentarios.
+
+En algún momento podría editar el fichero \sfilename{series} a mano,
+por tal motivo se admiten comentarios y líneas en blanco como se
+menciono anteriormente.  Por ejemplo, puede poner en comentario un
+parche temporalmente y \hgxcmd{mq}{qpush} omitirá tal parche cuando
+los aplique.  También puede cambiar el orden en el cual se aplican los
+parches, reordenando las entradas en el fichero \sfilename{series}.
+
+También es posible colocar el fichero \sfilename{series} bajo control
+de revisiones;  también es favorable colocar todos los parches que refiera
+bajo control de revisiones.  Si crea un directorio de parches con la
+opción \hgxopt{mq}{qinit}{-c} de \hgxcmd{mq}{qinit}, esto se hará
+automáticamente.
+
+\subsection{El fichero \sfilename{status}}
+
+El fichero \sfilename{status} contiene los nombres y los hashes de los
+conjuntos de cambios de todos los parches que MQ ha aplicado.  A
+diferencia del fichero \sfilename{series}, este NO ha sido diseñado
+para ser editado.  No debería colocar este fichero bajo el control de
+revisiones o modificarlo de forma alguna.  MQ lo usa estrictamente
+para administración interna.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/mq-stack.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="mq-stack.svg"
+   sodipodi:docbase="/home/bos/hg/hgbook/en"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective2525" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4142136"
+     inkscape:cx="299.33323"
+     inkscape:cy="815.646"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="1014"
+     inkscape:window-height="689"
+     inkscape:window-x="89"
+     inkscape:window-y="25"
+     showgrid="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       style="fill:#0000ff;fill-opacity:0.75;fill-rule:evenodd;stroke:#3c3c3c;stroke-width:1.05063355px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       id="rect1307"
+       width="202.93683"
+       height="24.243662"
+       x="230.01944"
+       y="221.70146" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="237.89606"
+       y="237.13383"
+       id="text1309"><tspan
+         sodipodi:role="line"
+         id="tspan1311"
+         x="237.89606"
+         y="237.13383">prevent-compiler-reorder.patch</tspan></text>
+    <rect
+       style="fill:#7979ff;fill-opacity:0.875;fill-rule:evenodd;stroke:#3c3c3c;stroke-width:1.05063355px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       id="rect1320"
+       width="202.93683"
+       height="24.243662"
+       x="230.01936"
+       y="251.34325" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="237.89598"
+       y="266.77563"
+       id="text1322"><tspan
+         sodipodi:role="line"
+         id="tspan1324"
+         x="237.89598"
+         y="266.77563">namespace-cleanup.patch</tspan></text>
+    <rect
+       style="fill:#7979ff;fill-opacity:0.875;fill-rule:evenodd;stroke:#3c3c3c;stroke-width:1.05063355px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       id="rect2217"
+       width="202.93683"
+       height="24.243662"
+       x="230.01936"
+       y="280.98505" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="237.89598"
+       y="296.41742"
+       id="text2219"><tspan
+         sodipodi:role="line"
+         id="tspan2221"
+         x="237.89598"
+         y="296.41742">powerpc-port-fixes.patch</tspan></text>
+    <rect
+       style="fill:#7979ff;fill-opacity:0.875;fill-rule:evenodd;stroke:#3c3c3c;stroke-width:1.05063355px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       id="rect3114"
+       width="202.93683"
+       height="24.243662"
+       x="230.01936"
+       y="310.6268" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="237.89598"
+       y="326.05917"
+       id="text3116"><tspan
+         sodipodi:role="line"
+         id="tspan3118"
+         x="237.89598"
+         y="326.05917">report-devinfo-correctly.patch</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="200.01021"
+       y="191.68094"
+       id="text3170"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3172"
+         x="200.01021"
+         y="191.68094"
+         style="font-size:48px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans">{</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:15.25329685px;font-style:normal;font-weight:normal;line-height:125%;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="255.26627"
+       y="248.79449"
+       id="text3190"
+       sodipodi:linespacing="125%"
+       transform="scale(0.786716,1.271107)"><tspan
+         sodipodi:role="line"
+         id="tspan3192"
+         x="255.26627"
+         y="248.79449"
+         style="font-size:61.01318741px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;font-family:Bitstream Vera Sans">{</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="195.86807"
+       y="173.17117"
+       id="text4085"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4087"
+         x="195.86807"
+         y="173.17117"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;font-family:Bitstream Vera Sans">presente en la serie,</tspan><tspan
+         sodipodi:role="line"
+         x="195.86807"
+         y="188.17117"
+         id="tspan4089"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;font-family:Bitstream Vera Sans">pero no aplicado</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="195.0712"
+       y="288.91745"
+       id="text4091"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4093"
+         x="195.0712"
+         y="288.91745"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;font-family:Bitstream Vera Sans">parches aplicados,</tspan><tspan
+         sodipodi:role="line"
+         x="195.0712"
+         y="303.91745"
+         id="tspan4111"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;font-family:Bitstream Vera Sans">Conjuntos de cambios presentes</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;line-height:125%;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="195.0712"
+       y="229.28813"
+       id="text4095"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4097"
+         x="195.0712"
+         y="229.28813"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;font-family:Bitstream Vera Sans">parche aplicado</tspan><tspan
+         sodipodi:role="line"
+         x="195.0712"
+         y="244.28813"
+         id="tspan4109"
+         style="font-size:12px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:end;line-height:125%;writing-mode:lr-tb;text-anchor:end;font-family:Bitstream Vera Sans">más recientemente</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;opacity:1;fill:#666666;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="450.4975"
+       y="238.29692"
+       id="text4137"><tspan
+         sodipodi:role="line"
+         id="tspan4139"
+         x="450.4975"
+         y="238.29692">201ad3209902</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;opacity:1;fill:#989898;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="450.05804"
+       y="267.93872"
+       id="text4141"><tspan
+         sodipodi:role="line"
+         id="tspan4143"
+         x="450.05804"
+         y="267.93872">126b84e593ae</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;opacity:1;fill:#989898;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="450.6557"
+       y="297.58051"
+       id="text4145"><tspan
+         sodipodi:role="line"
+         id="tspan4147"
+         x="450.6557"
+         y="297.58051">a655daf15409</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;opacity:1;fill:#989898;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="450.71429"
+       y="327.22226"
+       id="text4149"><tspan
+         sodipodi:role="line"
+         id="tspan4151"
+         x="450.71429"
+         y="327.22226">e50d59aaea3a</tspan></text>
+    <rect
+       style="fill:#d7d7ff;fill-opacity:0.875;fill-rule:evenodd;stroke:#a6a6a6;stroke-width:1.05063355px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       id="rect3106"
+       width="202.93683"
+       height="24.243662"
+       x="230.01936"
+       y="150.41792" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#808080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="237.89598"
+       y="165.8503"
+       id="text3108"><tspan
+         sodipodi:role="line"
+         id="tspan3110"
+         x="237.89598"
+         y="165.8503">forbid-illegal-params.patch</tspan></text>
+    <rect
+       style="fill:#d7d7ff;fill-opacity:0.875;fill-rule:evenodd;stroke:#a6a6a6;stroke-width:1.05063355px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       id="rect2241"
+       width="202.93683"
+       height="24.243662"
+       x="230.16466"
+       y="180.05968" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#808080;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+       x="238.04128"
+       y="195.49205"
+       id="text2243"><tspan
+         sodipodi:role="line"
+         id="tspan2245"
+         x="238.04128"
+         y="195.49205">fix-memory-leak.patch</tspan></text>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/mq.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1103 @@
+\chapter{Administración de cambios con Colas de Mercurial}
+\label{chap:mq}
+
+\section{El problema de la administración de parches}
+\label{sec:mq:patch-mgmt}
+
+Un escenario frecuente: usted necesita instalar un paquete de software
+desde las fuentes, pero encuentra un fallo que debe arreglar antes de
+poder comenzar a usarlo.  Hace sus cambios, y se olvida del paquete
+por un tiempo, unos meses después necesita actualizar a una nueva
+versión del paquete.  Si la nueva versión del paquete todavía tiene el
+fallo, debe extraer su arreglo del árbol de fuentes anteriores y
+aplicarlo a la nueva versión.  Una tarea tediosa en la cual es fácil
+equivocarse.
+
+Este es un caso simple del problema del ``manejo de parches''.  Usted
+tiene un árbol de fuentes del ``mantenedor principal'' que no puede
+cambiar: necesita hacer algunos cambios locales sobre el árbol
+principal; y desearía poder mantener tales cambios separados, de forma
+tal que pueda aplicarlos a versiones más nuevas del árbol principal.
+
+El problema de administración de parches surge en muchas situaciones.
+Probablemente la más visible es cuando un usuario de un proyecto de
+software de fuentes abiertas contribuye con un arreglo de un fallo o
+una nueva característica a los mantenedores del proyecto en la forma
+de un parche.
+
+Aquellos que distribuyen sistemas operativos que incluyen programas
+abiertos usualmente requieren hacer cambios en los paquetes que
+distribuyen de tal forma que se armen apropiadamente en sus ambientes.
+
+Cuando hay pocos cambios por mantener, es muy sencillo administrar un
+solo parche con los programas estándar \command{diff} y
+\command{patch} (ver la sección~\ref{sec:mq:patch} para ver cómo
+emplear tales herramientas). Cuando la cantidad de cambios comienza a
+crecer, tiene sentido mantener parches como ``porciones de trabajo''
+individual, de forma que cada cambio contiene solamente un arreglo de
+un fallo (el parche puede modificar varios ficheros, pero está
+``haciendo una sola cosa''), y puede tener cierta cantidad de tales
+parches para diferentes fallos y cambios locales.  En esta situación,
+si envía un parche que arregla un fallo a los mantenedores principales
+de un paquete y ellos incluyen su arreglo en una publicación
+posterior, puede deshacerse de tal parche cuando se actualice a la
+nueva versión.
+
+Mantener un solo parche frente a un árbol principal es algo tedioso y
+es fácil equivocarse, pero no es difícil.  Aunque, la complejidad del
+problema crece rápidamente a medida que la cantidad de parches que
+tiene que mantener crece.  Con más que una pequeña cantidad de
+cambios, entender cuáles ha aplicado se convierte de algo desordenado
+a algo avasallante.
+
+Afortunadamente Mercurial provee una extensión poderos: Colas de
+Mercurial (o simplemente ``MQ''), que simplifica en gran medida el
+problema de administración de parches.
+
+\section{La prehistoria de las Colas de Mercurial}
+\label{sec:mq:history}
+
+A finales de los 90s, muchos desarrolladores del núcleo de Linux
+comenzaron a mantener ``series de parches'' que modificaron el
+comportamiento del núcleo de Linux.  Algunos se enfocaban en
+estabilidad, otros en aumentar las características, y otros un poco
+más especulativos.
+
+Los tamaños de las series de parches crecieron rápidamente.  En el
+2002, Andrew Morton publicó algunos guiones de línea de órdenes que
+estuvo usando para automatizar la tarea de administrar su cola de
+parches.  Andrew usó exitósamente tales guiones para administrar
+centenas (a veces millares) de parches en el núcleo de Linux.
+
+\subsection{Trabajar parches con quilt}
+\label{sec:mq:quilt}
+
+A comienzos del 2003, Andreas Gruenbacher y Martin Quinson tomaron la
+aproximación de los guiones de Andrew y publicaron una herramienta
+llamada
+``patchwork quilt''~\cite{web:quilt}, o simplemente ``quilt''
+(ver~\cite{gruenbacher:2005} el paper que lo describe).  Dado que
+quilt automatizaba sustancialmente la administración de parches, fue
+adoptado en gran medida por desarrolladores de programas abiertos.
+
+Quilt maneja una \emph{pila de parches} sobre un árbol de directorios.
+Para comenzar, usted le indica a quilt que administre un árbol de
+directorios, le indica qué ficheros manejar; Este almacena los nombres
+y los contenidos de estos ficheros.  Para arreglar un fallo, usted
+crea un nuevo parche (con una sola orden), edita los ficheros que está
+arreglando y ``refresca'' el parche.
+
+El paso de refresco hace que quilt revise el árbol de directorios;
+actualiza el parche con todos los cambios que usted haya hecho.  Puede
+crear otro parche sobre el primero, que hará seguimiento de los
+cambios requeridos para modificar el árbol desde ``el árbol con un
+parch aplicado'' a un ``árbol con dos parches aplicados''.
+
+Usted puede \emph{elegir} qué cambios desea aplicar al árbol.  Si
+``pop''\ndt{saca} un parche, los cambios hechos por tal parchve
+desapareceŕan del árbol de directorios.  Quilt recuerda qué parches ha
+sacado, para que pueda ``introducirlos''\ndt{push} posteriormente, así el
+árbol de directorios se restaurará con las modificaciones que vienen
+del parche.  Lo más importante es que puede ejecutar la orden
+``refresh'' en cualquier momento, y el último parche será
+actualizado.  Esto significa que puede, en cualquier momento, cambiar
+qué parches serán aplicados y qué modificaciones hacen ellos.
+
+Quilt no tiene nada que ver con herramientas de control de versiones,
+y puede trabajar bien sobre un conjunto de fuentes que viene de un
+fichero comprimido y empaquetado o una copia de trabajo de Subversion.
+
+\subsection{Pasar de trabajo con parches con Quilt hacia Colas de Mercurial}
+\label{sec:mq:quilt-mq}
+
+A mediados de 2005, Chris Mason tomó las características de quilt y
+escribió una extensión que llamó Colas de Mercurial\ndt{Mercurial
+Queues}, que proporcionó un comportamiento a Mercurial al estilo
+quilt.
+
+La diferencia clave entre quilt y MQ es que quilt no sabe nada acerca
+del sistema de control de revisiones, mientras que MQ está
+\emph{integrado} con Mercurial.  Cada parche que usted introduce se
+representa como un conjunto de cambios en Mercurial.  Si sustrae un
+parche, el conjunto de cambios desaparece.\ndt{introduce originalmente es
+push y pop es sustraer en este contexto, usaremos el original en inglés
+cuando encontremos que facilita la comprensión}
+
+Dado que quilt no se preocupa por las herramientas de control de
+revisiones, continúa siendo una porción de software tremendamente útil
+para aquellas situaciones en las cuales no puede usar Mercurial y MQ.
+
+\section{La gran ventaja de MQ}
+
+No puedo sobreestimar el valor que MQ ofrece en la unificación de
+parches y el control de revisiones.
+
+La principal razón por la cual los parches han persistido en el mundo
+del software libre y de fuentes abiertas--a pesar de la creciente
+disponibilidad de herramientas poderosas de control de revisiones-- es
+la \emph{agilidad} que ofrecen.
+
+Las herramientas tradicionales de control de revisiones llevan un
+registro permanente e irreversible de todo lo que usted hace.  A pesar
+de que esto tiene gran valor, también es bastante sutil.  Si requiere
+realizar un experimento ((((wild-eyed)))), debe ser cuidadoso en cómo
+lo hace, o puede dejar trazas innecesarias--o peor aún,
+desconcertantes o desestabilizantes--- de los pasos y errores en el
+registro de revisiones de forma permanente.
+
+En contraste, con la cohesión de MQ con el control de revisiones
+distribuidos y los parches, resulta más sencillo aislar su trabajo.
+Sus parches viven encima del historial de revisiones normales, y
+puede hacer que ellos desaparezcan o reaparezcan cuando lo desee.  Si
+no le gusta un parche, puede desecharlo.  Si un parche no satisface
+todo lo que usted desea, puede arreglarlo---tantas veces como lo
+requiera, hasta que lo haya refinado lo suficiente hacia sus
+expectativas.
+
+Por ejemplo, la integración de parches con el control de revisiones
+hace que el entender los parches y revisar sus efectos---y sus
+interacciones con el código en el cuál están enlazados--- sea
+\emph{mucho} más sencillo.  Dado que todo parche que se aplique tiene
+un conjunto de cambios asociado, puede usar
+\hgcmdargs{log}{\emph{filename}} para ver qué conjuntos de cambios y
+parches afectaron un fichero.  Puede usar la orden \hgext{bisect} para
+hacer una búsqueda binaria sobre todos los conjuntos de cambios y
+parches aplicados para ver dónde se introdujo un fallo o dónde fue
+arreglado.  Puede usar la orden \hgcmd{annotate} para ver qué
+conjuntos de cambios o parches modificaron una línea particular de un
+fichero fuente. Y mucho más.
+
+\section{Entender los parches}
+\label{sec:mq:patch}
+
+Dado que MQ no esconde su naturaleza parche-céntrica, es muy útil para
+entender de qué se tratan los parches, y un poco acerca de las
+herramientas que trabajan con ellos.
+
+La orden de Unix tradicional \command{diff} compara dos ficheros, e
+imprime una lista de diferencias de sus líneas.  La orden
+\command{patch} entiende esas diferencias como \emph{modificaciones}
+para construir un fichero.  Vea en la figura~\ref{ex:mq:diff} un
+ejemplo sencillo de tales órdenes en acción.
+
+\begin{figure}[ht]
+  \interaction{mq.dodiff.diff}
+  \caption{Uso sencillo de las órdenes \command{diff} y \command{patch}}
+  \label{ex:mq:diff}
+\end{figure}
+
+El tipo de fichero que \command{diff} genera (y que \command{patch}
+toma como entrada) se llama un ``parche'' o un ``diff''; no hay
+diferencia entre un parche y un diff.  (Usaremos el término ``parche'',
+dado que es el que más comunmente se usa.)
+
+Un parche puede comenzar con un texto arbitrario; la orden \command{patch}
+ignora este texto, pero MQ lo usa como el mensaje de consignación
+cuando se crean conjuntos de cambios.  Para encontrar el inicio del
+contenido de un parche, la orden \command{patch} busca la primera
+línea que comience con la cadena ``\texttt{diff~-}''.
+
+MQ trabaja con diffs \emph{unificados} (\command{patch} acepta varios
+formatos de diff adicionales, pero MQ no).  Un diff unificado contiene
+dos clases de encabezados.  El \emph{encabezado de fichero} describe
+el fichero que se está modificando; contiene el nombre del fichero a
+modificar.  Cuando \command{patch} ve un nuevo encabezado de fichero,
+busca un fichero con ese nombre para modificarlo.
+
+Después del encabezaado vienen varios \emph{trozos}.  Cada trozo
+comienza con un encabezado; que identifica el rango de líneas del
+fichero que el trozo debe modificar.  Después del encabezado, un trozo
+comienza y termina con unas pocas líneas (usualmente tres) de texto del
+fichero que no han sido modificadas; las cuales llamamos el
+\emph{contexto} del trozo.  Si solamente hay una pequeña cantidad de
+contexto entre trozos sucesivos, \command{diff} no imprime un nuevo
+encabezado para el trozo, continua integrando los trozos, con unas
+líneas de contexto entre las modificaciones.
+
+Cada línea de contexto comienza con un caracter de espacio.  En el
+trozo, si una línea comienza con ``\texttt{-}'' significa ``elimine
+esta línea'', si la línea comienza con un ``\texttt{+}'' significa
+``inserte esta línea''.  Por ejemplo, una línea que se modifica se
+representa con una línea eliminada y una línea insertada.
+
+Retomaremos aspectos más sutiles acerca de parches posteriormente (en
+la sección~\ref{sec:mq:adv-patch}), pero en el momento usted ya
+debería tener suficiente información para usar MQ.
+
+\section{Comenzar a usar Colas de Mercurial}
+\label{sec:mq:start}
+
+Dado que MQ está implementado como una extensión, debe habilitarla
+explícitamente antes de comenzar a usarla.  (No necesita descargar
+nada; MQ viene con la distribución estándar de Mercurial.)  Para
+habilitar MQ, edite su fichero \tildefile{.hgrc}, y añada las líneas
+de la figura~\ref{ex:mq:config}.
+
+\begin{figure}[ht]
+  \begin{codesample4}
+    [extensions]
+    hgext.mq =
+  \end{codesample4}
+  \label{ex:mq:config}
+  \caption{Líneas a añadir en \tildefile{.hgrc} para habilitar la extensión MQ}
+\end{figure}
+
+Cuando la extensión esté habilitada, aparecerán varios comandos.  Para
+verificar que la extensión está trabajando, puede usar \hgcmd{help}
+para ver si la orden \hgxcmd{mq}{qinit} está disponible; vea un
+ejemplo en la figura~\ref{ex:mq:enabled}.
+
+\begin{figure}[ht]
+  \interaction{mq.qinit-help.help}
+  \caption{Cómo verificar que MQ está habilitado}
+  \label{ex:mq:enabled}
+\end{figure}
+
+Puede usar MQ en \emph{cualquier} repositorio de Mercurial, y sus
+comandos solamente operarán con tal repositorio.  Para comenzar, basta
+con preparar el repositorio con la orden \hgxcmd{mq}{qinit} (ver la
+figura~\ref{ex:mq:qinit}).  Esta orden crea un directorio vacío
+llamado \sdirname{.hg/patches}, donde MQ mantendrá sus metadatos. Como
+otras ordenes de Mercurial, la orden \hgxcmd{mq}{qinit} no imprime
+nada cuando es exitosa.
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qinit}
+  \caption{Preparar un repositorio para usar MQ}
+  \label{ex:mq:qinit}
+\end{figure}
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qnew}
+  \caption{Crear un nuevo parche}
+  \label{ex:mq:qnew}
+\end{figure}
+
+\subsection{Crear un nuevo parche}
+
+Para comenzar a trabajar en un nuevo parche use la orden
+\hgxcmd{mq}{qnew}. Esta orden recibe un argumento, el nombre del
+parche a crear.  MQ lo usará como el nombre del fichero en el
+directorio \sdirname{.hg/patches}, como puede apreciarlo en la
+figura~\ref{ex:mq:qnew}.
+
+También hay otros dos nuevos ficheros en el directorio
+\sdirname{.hg/patches}:  \sfilename{series} y \sfilename{status}.  El
+fichero \sfilename{series} lista todos los parches de los cuales MQ
+tiene noticia para este repositorio, con un parche por línea.
+Mercurial usa el fichero \sfilename{status} para mantener registros
+interns; da seguimiento a todos los parches que MQ ha \emph{aplicado}
+en el repositorio.
+
+\begin{note}
+  En ciertas ocasiones usted querrá editar el fichero
+  \sfilename{series} a mano; por ejemplo, cambiar el orden en que se
+  aplican ciertos parches.  A pesar de esto, es una mala idea editar
+  manualmente  el fichero \sfilename{status}, dado que es fácil
+  desorientar a MQ acerca de lo que está pasando.
+\end{note}
+
+Una vez que haya creado un nuevo parche, puede editar los ficheros en
+el directorio de trabajo, como lo haría usualmente.  Toda las órdenes
+que de a Mercurial, tales como \hgcmd{diff} y \hgcmd{annotate},
+trabajarán de la misma forma como lo han hecho antes.
+
+\subsection{Refrescar un parche}
+
+Cuando usted llega a un punto en el cual desea guardar su trabajo, use
+la orden \hgxcmd{mq}{qrefresh} (figura~\ref{ex:mq:qnew}) para
+actualizar el parche en el cual está trabajando.  Esta orden almacena
+los cambios que haya hecho al directorio actual de trabajo en su
+parche, y almacena el conjunto de cambios correspondiente que contiene
+los cambios.
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qrefresh}
+  \caption{Refrescar un parche}
+  \label{ex:mq:qrefresh}
+\end{figure}
+
+Puede ejecutar la orden \hgxcmd{mq}{qrefresh} tan seguido como quiera,
+y es una buena forma de ``colocar marcas'' a su trabajo.  Refresque su
+parche en momentos oportunos; intente un experimento; si el
+experimento no funciona, Use \hgcmd{revert} sobre sus modificaciones
+para volver al refresco anterior.
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qrefresh2}
+  \caption{Refrescar un parche muchas veces para acumular cambios}
+  \label{ex:mq:qrefresh2}
+\end{figure}
+
+\subsection{Aplicar un parche tras otro y dar seguimiento}
+
+Cuando haya terminado de trabajar en un parche, o necesite trabajar en
+otro, puede usar la orden \hgxcmd{mq}{qnew} para crear un nuevo
+parche.  Mercurial aplicará este parche sobre su parche anterior.
+Para un ejemplo, ver la figura~\ref{ex:mq:qnew2}.  Note que el parche
+contiene los cambios en nuestro parche anterior como parte de su
+contexto (lo verá más claramente en la salida de \hgcmd{annotate}).
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qnew2}
+  \caption{Aplicar un parche después del primero}
+  \label{ex:mq:qnew2}
+\end{figure}
+
+Hasta ahora, con excepción de \hgxcmd{mq}{qnew} y
+\hgxcmd{mq}{qrefresh}, hemos sido cuidadosos para aplicar únicamente
+órdenes usuaales de Mercurial.  De todas maneras, MQ ofrece muchos
+comandos que son más sencillos de usar cuando esté pensando acerca de
+parches, como se puede ver en la figura~\ref{ex:mq:qseries}:
+
+\begin{itemize}
+\item La orden \hgxcmd{mq}{qseries} lista cada parche del cual MQ
+  tiene noticia en este repositorio, desde el más antiguo hasta el más
+  nuevo (El último \emph{creado}).
+\item La orden \hgxcmd{mq}{qapplied} lista cada parche que MQ haya
+  \emph{aplicado} en este repositorio, de nuevo, desde el más antiguo
+  hasta el más nuevo (El aplicado más recientemente).
+\end{itemize}
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qseries}
+  \caption{Entender la pila de parches con \hgxcmd{mq}{qseries} y
+    \hgxcmd{mq}{qapplied}}
+  \label{ex:mq:qseries}
+\end{figure}
+
+\subsection{Manipular la pila de parches}
+
+La discusión previa indicó que debe haber una diferencia entre los
+parches ``conocidos'' y ``aplicados'', y efectivamente la hay.  MQ
+puede manejar un parche sin que este haya sido aplicado al
+repositorio.
+
+Un parche \emph{aplicado} tiene su correspondiente conjunto de cambios
+en el repositorio, y los efectos del parche y el conjunto de cambios
+son visibles en el directorio de trabajo.  Puede deshacer la
+aplicación de un parche con la orden \hgxcmd{mq}{qpop}.  MQ 
+\emph{sabe acerca de}, o maneja un parche sustraído, pero el parche ya
+no tendrá un conjunto de cambios correspondientes en el repositorio, y
+el directorio de trabajo no contendrá los cambios hechos por el
+parche.  La figura~\ref{fig:mq:stack} ilustra la diferencia entre
+parches aplicados y seguidos.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{mq-stack}
+  \caption{Parches aplicados y no aplicados en la pila de parches de MQ}
+  \label{fig:mq:stack}
+\end{figure}
+
+Puede reaplicar un parche no aplicado o sustraído con la orden
+\hgxcmd{mq}{qpush}.  Esto crea un nuevo conjunto de cambios
+correspondiente al parche, y los cambios del parche estarán presentes
+de nuevo en el directorio de trabajo.  Vea ejemplos de
+\hgxcmd{mq}{qpop} y \hgxcmd{mq}{qpush} en acción en la
+figura~\ref{ex:mq:qpop}.  Vea que hemos sustraído uno o dos parches,
+la salida de\hgxcmd{mq}{qseries} continúa igual, mientras que
+\hgxcmd{mq}{qapplied} ha  cambiado.
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qpop}
+  \caption{Modificar la pila de parches aplicados}
+  \label{ex:mq:qpop}
+\end{figure}
+
+\subsection{Introducir y sustraer muchos parches}
+
+Mientras que \hgxcmd{mq}{qpush} y \hgxcmd{mq}{qpop} operan sobre un
+único parche cada vez, puede introducir y sustraer varios parches de
+una vez.  La opción \hgxopt{mq}{qpush}{-a} de \hgxcmd{mq}{qpush}
+introduce todos los cambios que no hayan sido aplicados, mientras que
+la opción \hgxopt{mq}{qpop}{-a} de \hgxcmd{mq}{qpop} sustrae todos los
+cambios aplicados.  (Vea la sección~\ref{sec:mq:perf} más adelante
+en la cual se explican otras formas de de introducir y sustraer varios
+cambios.)
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.qpush-a}
+  \caption{Pushing all unapplied patches}
+  \label{ex:mq:qpush-a}
+\end{figure}
+
+\subsection{Medidas de seguridad y cómo saltarlas}
+
+Muchas órdenes MQ revisan el directorio de trabajo antes de hacer
+cualquier cosa, y fallan si encuentran alguna modificación.  Lo hacen
+para garantizar que usted no pierda cambio alguno de los que haya
+hecho, pero que no hayan sido incorporados en algún parche.  La
+figura~\ref{ex:mq:add} ilusta esto; la orden \hgxcmd{mq}{qnew} no
+creará un nuevo parche si hay cambios notorios, causados en este caso
+por aplicado la orden \hgcmd{add} a \filename{file3}.
+
+\begin{figure}[ht]
+  \interaction{mq.tutorial.add}
+  \caption{Crear un parche a la fuerza}
+  \label{ex:mq:add}
+\end{figure}
+
+Las órdenes que revisan el directorio actual cuentan con una opción
+``Se lo que estoy haciendo'', que siempre está nombrada como
+\option{-f}.  El significado exacto de \option{-f} depende de la
+orden.  Por ejemplo, \hgcmdargs{qnew}{\hgxopt{mq}{qnew}{-f}}
+incorporarán cualquier cambio notorio en el nuevo parche que crea pero
+\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-f}} revertirá las modificaciones a
+cualquier fichero que haya sido afectado por el parche que está siendo
+sustraído. ¡Asegúrese de leer la documentación de la opción \option{-f}
+de cada comando antes de usarla!
+
+\subsection{Trabajar con varios parches a la vez}
+
+La orden \hgxcmd{mq}{qrefresh} siempre refresca el \emph{último}
+parche aplicado.  Esto significa que usted puede suspender su trabajo
+en un parche (refrescándolo), sustraerlo o introducirlo para lograr
+que otro parche esté de último y trabajar en \emph{ese} parche por un
+rato.
+
+A continuación un ejemplo que ilustra cómo puede usar esta habilidad.
+Digamos que está desarrollando una nueva característica en dos
+parches.  El primero es un cambio en la parte fundamental de su
+programa, y el segundo--sobre el primero---cambia la interfaz de
+usuario para usar el código que ha añadido a la parte fundamental.  Si
+ve que hay un fallo en la parte fundamental mientras está trabajando
+en el parche de UI\ndt{Interfaz de Usuario, User Interface en inglés}, es fácil arreglar la parte fundamental.
+Simplemente use \hgxcmd{mq}{qrefresh} sobre el parche de la UI para
+guardar los cambios de su trabajo en progreso, y use \hgxcmd{mq}{qpop}
+para sacar sustraer el parche de la parte fundamental.  Arregla el
+fallo sobre la parte fundamental, aplique \hgxcmd{mq}{qrefresh} sobre
+el parche fundamental, y aplique \hgxcmd{mq}{qpush} sobre el parche de
+UI para continuar donde había quedado.
+
+\section{Más acerca de parches}
+\label{sec:mq:adv-patch}
+
+MQ usa la orden GNU \command{patch} para aplicar los parches, por lo
+tanto es útil conocer ciertos detalles de cómo trabaja
+\command{patch}, y también acerca de los parches.
+
+\subsection{La cantidad de franjas}
+
+Si ve el encabezado de un parche, notará que la ruta al fichero tiene
+un componente adicional al principio, que no está presente en la
+ruta. Esta es una traza de cómo generaba anteriormente los parches la
+gente (algunos aún lo hacen, pero es raro con las herramientas de
+control de revisiones del actuales).
+
+Alicia desempaquetaría un comprimido, editaría sus ficheros, y querría
+crear un parche.  Por lo tanto ella renombraría su directorio de
+trabajo, desempacaría el comprimido de nuevo (para lo cual necesitó el
+renombramiento), y usaría las opciones \cmdopt{diff}{-r} y
+\cmdopt{diff}{-N} de \command{diff} para generar recursivamente un
+parche entre el directorio original y el modificado.  El resultado
+sería que el nombre del directorio original estaría al principio de
+toda ruta en cada encabezado de fichero, y el nombre del directorio
+modificado estaría al frente de la porción derecha de la ruta del
+fichero.
+
+Como alguien que reciba un parche de Alicia en la red podría obtener
+dos directorios, uno original y el otro modificado con exactamente los
+mismos nombres, la orden \command{patch} tiene la opción
+\cmdopt{patch}{-p} que indica la cantidad de componentes de la ruta
+a eliminar cuando se vaya a aplicar el parche.  Este número se
+llama la \emph{cantidad de eliminaciones}.
+
+La opción con ``\texttt{-p1}'' significa ``elimine uno''.  Si
+\command{patch} ve un nombre de fichero \filename{foo/bar/baz} en el
+encabezado del fichero, eliminará \filename{foo} y tratará de parchar
+un fichero llamado \filename{bar/baz}.  (Hablando estrictamente, la
+cantidad de eliminaciones se refiere a la cantidad de \emph{separadores de
+ ruta} (y los componentes que vayan con ellos) a eliminar.  Si el
+contador es uno volverá \filename{foo/bar} en \filename{bar}, pero
+\filename{/foo/bar} (note la barra extra) en \filename{foo/bar}.)
+
+La cantidad a eliminar``estándar'' para parches es uno; casi todos los
+parches contienen un componente inicial de la ruta que necesita ser
+eliminado.  La orden \hgcmd{diff} de Mercurial genera nombres de ruta
+de esta forma, y la orden \hgcmd{import} y MQ esperan parches que
+tengan a uno como cuenta de eliminaciones.
+
+Si recibe un parche de alguien de quien desea adicionar adicionar a su
+cola de parches, y el parche necesita una cuenta de eliminación que no
+sea uno, no podrá aplicar \hgxcmd{mq}{qimport} en primera medida,
+porque \hgxcmd{mq}{qimport} no tiene todavía una opción \texttt{-p}
+option (ver~\bug{311}).  Lo mejor que puede hacer es aplicar
+\hgxcmd{mq}{qnew} por su cuenta, y después usar \cmdargs{patch}{-p\emph{N}}
+para aplicar tal parche, seguido de \hgcmd{addremove} para tener en
+cuenta cualquier fichero adicionado o eliminado por el parche, seguido
+de \hgxcmd{mq}{qrefresh}.  Esta complejidad puede ser innecesaria;
+consulte~\bug{311} para más información.
+
+\subsection{Estrategias para aplicar parches}
+
+Cuando \command{patch} aplica un trozo, intenta varias estrategias
+sucesivas que decrecen en precisión para intentar aplicarlo.  Esta
+técnica de pruebas y error aveces permite que un parche que fue
+generado contra una versión anterior de un fichero, sea aplicada sobre
+una versión más nueva del mismo.
+
+Primero \command{patch} intenta una correspondencia perfecta donde los
+números de línea, el contexto y el texto a modificar deben coincidir
+perfectamente.  Si no lo logra, intenta encontrar una correspondencia
+exacta del contexto, sin tener en cuenta el número de línea.  Si es
+exitoso, imprime una línea indicando que el trozo fue aplicado, pero a
+un \emph{corrimiento} del número de línea original.
+
+Si falla la correspondencia por contexto, \command{patch} elimina la
+primera y la última línea del contexto, e intenta una correspondencia
+\emph{reducida} del contexto.  Si el trozo con contexto reducido es
+exitoso, imprime un mensaje indicando que aplicó el trozo con un
+\emph{factor difuso} (el número después del factor difuso indica
+cuántas líneas de contexto \command{patch} tuvo que eliminar antes de
+aplicar el parche).
+
+Cuando ninguna de estas técnicas funciona, \command{patch} imprime un
+mensaje indicando que el trozo en cuestión se desechó.  Almacena los
+trozos desechados (también llamados ``descartados'') en un fichero con
+el mismo nombre, y la extensión \sfilename{.rej} añadida.  También
+almacena una copia igual al fichero original con la extensión
+\sfilename{.orig}; la copia del fichero sin extensión contendrá
+cualquier cambio hecho por los trozos que \emph{sí} se aplicaron sin
+problema.  Si usted tiene un parche que modifica \filename{foo} con
+seis trozos, y uno de ellos falla al aplicarse, tendrá : un fichero
+original \filename{foo.orig}, un fichero \filename{foo.rej} que
+contiene el trozo, y \filename{foo}, que contiene los cambios que se
+aplicaron por los cinco trozos exitosos.
+
+\subsection{Algunos detalles de la representación de parches}
+
+Hay ciertas cosas útiles por saber acerca de cómo trabaja
+\command{patch} con los ficheros:
+\begin{itemize}
+\item Debería ser obvio que \command{patch} no puede manipular
+  ficheros binarios.
+\item No se preocupa por el bit ejecutable; crea ficheros nuevos en
+  modo lectura, pero no ejecutable.
+\item \command{patch} intenta eliminar un fichero como una diferencia
+  entre el fichero a eliminar y un fichero vacío.  Y por lo tanto su
+  idea de ``Borré este fichero'' debería pensarse como ``toda línea de
+  este fichero fue eliminada'' en un parche.
+\item Trata la adición de un fichero como un diff entre un fichero
+  vacío y el fichero a ser adicionado.  Por lo tanto en un parche su
+  idea de ``Añadí este fichero'' se vería como ``toda línea de este
+  fichero fue añadida''.
+\item Trata el renombramiento de un fichero como la eliminación del
+  nombre anterior y la adición del nuevo nombre.  Esto significa que
+  los ficheros renombrados dejan un rastro grande en los parches.
+  (Tenga en cuenta que Mercurial no trata de inferir cuando los
+  ficheros han sido renombrados o copiados en un parche en este
+  momento.)
+\item \command{patch} no puede representar ficheros vacíos, por lo
+  tanto no puede usar un parche para representar la noción ``Añadí
+  este fichero vacío al árbol''.
+\end{itemize}
+\subsection{Cuidado con los difusos}
+
+Cuando aplique un trozo con un corrimiento, o con un factor difuso,
+aveces será taotalmente exitoso, tales técnicas inexactas dejan
+claramente la posibilidad de corromper el fichero parchado.  Los casos
+más típicos involucran aplicar un parche dos veces o en un sitio
+incorrecto del fichero. Si \command{patch} o \hgxcmd{mq}{qpush} llegan
+a mencionar un corrimiento o un factor difuso, debería asegurarse que
+los ficheros modificados estén correctos después del suceso.
+
+Casi siempre es buena idea refrescar un parche que fue aplicado con un
+corrimiento o un factor difuso; refrescar el parche genera nueva
+información de contexto que permitirá aplicarlo limpiamente.  Digo
+``casi siempre,'' no ``siempre'', puesto que en ciertas ocasiones
+refrescar un parche lo hará fallar frente a una revisión diferente del
+fichero.  En algunos casos, como por ejemplo, cuando usted está
+manteniendo un parche que debe estar encima de múltiples revisiones de
+un árbol de fuentes, es aceptable tener un parche aplicado algo
+difuso, siempre que haya verificado los resultados del proceso de
+parchar.
+
+\subsection{Manejo de descartes}
+
+Si \hgxcmd{mq}{qpush} falla al aplicar un parche, mostrará un texto de
+error y saldrá.  Si ha dejado ficheros \sfilename{.rej}, es mejor
+arreglar los trozos descartados antes de introducir parches
+adicionales o hacer cualquier otra cosa.
+
+Si su parche \emph{solía} aplicarse limpiamente, y ya no lo hace
+porque ha cambiado código subyacente en el cual se basa su parche, las
+Colas de Mercurial pueden ayudar; consulte la sección~\ref{sec:mq:merge}.
+
+Desafortunadamente, no hay grandes técnicas para tratar los trozos
+descartados.  Casi siempre deberá consultar el fichero
+\sfilename{.rej} y editar el fichero objetivo, aplicando los trozos
+descartados a mano.
+
+Si es aventurero, Neil Brown, un hacker del núcleo Linux, escribió una
+herramienta llamada \command{wiggle}~\cite{web:wiggle}, que es más
+vigorosa que \command{patch} en su intento de hacer que se aplique un
+parche.
+
+Otro hacker del nucleo Linux, Chris Mason (el autor de las Colas de
+Mercurial), escribió una herramienta similar llamada
+\command{mpatch}~\cite{web:mpatch}, que sigue una aproximación
+sencilla para automatizar la aplicación de trozos descartados por
+\command{patch}.  La orden \command{mpatch} puede ayudar con cuatro
+razones comunes por las cuales un parche ha sido descartado:
+
+\begin{itemize}
+\item El contexto en la mitad de un trozo ha cambiado.
+\item Un trozo ha perdido cierto contexto al principio o al final.
+\item Un trozo largo podría aplicarse mejor---por completo o una
+  parte---si estaba cortado en trozos más pequeños.
+\item Un trozo remueve líneas con contenido ligeramente diferente que
+  aquellas que están presentes en el fichero.
+\end{itemize}
+
+Si usted usa \command{wiggle} o \command{mpatch}, debería ser
+doblemente cuidadoso al revisar sus resultados cuando haya terminado.
+De hecho, \command{mpatch} refuerza este método de revisar por partida
+doble su salida, dejándolo a usted en un programa de fusión cuando la
+herramienta haya terminado su trabajo, de tal forma que usted pueda
+verificar lo que ha hecho y pueda terminar de aplicar cualquier fusión
+faltante.
+
+\section{maximizar el rendimiento de MQ}
+\label{sec:mq:perf}
+
+MQ es muy eficiente al tratar con una gran cantidad de parches.  Corrí
+unos experimentos de desempeño a mediados del 2006 para una charla que
+dí en la conferencia EuroPython 2006~\cite{web:europython}.  Empleé la
+serie de parches para el núcleo Linux 2.6.17-mm1, que contaba con 1.738
+parches.  Los apliqué sobre un repositorio del núcleo de Linux con
+todas las 27.472 revisiones entre 2.6.12-rc2 y 2.6.17.
+
+En mi portátil antiguo y lento, logré aplicar 
+\hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} a los 1.738 parches en 3.5
+minutos, y \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} en 30 segundos.
+(En un portátil más nuevo, el tiempo para introducir todos los
+parches, se logró en menos de dos minutos.)  Apliqué
+\hgxcmd{mq}{qrefresh} sobre uno de los parches más grandes (que hizo
+22.779 líneas de cambios en 287 ficheros) en 6,6 segundos.
+
+Claramente, MQ funciona adecuadamente en árboles grandes, y además hay
+unos trucos que pueden emplearse para obtener el máximo desempeño.
+
+En primer lugar, trate de hacer ``en lote'' las operaciones.  Cada vez
+que ejecute \hgxcmd{mq}{qpush} o \hgxcmd{mq}{qpop}, tales órdenes
+revisan el directorio de trabajo para asegurarse de que usted no ha
+hecho cambios y ha olvidado ejecutar \hgxcmd{mq}{qrefresh}.  En un
+árbol pequeño, el tiempo de esta revisión puede ser mínimo,  Pero en
+un árbol mediano (con decenas de miles de ficheros), puede tomar un
+segundo o más.
+
+Las órdenes \hgxcmd{mq}{qpush} y \hgxcmd{mq}{qpop} le permiten
+introducir o sustraer varios parches en una operación.  Puede
+identificar el ``parche destino'' que desee.  Cuando aplique
+\hgxcmd{mq}{qpush} con un destino, introducirá tantos parches como sea
+necesario hasta que el especificado esté en el tope de la pila.
+Cuando emplee \hgxcmd{mq}{qpop} con un destino, MQ sustraerá parches
+hasta que el parche destino esté en el tope.
+
+Puede identificar un parche destino con el nombre del parche o con el
+número.  Si se refiere al número, los parches se contarán desde cero;
+esto significa que el primer parche es cero, el segundo es uno y así
+sucesivamente.
+
+\section{Actualiar los parches cuando el código cambia}
+\label{sec:mq:merge}
+
+Es común contar con una pila de parches sobre un repositorio que usted
+no modifica directamente.  Si está trabajando en cambios de código de
+otros, o en una característica que tarda bastante en desarrollarse
+comparada con la tasa de cambio del código sobre la cual se está
+trabajando, necesitará sincronizarse con el código, y ajustar
+cualquier trozo en sus parches que ya no estén al día.  A esto se le
+llama hacer \emph{rebase} a su serie de parches.
+
+La vía más sencilla de hacerlo es con \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}}
+sobre sus parches, después hacer \hgcmd{pull} de los cambios en el
+repositorio, y finalmente hacer
+\hgcmdargs{qpush}{\hgxopt{mq}{qpop}{-a}} con sus parches de nuevo.  MQ
+dejará de de introducir parches siempre que llegue a un parche que no se pueda
+aplicar debido a un conflicto, permitiéndole a usted arreglarlo,
+aplicar \hgxcmd{mq}{qrefresh} al parche afectado y continuar
+introduciendo hasta que haya arreglado la pila completa.
+
+Esta aproximación es sencilla y funciona bien si no espera cambios en
+el código original que afecte en gran medida los parches que usted
+esté aplicando. Si su pila de parches toca código que es modificado
+frecuentemente o de forma invasiva sobre el código subyacente,
+arreglar trozos manualmente se vuelve desgastante.
+
+Es posible automatizar de forma parcial el proceso de rebase.  Si sus
+parches se aplican limpiamente sobre algunas revisiones del
+repositorio subyacente, MQ puede usar esta información para ayudarle a
+a resolver conflictos entre sus parches y una revisión distinta.
+
+El proceso resulta un poco complejo:
+\begin{enumerate}
+\item Para comenzar, haga \hgcmdargs{qpush}{-a} sobre todos los
+  parches que usted sepa se aplican limpiamente.
+\item Guarde una copia de seguridad de su directorio de parches  con
+  \hgcmdargs{qsave}{\hgxopt{mq}{qsave}{-e} \hgxopt{mq}{qsave}{-c}}.
+  Esto imprime el nombre del directorio en el cual se han guardado los
+  parches.  Guardará los parches en un directorio llamado
+  \sdirname{.hg/patches.\emph{N}}, donde \texttt{\emph{N}} es un
+  entero pequeño.  También consigna un ``conjunto de cambios de
+  seguridad'' sobre sus parches aplicados; esto es para mantener el
+  histórico, y guarda los estados de los ficheros  \sfilename{series}
+  y \sfilename{status}.
+\item Use \hgcmd{pull} para traer los nuevos cambios en el repositorio
+  subyacente. (No ejecute \hgcmdargs{pull}{-u}; vea más adelante por qué.)
+\item Actualice a la nueva revisión punta con 
+  \hgcmdargs{update}{\hgopt{update}{-C}} para sobreescribir los
+  parches que haya introducido.
+\item Fusione todos los parches con \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}
+    \hgxopt{mq}{qpush}{-a}}.  La opción \hgxopt{mq}{qpush}{-m} de \hgxcmd{mq}{qpush}
+  le indica a MQ que haga una fusión que involucra tres fuentes si el
+  parche falla al aplicarse.
+\end{enumerate}
+
+Durante el \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}}, cada parche en
+el fichero \sfilename{series} se aplica normalmente.  Si un parche se
+aplica difusamente o se niea a aplicarse, MQ consulta la cola que
+usted guardó con \hgxcmd{mq}{qsave}, y aplica una fusión de tres con
+el correspondiente conjunto de cambios.  Esta fusión usa la maquinaria
+de Mercurial, por lo tanto puede mostrar una herramienta de fusión GUI
+para ayudarle a resolver los problemas.
+
+Cuando termine de resolver los efectos de un parche, MQ refrescará su
+parche basado en el resultado de la fusión.
+
+Al final de este proceso, su repositorio tendrá una cabeza extra de la
+antigua cola de parches, y una copia de la cola de parches anterio
+estará en \sdirname{.hg/patches.\emph{N}}. Puede eliminar la cabeza
+extra con \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a} \hgxopt{mq}{qpop}{-n} patches.\emph{N}}
+o \hgcmd{strip}.  Puede eliminar \sdirname{.hg/patches.\emph{N}} una
+vez que esté seguro de que no lo necesita más como copia de seguridad.
+
+\section{Identificar parches}
+
+Las órdenes de MQ le permiten trabajar refiriéndose al nombre del
+parche o al número.  Es obvio hacerlo por el nombre; por ejemplo se
+pasa el nombre \filename{foo.patch} a \hgxcmd{mq}{qpush}, que
+introducirá los parches hasta que \filename{foo.patch} se aplique.  
+
+Para hacerlo más corto, puede referirse a un parche con un nombre y un
+corrimiento de número; por ejemplo,  \texttt{foo.patch-2} significa
+``dos parches antes de \texttt{foo.patch}'', mientras que
+\texttt{bar.patch+4} significa ``cuatro parches después de \texttt{bar.patch}''.
+
+Referirse a un parche por su índice no es muy diferente.  El primer
+parche que se imprime en la salida de \hgxcmd{mq}{qseries} es el
+parche cero (si, es el primero en los sistemas que comienzan su conteo
+en cero); el segundo parche es uno y así sucesivamente.
+
+MQ facilita el trabajo cuando está usando órdenes normales de
+Mercurial.  Cada comando que acepte Identificadores de conjuntos de
+cambios también aceptará el nombre de un parche aplicado.  MQ aumenta
+las etiquetas normalmente en el repositorio con un distintivo para cada
+parche aplicado.  Adicionalmente, las etiquetas especiales \index{tags!special tag
+  names!\texttt{qbase}}\texttt{qbase} y \index{tags!special tag
+  names!\texttt{qtip}}\texttt{qtip} identifican los parches
+``primero'' y último, respectivamente.
+
+Junto con las capacidades de Mercurial para etiquetar, estas adiciones
+hacen que trabajar con parches sea muy sencillo.
+\begin{itemize}
+\item ¿Desea enviar una bomba de parches a una lista de correo con los
+  últimos cambios que ha hecho?
+  \begin{codesample4}
+    hg email qbase:qtip
+  \end{codesample4}
+  (¿No sabe qué es una ``bomba de parches''?  Consulte la
+  sección~\ref{sec:hgext:patchbomb}.)
+\item ¿Desea ver todos los parches desde que se aplicó
+  \texttt{foo.patch} sobre los ficheros de un subdirectorio en su
+  árbol?
+  \begin{codesample4}
+    hg log -r foo.patch:qtip \emph{subdir}
+  \end{codesample4}
+\end{itemize}
+
+Dado que MQ nombra los parches disponibles al resto de Mercurial con
+su maquinaria de etiquetas interna, usted no necesita teclear el
+nombre completo de un parche cuando desea identificarlo por su nombre.
+
+\begin{figure}[ht]
+  \interaction{mq.id.output}
+  \caption{Uso de las características de etiquetamiento al trabajar
+    con MQ}
+  \label{ex:mq:id}
+\end{figure}
+
+Otra consecuencia deseable al representar los nombres de parches como
+etiquetas es que cuando ejecute la orden \hgcmd{log}, desplegará el
+nombre del parche como una etiqueta, usualmente con la salida normal.
+Esto facilita distinguir visualmente los parches aplicados de las
+revisiones ``normales''.  La figura~\ref{ex:mq:id} muestra algunos
+comandos usuales de Mercurial al trabajar con parches.
+
+\section{Otra información útil}
+
+Hay una cantidad de aspectos que hacen que el uso de MQ no representen
+secciones en sí mismas, pero de los cuales es bueno estar
+enterado. Los presentamos en aquí:
+
+\begin{itemize}
+\item Usualmente cuando hace \hgxcmd{mq}{qpop} a un parche y vuelve a
+  hacerle \hgxcmd{mq}{qpush}, el conjunto de cambios que representa el
+  parche después de introducir/sustraer tendrá una  \emph{identidad
+    distinta} que aquella que representaba el conjunto de cambios
+  anteriormente. Consulte la  secctión~\ref{sec:mqref:cmd:qpush} para
+  obtener información del por qué de esto.
+\item No es una buena idea aplicar \hgcmd{merge} de cambios de otra
+  rama con un conjunto de cambios de parches, por lo menos si desea
+  mantener la ``información de parches'' de ese conjunto de cambios y
+  los conjuntos de cambios que se encuentran por debajo en la pila de
+  parches.  Si intenta hacerlo, parecerá que ha sido exitoso, pero MQ
+  se confundirá.
+\end{itemize}
+
+\section{Administrar parches en un repositorio}
+\label{sec:mq:repo}
+
+Dado que el directorio \sdirname{.hg/patches} de MQ reside fuera del
+repositorio de trabajo de Mercurial, el repositorio ``subyacente'' de
+Mercurial no sabe nada acerca de la administración o presencia de
+parches.
+
+Esto presenta la interesante posibilidad de administrar los contenidos
+del directorio de parches como un repositorio de Mercurial por su
+cuenta.  Puede ser una forma útil de trabajar.  Por ejemplo, puede
+trabajar en un parche por un rato, hacerle \hgxcmd{mq}{qrefresh} y
+después hacer \hgcmd{commit} al estado actual del parche.  Esto le
+permite ``devolverse'' a esa versión del parche posteriormente.
+
+Puede también compartir diferentes versiones de la misma pila de
+parches entre varios repositorios subyacentes.  Uso esto cuando estoy
+desarrollando una característica del núcleo Linux.  Tengo una copia
+original de las fuentes del núcleo para varias arquitecturas, y cloné
+un rpositorio en cada una que contiene los parches en los cuales
+estoy trabajando.  Cuando quiero probar un cambio en una arquitectura
+diferente, introduzco mis parches actuales al repositorio de parches
+asociado con el árbol del kernel, sustraigo e introduzco todos mis
+parches, armo y pruebo el núcleo.
+
+Llevar los parches en un repositorio permite que varios
+desarrolladores puedan trabajar en la misma serie de parches sin
+sobreponerse, todo sobre la fuente base subyacente que pueden o no
+controlar.
+
+\subsection{Soporte de MQ para repositorios de parches}
+
+MQ le ayuda a trabajar con el directorio \sdirname{.hg/patches} como
+un repositorio; cuando usted prepara un repositorio para trabajar con
+parches usando \hgxcmd{mq}{qinit}, puede pasarle la opción
+\hgxopt{mq}{qinit}{-c} para que se cree el directorio
+\sdirname{.hg/patches} como un repositorio de Mercurial.
+
+\begin{note}
+  Si olvida usar la opción \hgxopt{mq}{qinit}{-c} option, puede ir al
+  directorio \sdirname{.hg/patches} en cualquier momento y ejecutar
+  \hgcmd{init}.  No olvide añadir una entrada en el fichero
+  \sfilename{status} del fichero \sfilename{.hgignore}, a pesar de que
+  (\hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} hace estodo de forma
+  automática para usted); usted \emph{seguro} no quiere administrar el
+  fichero \sfilename{status}.
+\end{note}
+
+MQ nota convenientemente que el directorio \dirname{.hg/patches}
+es un repositorio, hará \hgcmd{add} automáticamente a cada parche que
+usted cree e importe.
+
+MQ provee una orden corta, \hgxcmd{mq}{qcommit}, que ejecuta
+\hgcmd{commit} en el directorio \sdirname{.hg/patches}.  Lo que ahorra
+tecleo recurrente.
+
+Finalmente, para administrar convenientemente el directorio de
+parches, puede definir el alias \command{mq} en sistemas Unix.  Por
+ejemplo, en sistemas Linux con el intérprete \command{bash}, puede
+incluir el siguiente recorte de código\ndt{snippet} en su fichero
+\tildefile{.bashrc}.
+
+\begin{codesample2}
+  alias mq=`hg -R \$(hg root)/.hg/patches'
+\end{codesample2}
+
+Puede aplicar las órdenes de la forma \cmdargs{mq}{pull} al
+repositorio principal.
+
+\subsection{Detalles a tener en cuenta}
+
+El soporte de MQ para trabajar con un repositorio de parches es
+limitado en ciertos aspectos:
+
+MQ no puede detectar automáticamente los cambios que haga al
+directorio de parches.  Si aplica \hgcmd{pull}, edita manualmente, o
+hace \hgcmd{update} a los parches o el fichero \sfilename{series},
+tendrá que aplicar \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} y después
+\hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} en el repositorio subyacente
+para que los cambios se reflejen allí.  Si olvida hacerlo, puede
+confundir a MQ en cuanto a qué parches se han aplicado.
+
+\section{Otras herramientas para trabajar con parches}
+\label{sec:mq:tools}
+
+Cuando haya trabajado por cierto tiempo con parches, deseará
+herramientas que le ayuden a entender y manipular los parches con los
+que esté tratando.
+
+La orden \command{diffstat}~\cite{web:diffstat} genera un histograma
+de modificaciones hechas a cada fichero en un parche.  Provee una
+interesante forma de ``dar un vistazo'' al parche---qué ficheros
+afecta, y cuántos cambios introduce a cada fichero y en total.  (Me ha
+parecido interesante usar la opción \cmdopt{diffstat}{-p} de
+\command{diffstat}, puesto que de otra forma intentará hacer cosas
+inteligentes con prefijos de ficheros que terminan confundiéndome.)
+
+\begin{figure}[ht]
+  \interaction{mq.tools.tools}
+  \caption{Las órdenes \command{diffstat}, \command{filterdiff}, y \command{lsdiff}}
+  \label{ex:mq:tools}
+\end{figure}
+
+El paquete \package{patchutils}~\cite{web:patchutils} es
+invaluable. Provee un conjunto de pequeñas utilidades que siguen la
+``filosofía Unix''; cada una hace una cosa muy bien hecha a un
+parche. La orden \package{patchutils} que más uso es
+\command{filterdiff}, que extrae subconjuntos de un fichero de
+parche.  Por ejemplo, dado un parche que modifica centenas de ficheros
+en docenas de directorios, una única invocación de
+\command{filterdiff} puede generear un parche más pequeño que
+solamente toca aquellos ficheros con un patrón.  Puede ver otro
+ejemplo en la sección~\ref{mq-collab:tips:interdiff}.
+
+\section{Buenas prácticas de trabajo con parches}
+
+En caso de que esté trabajando en una serie de parches para enviar a
+un proyecto de software libre o de fuentes abiertas, o en una serie
+que desea tratar como un conjunto de cambios regular, cuando haya
+terminado, puede usar técnicas sencillas para mantener su trabajo bien
+organizado.
+
+De nombres descriptivos a sus parches.  Un buen nombre para un parche
+podría ser \filename{rework-device-alloc.patch}, porque da de forma
+inmediata una pista del propósito del parche. Los nombres largos no
+deben ser un problema; no los estará tecleando repetidamente, pero
+\emph{estará} ejecutando regularmente órdenes como
+\hgxcmd{mq}{qapplied} y \hgxcmd{mq}{qtop}.  Los nombres adecuados son
+especialmente importantes cuando tiene bastantes parches con los
+cuales trabajar, o si está trabajando en diferentes tareas y sus
+parches toman solamente una porción de su atención.
+
+Tenga en cuenta en qué parche está trabajando.  Use la orden \hgxcmd{mq}{qtop}
+para dar un vistazo al texto de sus parches frecuentemente---por
+ejemplo, use \hgcmdargs{tip}{\hgopt{tip}{-p}})---para asegurarse en
+dónde está ubicado.  En distintas oportunidades me sucedió que apliqué
+\hgxcmd{mq}{qrefresh} a un parche distinto al que deseaba hacerlo, y
+usualmente es complejo migrar los cambios al parche correcto después
+de haberlo hecho mal.
+
+Por este motivo, vale la pena invertir ese poco tiempo para aprender
+cómo usar otras herramientas que describí en la
+sección~\ref{sec:mq:tools}, particularmente \command{diffstat} y
+\command{filterdiff}.  La primera le dará una idea de qué cambios está
+haciendo su parche, mientras que la segunda permite seleccionar trozos
+de un parche para colocarlos en otro.
+
+\section{Recetas de MQ}
+
+\subsection{Administrar parches ``triviales''}
+
+Puesto que colocar ficheros en un repositorio de Mercurial es tan
+sencillo, tiene bastante sentido administrar parches de esta forma
+incluso si desea hacer algunos cambios al paquete de ficheros que
+descargó.
+
+Para comenzar a descargar y desempaqueter un paquete de ficheros, y
+volverlo en un repositorio de Mercurial:
+\interaction{mq.tarball.download}
+
+Continue creando una pila de parches y haga sus cambios.
+\interaction{mq.tarball.qinit}
+
+Digamos que pasan unas semanas o meses, y el autor del paquete libera
+una nueva versión.  Primero se traen sus cambios al repositorio.
+\interaction{mq.tarball.newsource}
+La porción que comienza con \hgcmd{locate} mostrada más arriba, borra
+todos los ficheros en el directorio de trabajo, así que la opción
+\hgopt{commit}{--addremove} de \hgcmd{commit} puede indicar qué
+ficheros se han eliminado en la nueva versión del árbol de fuentes.
+
+Finalmente, puede aplicar sus parches encima del nuevo árbol de fuentes
+\interaction{mq.tarball.repush}
+
+\subsection{Combinar parches completos}
+\label{sec:mq:combine}
+
+MQ provee la orden \hgxcmd{mq}{qfold} que le permite combinar parches
+enteros.  Se ``integran''\ndt{fold} los parches que usted nombre, en
+el orden que especifique, en el último parche aplicado, y concatena
+sus descripciones al final de su descripción.  Deberá sustraer los
+cambios para poder integrarlos.
+
+El orden en el que integre los parches importa.  Si el parche
+últimamente aplicado es \texttt{foo}, e integra \hgxcmd{mq}{qfold} \texttt{bar} y
+\texttt{quux} en él, terminará con un parche que tiene el mismo efecto
+que si hubiera aplicado primero \texttt{foo}, y después \texttt{bar},
+seguido de \texttt{quux}.
+
+\subsection{Fusionar una porción de un parche dentro de otro}
+
+Fusionar \emph{partes} de un parche dentro de otro es más complejo que
+combinar completamente dos parches.
+
+Si desea mover cambios de ficheros completos, puede usar las opciones
+\command{filterdiff}'s \cmdopt{filterdiff}{-i} y
+\cmdopt{filterdiff}{-x} para elegir las modificaciones remover de un
+parche, concatenar su salida al final del parche donde desea
+fusionarlo.  Usualmente no necesitará modificar el parche del cuál ha
+fusionado los cambios.  En cambio, MQ reportará que hay unos trozos
+que se han desechado cuando usted aplique \hgxcmd{mq}{qpush} (de los
+trozos que haya movido al otro parche), y puede sencillamente aplicar
+\hgxcmd{mq}{qrefresh} para eliminar los trozos replicados.
+
+Si tiene un parche que tiene varios trozos que modifican un fichero, y
+desea mover solamente unos de ellos, el trabajo es un poco más
+enredado, pero puede automatizarlo parcialmente.  Use
+\cmdargs{lsdiff}{-nvv} para imprimir algunos metadatos del parche.
+\interaction{mq.tools.lsdiff}
+
+Esta orden imprime tres clases diferentes de números:
+\begin{itemize}
+\item (en la primera columna) un \emph{número de fichero} para
+  identificar cada fichero modificado en el parche;
+\item (En la siguiente línea, indentado) el número de línea dentro de
+  un fichero modificado donde comienza el trozo; y
+\item (en la misma línea) un \emph{número de trozo} que identifica el
+  trozo.
+\end{itemize}
+
+Tendrá que hacer una inspección visual, y leer el parche para
+identificar los números de fichero y trozo que desea, pero puede pasar
+posteriormente a las opciones \cmdopt{filterdiff}{--files} y 
+\cmdopt{filterdiff}{--hunks} de \command{filterdiff}, para seleccionar
+exactamente el fichero y el trozo que desea extraer.
+
+Cuando tenga el trozo, puede concatenarlo al final de su parche
+objetivo y continuar como en la sección~\ref{sec:mq:combine}.
+
+\section{Diferencias entre quilt y MQ}
+
+Si le es familiar quilt, MQ provee un conjunto similar de órdenes. Hay
+algunas diferencias en cómo funcionan.
+
+Debe haber notado que la mayoría de comandos de quilt tienen su
+contraparte en MQ, que simplemente comienzan con ``\texttt{q}''.  Las
+excepciones son las órdenes \texttt{add} y \texttt{remove} de quilt,
+que realmente son las órdenes \hgcmd{add} y \hgcmd{remove} de
+Mercurial.  No hay un equivalente en MQ para la orden
+\texttt{edit} de quilt.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
Binary file es/note.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/preface.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,74 @@
+\chapter*{Prefacio}
+\addcontentsline{toc}{chapter}{Prefacio}
+\label{chap:preface}
+
+El control distribuido de revisiones es un territorio relativamente 
+nuevo, y ha crecido hasta ahora 
+% TODO el original dice "due to", que sería "debido", pero creo que "gracias
+% a" queda mejor 
+gracias a  a la voluntad que tiene la gente de salir y explorar
+territorios desconocidos.
+% TODO revisar la frase anterior. me tomé muchas licencias para
+% traducirla
+
+Estoy escribiendo este libro acerca de control de revisiones
+distribuido porque creo que es un tema importante que merece una guía
+de campo. Escogí escribir acerca de Mercurial porque es la herramienta
+%TODO puse explorar en vez de aprender, you be the judge dear reviewer ;)
+más fácil para explorar el terreno, y sin embargo escala a las
+demandas de retadores ambientes reales donde muchas otras herramientas
+de control de revisiones fallan.
+
+\section{Este libro es un trabajo en progreso}
+Estoy liberando este libro mientras lo sigo escribiendo, con la
+esperanza de que pueda ser útil a otros. También espero que los
+lectores contribuirán como consideren adecuado.
+
+\section{Acerca de los ejemplos en este libro}
+Este libro toma un enfoque inusual hacia las muestras de código. Cada
+ejemplo está ``en directo''---cada uno es realmente el resultado de un
+% TODO shell script
+script de shell que ejecuta los comandos de Mercurial que usted ve.
+Cada vez que una copia del libro es construida desde su código fuente,
+% TODO scripts
+todos los scripts de ejemplo son ejecutados automáticamente, y sus
+resultados actuales son comparados contra los resultados esperados.
+
+La ventaja de este enfoque es que los ejemplos siempre son precisos;
+ellos describen \emph{exactamente} el comportamiento de la versión de
+Mercurial que es mencionada en la portada del libro. Si yo actualizo
+la versión de Mercurial que estoy documentando, y la salida de algún
+comando cambia, la construcción falla.
+
+Hay una pequeña desventaja de este enfoque, que las fechas y horas que
+usted verá en los ejemplos tienden a estar ``aplastadas'' juntas de una
+forma que no sería posible si los mismos comandos fueran escritos por
+un humano. Donde un humano puede emitir no más de un comando cada
+pocos segundos, con cualquier marca de tiempo resultante
+correspondientemente separada, mis scripts automatizados de ejemplos
+ejecutan muchos comandos en un segundo.
+
+% TODO commit
+Como un ejemplo de esto, varios commits consecutivos en un ejemplo
+pueden aparecer como habiendo ocurrido durante el mismo segundo. Usted
+puede ver esto en el ejemplo \hgext{bisect} en la
+sección~\ref{sec:undo:bisect}, por ejemplo.
+
+Así que cuando usted lea los ejemplos, no le dé mucha importancia a
+las fechas o horas que vea en las salidas de los comandos. Pero
+\emph{tenga} confianza en que el comportamiento que está viendo es
+consistente y reproducible.
+
+\section{Colofón---este libro es Libre}
+Este libro está licenciado bajo la Licencia de Publicación Abierta, y
+es producido en su totalidad usando herramientas de Software Libre. Es
+compuesto con \LaTeX{}; las ilustraciones son dibujadas y generadas
+con \href{http://www.inkscape.org/}{Inkscape}.
+
+El código fuente completo para este libro es publicado como un
+repositorio Mercurial, en \url{http://hg.serpentine.com/mercurial/book}.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/revlog.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,1164 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docbase="/home/bos/hg/hgbook/en"
+   sodipodi:docname="revlog.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective2726" />
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path4852"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <linearGradient
+       id="linearGradient3092">
+      <stop
+         style="stop-color:#44436f;stop-opacity:1;"
+         offset="0"
+         id="stop3094" />
+      <stop
+         style="stop-color:#abade5;stop-opacity:1;"
+         offset="1"
+         id="stop3096" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient3118"
+       gradientUnits="userSpaceOnUse"
+       x1="176.16635"
+       y1="405.21934"
+       x2="417.11935"
+       y2="405.21934" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient3120"
+       gradientUnits="userSpaceOnUse"
+       x1="176.16635"
+       y1="405.21934"
+       x2="417.11935"
+       y2="405.21934" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient3129"
+       gradientUnits="userSpaceOnUse"
+       x1="176.16635"
+       y1="405.21934"
+       x2="417.11935"
+       y2="405.21934"
+       gradientTransform="translate(-0.928574,-1.428574)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient3133"
+       gradientUnits="userSpaceOnUse"
+       x1="176.16635"
+       y1="405.21934"
+       x2="417.11935"
+       y2="405.21934"
+       gradientTransform="translate(-0.928574,-1.428574)" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient3708"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.423343,0,0,0.423343,138.874,-67.01732)"
+       x1="175.23776"
+       y1="509.98154"
+       x2="416.29077"
+       y2="297.49997" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient5164"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.423343,0,0,0.423343,198.249,247.4358)"
+       x1="175.23776"
+       y1="509.98154"
+       x2="416.29077"
+       y2="297.49997" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient5584"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.423343,0,0,0.423343,143.9081,371.2915)"
+       x1="175.23776"
+       y1="509.98154"
+       x2="416.29077"
+       y2="297.49997" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient5784"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
+       x1="175.23776"
+       y1="509.98154"
+       x2="416.29077"
+       y2="297.49997" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient5786"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.423343,0,0,0.423343,198.249,152.137)"
+       x1="175.23776"
+       y1="509.98154"
+       x2="416.29077"
+       y2="297.49997" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient5895"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.423343,0,0,0.423343,198.0215,261.7142)"
+       x1="175.23776"
+       y1="509.98154"
+       x2="416.29077"
+       y2="297.49997" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3092"
+       id="linearGradient5958"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.423343,0,0,0.423343,137.1978,42.55987)"
+       x1="175.23776"
+       y1="509.98154"
+       x2="416.29077"
+       y2="297.49997" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.8101934"
+     inkscape:cx="199.78816"
+     inkscape:cy="863.27363"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="29"
+     inkscape:window-y="79"
+     inkscape:connector-spacing="11"
+     showgrid="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       y="168.74846"
+       x="211.58516"
+       height="89.506805"
+       width="101.60232"
+       id="rect3068"
+       style="fill:url(#linearGradient5958);fill-opacity:1;stroke:black;stroke-width:0.48811448;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <g
+       id="g3215"
+       transform="matrix(0.423343,0,0,0.423343,137.1977,42.55985)">
+      <rect
+         y="447.71451"
+         x="299.67859"
+         height="48.571426"
+         width="103.14286"
+         id="rect2899"
+         style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text2903"
+         y="464.8139"
+         x="308.89639"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           y="464.8139"
+           x="308.89639"
+           sodipodi:role="line"
+           id="tspan2905">Segundo padre</tspan></text>
+      <text
+         id="text2907"
+         y="485.50256"
+         x="308.20175"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="485.50256"
+           x="308.20175"
+           id="tspan2909"
+           sodipodi:role="line">32bf9a5f22c0</tspan></text>
+    </g>
+    <g
+       id="g3250"
+       transform="matrix(0.423343,0,0,0.423343,137.1977,42.55986)">
+      <rect
+         y="311.28598"
+         x="188.6071"
+         height="48.571426"
+         width="103.14286"
+         id="rect2936"
+         style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text2940"
+         y="328.38538"
+         x="197.82495"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           y="328.38538"
+           x="197.82495"
+           sodipodi:role="line"
+           id="tspan2942">Hash de revisión</tspan></text>
+      <text
+         id="text2944"
+         y="349.07404"
+         x="197.13031"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="349.07404"
+           x="197.13031"
+           id="tspan2946"
+           sodipodi:role="line">34b8b7a15ea1</tspan></text>
+    </g>
+    <g
+       id="g3243"
+       transform="matrix(0.423343,0,0,0.423343,137.6664,43.91853)">
+      <rect
+         y="363.07654"
+         x="187.5"
+         height="75"
+         width="213.85715"
+         id="rect2950"
+         style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text2958"
+         y="400.86459"
+         x="196.02321"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="fill:black;fill-opacity:1;font-family:Courier"
+           y="400.86459"
+           x="196.02321"
+           id="tspan2960"
+           sodipodi:role="line">...</tspan></text>
+      <text
+         id="text2954"
+         y="380.17593"
+         x="196.71785"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           y="380.17593"
+           x="196.71785"
+           sodipodi:role="line"
+           id="tspan2956"
+           style="fill:#000000;fill-opacity:1">Datos de Revisión (delta o snapshot)</tspan></text>
+    </g>
+    <g
+       id="g5529"
+       transform="translate(-6.710312,-8.165836e-6)">
+      <rect
+         style="fill:url(#linearGradient5584);fill-opacity:1;stroke:black;stroke-width:0.48811448;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect3509"
+         width="101.60232"
+         height="89.506805"
+         x="218.29547"
+         y="497.4801" />
+      <g
+         transform="matrix(0.423343,0,0,0.423343,143.908,371.2915)"
+         id="g3513">
+        <g
+           id="g3515">
+          <rect
+             y="447.72418"
+             x="188.6071"
+             height="48.571426"
+             width="103.14286"
+             id="rect3517"
+             style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+          <text
+             id="text3519"
+             y="464.82358"
+             x="197.82495"
+             style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+             xml:space="preserve"><tspan
+               y="464.82358"
+               x="197.82495"
+               sodipodi:role="line"
+               id="tspan3521">Primer padre</tspan></text>
+          <text
+             id="text3523"
+             y="485.51224"
+             x="197.13031"
+             style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+             xml:space="preserve"><tspan
+               style="font-family:Courier"
+               y="485.51224"
+               x="197.13031"
+               id="tspan3525"
+               sodipodi:role="line">000000000000</tspan></text>
+        </g>
+        <g
+           id="g3527">
+          <rect
+             y="447.71451"
+             x="299.67859"
+             height="48.571426"
+             width="103.14286"
+             id="rect3529"
+             style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+          <text
+             id="text3531"
+             y="464.8139"
+             x="308.89639"
+             style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+             xml:space="preserve"><tspan
+               y="464.8139"
+               x="308.89639"
+               sodipodi:role="line"
+               id="tspan3533">Segundo padre</tspan></text>
+          <text
+             id="text3535"
+             y="485.50256"
+             x="308.20175"
+             style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+             xml:space="preserve"><tspan
+               style="font-family:Courier"
+               y="485.50256"
+               x="308.20175"
+               id="tspan3537"
+               sodipodi:role="line">000000000000</tspan></text>
+        </g>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,143.908,371.2915)"
+         id="g3539">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3541"
+           width="103.14286"
+           height="48.571426"
+           x="188.6071"
+           y="311.28598" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.82495"
+           y="328.38538"
+           id="text3543"><tspan
+             id="tspan3545"
+             sodipodi:role="line"
+             x="197.82495"
+             y="328.38538">Hash de revisión</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.13031"
+           y="349.07404"
+           id="text3547"><tspan
+             sodipodi:role="line"
+             id="tspan3549"
+             x="197.13031"
+             y="349.07404"
+             style="font-family:Courier">ff9dc8bc2a8b</tspan></text>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,144.3767,372.6502)"
+         id="g3551">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3553"
+           width="213.85715"
+           height="75"
+           x="187.5"
+           y="363.07654" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="196.02321"
+           y="400.86459"
+           id="text3555"><tspan
+             sodipodi:role="line"
+             id="tspan3557"
+             x="196.02321"
+             y="400.86459"
+             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="196.71785"
+           y="380.17593"
+           id="text3559"><tspan
+             style="fill:#000000;fill-opacity:1"
+             id="tspan3561"
+             sodipodi:role="line"
+             x="196.71785"
+             y="380.17593">Datos de revisión (delta o snapshot)</tspan></text>
+      </g>
+    </g>
+    <g
+       id="g4868"
+       transform="translate(-1.676208,-2.342463e-5)">
+      <rect
+         style="fill:url(#linearGradient3708);fill-opacity:1;stroke:black;stroke-width:0.48811448;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect3567"
+         width="101.60232"
+         height="89.506805"
+         x="213.26137"
+         y="59.171272" />
+      <g
+         transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01734)"
+         id="g3573">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3575"
+           width="103.14286"
+           height="48.571426"
+           x="188.6071"
+           y="447.72418" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.82495"
+           y="464.82358"
+           id="text3577"><tspan
+             id="tspan3579"
+             sodipodi:role="line"
+             x="197.82495"
+             y="464.82358">Primer padre</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.13031"
+           y="485.51224"
+           id="text3581"><tspan
+             sodipodi:role="line"
+             id="tspan3583"
+             x="197.13031"
+             y="485.51224"
+             style="font-family:Courier">34b8b7a15ea1</tspan></text>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01734)"
+         id="g3585">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3587"
+           width="103.14286"
+           height="48.571426"
+           x="299.67859"
+           y="447.71451" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="308.89639"
+           y="464.8139"
+           id="text3589"><tspan
+             id="tspan3591"
+             sodipodi:role="line"
+             x="308.89639"
+             y="464.8139">Segundo padre</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="308.20175"
+           y="485.50256"
+           id="text3593"><tspan
+             sodipodi:role="line"
+             id="tspan3595"
+             x="308.20175"
+             y="485.50256"
+             style="font-family:Courier">000000000000</tspan></text>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01733)"
+         id="g3597">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3599"
+           width="103.14286"
+           height="48.571426"
+           x="188.6071"
+           y="311.28598" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.82495"
+           y="328.38538"
+           id="text3601"><tspan
+             id="tspan3603"
+             sodipodi:role="line"
+             x="197.82495"
+             y="328.38538">Hash de revisión</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.13031"
+           y="349.07404"
+           id="text3605"><tspan
+             sodipodi:role="line"
+             id="tspan3607"
+             x="197.13031"
+             y="349.07404"
+             style="font-family:Courier">1b67dc96f27a</tspan></text>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,139.3426,-65.65866)"
+         id="g3609">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3611"
+           width="213.85715"
+           height="75"
+           x="187.5"
+           y="363.07654" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="196.02321"
+           y="400.86459"
+           id="text3613"><tspan
+             sodipodi:role="line"
+             id="tspan3615"
+             x="196.02321"
+             y="400.86459"
+             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="196.71785"
+           y="380.17593"
+           id="text3617"><tspan
+             style="fill:#000000;fill-opacity:1"
+             id="tspan3619"
+             sodipodi:role="line"
+             x="196.71785"
+             y="380.17593">Datos de revisión (delta o snapshot)</tspan></text>
+      </g>
+    </g>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-end:url(#Arrow1Mend)"
+       d="M 240.78255,143.08593 L 241.42595,171.75349"
+       id="path3801"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g3573"
+       inkscape:connection-end="#g3250" />
+    <g
+       id="g5677">
+      <rect
+         style="fill:url(#linearGradient5784);fill-opacity:1;stroke:black;stroke-width:0.48811448;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect3393"
+         width="101.60232"
+         height="89.506805"
+         x="150.76137"
+         y="278.32565" />
+      <g
+         transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
+         id="g3399">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3401"
+           width="103.14286"
+           height="48.571426"
+           x="188.6071"
+           y="447.72418" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.82495"
+           y="464.82358"
+           id="text3403"><tspan
+             id="tspan3405"
+             sodipodi:role="line"
+             x="197.82495"
+             y="464.82358">Primer padre</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.13031"
+           y="485.51224"
+           id="text3407"><tspan
+             sodipodi:role="line"
+             id="tspan3409"
+             x="197.13031"
+             y="485.51224"
+             style="font-family:Courier">ff9dc8bc2a8b</tspan></text>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
+         id="g3411">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3413"
+           width="103.14286"
+           height="48.571426"
+           x="299.67859"
+           y="447.71451" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="308.89639"
+           y="464.8139"
+           id="text3415"><tspan
+             id="tspan3417"
+             sodipodi:role="line"
+             x="308.89639"
+             y="464.8139">Segundo padre</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="308.20175"
+           y="485.50256"
+           id="text3419"><tspan
+             sodipodi:role="line"
+             id="tspan3421"
+             x="308.20175"
+             y="485.50256"
+             style="font-family:Courier">000000000000</tspan></text>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
+         id="g3423">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3425"
+           width="103.14286"
+           height="48.571426"
+           x="188.6071"
+           y="311.28598" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.82495"
+           y="328.38538"
+           id="text3427"><tspan
+             id="tspan3429"
+             sodipodi:role="line"
+             x="197.82495"
+             y="328.38538">Hash de revisión</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.13031"
+           y="349.07404"
+           id="text3431"><tspan
+             sodipodi:role="line"
+             id="tspan3433"
+             x="197.13031"
+             y="349.07404"
+             style="font-family:Courier">5b80c922ebdd</tspan></text>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,76.84265,153.4957)"
+         id="g3435">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3437"
+           width="213.85715"
+           height="75"
+           x="187.5"
+           y="363.07654" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="196.02321"
+           y="400.86459"
+           id="text3439"><tspan
+             sodipodi:role="line"
+             id="tspan3441"
+             x="196.02321"
+             y="400.86459"
+             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="196.71785"
+           y="380.17593"
+           id="text3443"><tspan
+             style="fill:#000000;fill-opacity:1"
+             id="tspan3445"
+             sodipodi:role="line"
+             x="196.71785"
+             y="380.17593">Datos de revisión (delta o snapshot)</tspan></text>
+      </g>
+    </g>
+    <g
+       id="g5646"
+       transform="translate(-0.227432,0)">
+      <rect
+         style="fill:url(#linearGradient5786);fill-opacity:1;stroke:black;stroke-width:0.48811448;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect3451"
+         width="101.60232"
+         height="89.506805"
+         x="272.63638"
+         y="278.32565" />
+      <g
+         transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)"
+         id="g3457">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3459"
+           width="103.14286"
+           height="48.571426"
+           x="188.6071"
+           y="447.72418" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.82495"
+           y="464.82358"
+           id="text3461"><tspan
+             id="tspan3463"
+             sodipodi:role="line"
+             x="197.82495"
+             y="464.82358">Primer padre</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.13031"
+           y="485.51224"
+           id="text3465"><tspan
+             sodipodi:role="line"
+             id="tspan3467"
+             x="197.13031"
+             y="485.51224"
+             style="font-family:Courier">ecacb6b4c9fd</tspan></text>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)"
+         id="g3469">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3471"
+           width="103.14286"
+           height="48.571426"
+           x="299.67859"
+           y="447.71451" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="308.89639"
+           y="464.8139"
+           id="text3473"><tspan
+             id="tspan3475"
+             sodipodi:role="line"
+             x="308.89639"
+             y="464.8139">Segundo padre</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="308.20175"
+           y="485.50256"
+           id="text3477"><tspan
+             sodipodi:role="line"
+             id="tspan3479"
+             x="308.20175"
+             y="485.50256"
+             style="font-family:Courier">000000000000</tspan></text>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)"
+         id="g3481">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3483"
+           width="103.14286"
+           height="48.571426"
+           x="188.6071"
+           y="311.28598" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.82495"
+           y="328.38538"
+           id="text3485"><tspan
+             id="tspan3487"
+             sodipodi:role="line"
+             x="197.82495"
+             y="328.38538">Hash de revisión</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="197.13031"
+           y="349.07404"
+           id="text3489"><tspan
+             sodipodi:role="line"
+             id="tspan3491"
+             x="197.13031"
+             y="349.07404"
+             style="font-family:Courier">32bf9a5f22c0</tspan></text>
+      </g>
+      <g
+         transform="matrix(0.423343,0,0,0.423343,198.7176,153.4957)"
+         id="g3493">
+        <rect
+           style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           id="rect3495"
+           width="213.85715"
+           height="75"
+           x="187.5"
+           y="363.07654" />
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="196.02321"
+           y="400.86459"
+           id="text3497"><tspan
+             sodipodi:role="line"
+             id="tspan3499"
+             x="196.02321"
+             y="400.86459"
+             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
+        <text
+           xml:space="preserve"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           x="196.71785"
+           y="380.17593"
+           id="text3501"><tspan
+             style="fill:#000000;fill-opacity:1"
+             id="tspan3503"
+             sodipodi:role="line"
+             x="196.71785"
+             y="380.17593">Datos de revisión (delta o snapshot)</tspan></text>
+      </g>
+    </g>
+    <rect
+       y="387.90286"
+       x="272.40894"
+       height="89.506805"
+       width="101.60232"
+       id="rect5081"
+       style="fill:url(#linearGradient5895);fill-opacity:1;stroke:black;stroke-width:0.48811448;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <g
+       id="g5087"
+       transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)">
+      <rect
+         y="447.72418"
+         x="188.6071"
+         height="48.571426"
+         width="103.14286"
+         id="rect5089"
+         style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text5091"
+         y="464.82358"
+         x="197.82495"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           y="464.82358"
+           x="197.82495"
+           sodipodi:role="line"
+           id="tspan5093">Primer padre</tspan></text>
+      <text
+         id="text5095"
+         y="485.51224"
+         x="197.13031"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="485.51224"
+           x="197.13031"
+           id="tspan5097"
+           sodipodi:role="line">ff9dc8bc2a8b</tspan></text>
+    </g>
+    <g
+       id="g5099"
+       transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)">
+      <rect
+         y="447.71451"
+         x="299.67859"
+         height="48.571426"
+         width="103.14286"
+         id="rect5101"
+         style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text5103"
+         y="464.8139"
+         x="308.89639"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           y="464.8139"
+           x="308.89639"
+           sodipodi:role="line"
+           id="tspan5105">Segundo padre</tspan></text>
+      <text
+         id="text5107"
+         y="485.50256"
+         x="308.20175"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="485.50256"
+           x="308.20175"
+           id="tspan5109"
+           sodipodi:role="line">000000000000</tspan></text>
+    </g>
+    <g
+       id="g5111"
+       transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)">
+      <rect
+         y="311.28598"
+         x="188.6071"
+         height="48.571426"
+         width="103.14286"
+         id="rect5113"
+         style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text5115"
+         y="328.38538"
+         x="197.82495"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           y="328.38538"
+           x="197.82495"
+           sodipodi:role="line"
+           id="tspan5117">Hash de revisión</tspan></text>
+      <text
+         id="text5119"
+         y="349.07404"
+         x="197.13031"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="349.07404"
+           x="197.13031"
+           id="tspan5121"
+           sodipodi:role="line">ecacb6b4c9fd</tspan></text>
+    </g>
+    <g
+       id="g5123"
+       transform="matrix(0.423343,0,0,0.423343,198.4901,263.0729)">
+      <rect
+         y="363.07654"
+         x="187.5"
+         height="75"
+         width="213.85715"
+         id="rect5125"
+         style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text5127"
+         y="400.86459"
+         x="196.02321"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="fill:black;fill-opacity:1;font-family:Courier"
+           y="400.86459"
+           x="196.02321"
+           id="tspan5129"
+           sodipodi:role="line">...</tspan></text>
+      <text
+         id="text5131"
+         y="380.17593"
+         x="196.71785"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           y="380.17593"
+           x="196.71785"
+           sodipodi:role="line"
+           id="tspan5133"
+           style="fill:#000000;fill-opacity:1">Datos de revisión (delta o snapshot)</tspan></text>
+    </g>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       d="M 299.69935,362.24027 L 299.69931,393.49494"
+       id="path5203"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g3457"
+       inkscape:connection-end="#g5111" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 182.35357,362.22647 L 241.2842,503.07224"
+       id="path5271"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g3399"
+       inkscape:connection-end="#g3539" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       d="M 287.63109,471.81747 L 250.9438,503.07223"
+       id="path5285"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g5087"
+       inkscape:connection-end="#g3539" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="M 290.80419,250.07192 L 297.80065,283.90394"
+       id="path5077"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g3215"
+       inkscape:connection-end="#g3481" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="M 229.63373,250.07601 L 190.07484,283.90394"
+       id="path5075"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#g3423" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="131.5625"
+       y="100.79968"
+       id="text5897"><tspan
+         sodipodi:role="line"
+         id="tspan5899"
+         x="131.5625"
+         y="100.79968"
+         style="text-align:end;text-anchor:end">Revisión principal</tspan><tspan
+         sodipodi:role="line"
+         x="131.5625"
+         y="115.79968"
+         id="tspan5901"
+         style="text-align:end;text-anchor:end">(sin hijos)</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="131.5625"
+       y="207.04968"
+       id="text5903"><tspan
+         sodipodi:role="line"
+         id="tspan5905"
+         x="131.5625"
+         y="207.04968"
+         style="text-align:end;text-anchor:end">Revisión de fusión</tspan><tspan
+         sodipodi:role="line"
+         x="131.5625"
+         y="222.04968"
+         id="tspan5907"
+         style="text-align:end;text-anchor:end">(dos padres)</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="131.92578"
+       y="451.58093"
+       id="text5909"><tspan
+         sodipodi:role="line"
+         id="tspan5911"
+         x="131.92578"
+         y="451.58093"
+         style="text-align:end;text-anchor:end">Ramas</tspan><tspan
+         sodipodi:role="line"
+         x="131.92578"
+         y="466.58093"
+         id="tspan5913"
+         style="text-align:end;text-anchor:end">(dos revisiones,</tspan><tspan
+         sodipodi:role="line"
+         x="131.92578"
+         y="481.58093"
+         id="tspan5915"
+         style="text-align:end;text-anchor:end">mismo padre)</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:2, 1;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 111.71875,433.61218 L 154.7268,368.52294"
+       id="path5917"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:2, 1;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 134.375,464.86218 L 277.86691,440.37816"
+       id="path5919"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#g5123" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;text-align:end;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="131.5625"
+       y="536.73718"
+       id="text5927"><tspan
+         sodipodi:role="line"
+         id="tspan5929"
+         x="131.5625"
+         y="536.73718">Primera revisión</tspan><tspan
+         sodipodi:role="line"
+         x="131.5625"
+         y="551.73718"
+         id="tspan5931">(ambos padres nulos)</tspan></text>
+    <rect
+       style="fill:#bbb4ff;fill-opacity:1;stroke:none;stroke-width:0.95291203;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2830"
+       width="43.664806"
+       height="20.562374"
+       x="217.0432"
+       y="232.10075" />
+    <text
+       xml:space="preserve"
+       style="font-size:5.0801158px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="220.94551"
+       y="239.33966"
+       id="text2832"><tspan
+         id="tspan2836"
+         sodipodi:role="line"
+         x="220.94551"
+         y="239.33966">Primer padre</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:5.0801158px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="220.65144"
+       y="248.09805"
+       id="text2879"><tspan
+         sodipodi:role="line"
+         id="tspan2881"
+         x="220.65144"
+         y="248.09805"
+         style="font-family:Courier">5b80c922ebdd</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:2, 1;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 139.84375,107.83093 L 210.15625,107.83093"
+       id="path5965"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:2, 1;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 137.5,213.29968 L 210.49036,214.09055"
+       id="path5967"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:2, 1;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 136.34375,544.54968 L 206.65625,544.54968"
+       id="path5969"
+       inkscape:connector-type="polyline"
+       inkscape:transform-center-y="-171.09375"
+       inkscape:transform-center-x="53.90625" />
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/snapshot.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2807"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docbase="/home/bos/hg/hgbook/en"
+   sodipodi:docname="snapshot.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs2809">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective2759" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4"
+     inkscape:cx="252.04111"
+     inkscape:cy="605.75448"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="906"
+     inkscape:window-height="721"
+     inkscape:window-x="141"
+     inkscape:window-y="57"
+     showgrid="false" />
+  <metadata
+     id="metadata2812">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       style="opacity:1;fill:#d3ceff;fill-opacity:1;stroke:#a7a7a7;stroke-width:1.88795626;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect2817"
+       width="118.18347"
+       height="245.32632"
+       x="243.05112"
+       y="315.4133"
+       inkscape:transform-center-x="136.84403"
+       inkscape:transform-center-y="-66.529183" />
+    <rect
+       y="315.04153"
+       x="46.965065"
+       height="97.803009"
+       width="108.92702"
+       id="rect2815"
+       style="fill:#ffced6;fill-opacity:1;stroke:#a7a7a7;stroke-width:1.14441991;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <g
+       id="g3814">
+      <rect
+         y="348.94302"
+         x="59.285713"
+         height="30"
+         width="84.285713"
+         id="rect2819"
+         style="fill:#ff6e86;fill-opacity:1;stroke:#a7a7a7;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         ry="0" />
+      <text
+         id="text2821"
+         y="368.02701"
+         x="72.717636"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           y="368.02701"
+           x="72.717636"
+           id="tspan2823"
+           sodipodi:role="line">Índice, rev 7</tspan></text>
+    </g>
+    <text
+       id="text3722"
+       y="303.43359"
+       x="22.61635"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       xml:space="preserve"><tspan
+         y="303.43359"
+         x="22.61635"
+         id="tspan3724"
+         sodipodi:role="line">Índice de bitácora de revisiones (archivo .i)</tspan></text>
+    <text
+       id="text3726"
+       y="301.29074"
+       x="241.90207"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       xml:space="preserve"><tspan
+         y="301.29074"
+         x="241.90207"
+         id="tspan3728"
+         sodipodi:role="line">Datos de Bitacora de revisiones (archivo .d)</tspan></text>
+    <path
+       style="fill:#c695ff;fill-opacity:0.60109288;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 143.57143,348.07647 L 255,368.07646 L 255.71429,544.50504 L 142.85714,379.50504 L 143.57143,348.07647 z "
+       id="path3839"
+       sodipodi:nodetypes="ccccc" />
+    <rect
+       style="fill:#4733ff;fill-opacity:1;stroke:#a7a7a7;stroke-width:2.35124183;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3752"
+       width="92.720184"
+       height="67.005905"
+       x="255.42564"
+       y="368.64264" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="264.45859"
+       y="387.30099"
+       id="text3754"><tspan
+         sodipodi:role="line"
+         id="tspan3756"
+         x="264.45859"
+         y="387.30099">Snapshot, rev 4</tspan></text>
+    <rect
+       style="fill:#7c6eff;fill-opacity:1;stroke:#a7a7a7;stroke-width:1.57776296;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3761"
+       width="93.49366"
+       height="29.922237"
+       x="255.03891"
+       y="442.04395" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="263.2662"
+       y="460.17206"
+       id="text3763"><tspan
+         sodipodi:role="line"
+         id="tspan3765"
+         x="263.2662"
+         y="460.17206">Delta, rev 4 a 5</tspan></text>
+    <rect
+       style="fill:#7c6eff;fill-opacity:1;stroke:#a7a7a7;stroke-width:1.57776296;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3774"
+       width="93.49366"
+       height="29.922237"
+       x="255.03891"
+       y="477.97485" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="263.2662"
+       y="496.10297"
+       id="text3776"><tspan
+         sodipodi:role="line"
+         id="tspan3778"
+         x="263.2662"
+         y="496.10297">Delta, rev 5 a 6</tspan></text>
+    <rect
+       style="fill:#7c6eff;fill-opacity:1;stroke:#a7a7a7;stroke-width:1.57776296;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3782"
+       width="93.49366"
+       height="29.922237"
+       x="255.03891"
+       y="513.90576" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="263.2662"
+       y="532.03387"
+       id="text3784"><tspan
+         sodipodi:role="line"
+         id="tspan3786"
+         x="263.2662"
+         y="532.03387">Delta, rev 6 a 7</tspan></text>
+    <rect
+       style="fill:#7c6eff;fill-opacity:1;stroke:#a7a7a7;stroke-width:1.57776296;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect3889"
+       width="93.49366"
+       height="29.922237"
+       x="255.03891"
+       y="332.32489" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="263.2662"
+       y="350.453"
+       id="text3891"><tspan
+         sodipodi:role="line"
+         id="tspan3893"
+         x="263.2662"
+         y="350.453">Delta, rev 2 a 3</tspan></text>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/srcinstall.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,55 @@
+\chapter{Instalar Mercurial desde las fuentes}
+\label{chap:srcinstall}
+
+\section{En un sistema tipo Unix}
+\label{sec:srcinstall:unixlike}
+
+Si usa un sistema tipo Unix que tiene una versión suficientemente
+reciente de Python (2.3~o superior) disponible, es fácil instalar
+Mercurial desde las fuentes.
+\begin{enumerate}
+\item Descargue un paquete fuente reciente de
+  \url{http://www.selenic.com/mercurial/download}.
+\item Descomprímalo:
+  \begin{codesample4}
+    gzip -dc mercurial-\emph{version}.tar.gz | tar xf -
+  \end{codesample4}
+\item Vaya al directorio fuente y ejecute el guión de instalación.
+  Esto armará Mercurial y lo instalará en su directorio casa:
+  \begin{codesample4}
+    cd mercurial-\emph{version}
+    python setup.py install --force --home=\$HOME
+  \end{codesample4}
+\end{enumerate}
+Cuando termine la instalación, Mercurial estará en el subdirectorio
+\texttt{bin} de su directorio casa.  No olvide asegurarse de que este
+directorio esté presente en el camino de búsqueda de su intérprete de
+órdenes.
+
+Probablemente necesitará establecer la variable de ambiente
+\envar{PYTHONPATH} de tal forma que los ejecutables de Mercurial
+puedan encontrar el resto de los paquetes de Mercurial.  Por ejemplo,
+en mi portátil, la establecía a \texttt{/home/bos/lib/python}.  La
+ruta exacta que usted use dependerá de como ha sido construído Python
+en su sistema, pero debería ser fácil deducirla.  Si no está seguro,
+mire lo que haya mostrado el script en el paso anterior, y vea dónde
+se instalaron los contenidos del directorio \texttt{mercurial} se
+instalaron.
+
+\section{En Windows}
+
+Armar e instalar Mercurial en Windows requiere una variedad de
+herramientas, cierta suficiencia técnica y paciencia considerable.
+Personalmente, \emph{no le recomiendo} hacerlo si es un ``usuario
+casual''.  A menos que intente hacer hacks a Mercurial, le recomiendo
+que mejor use un paquete binario.
+
+Si está decidido a construir Mercurial desde las fuentes en Windows,
+siga el ``camino difícil'' indicado en el wiki de Mercurial en
+\url{http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall},
+y espere que el proceso sea realmente un trabajo duro.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/template.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,497 @@
+\chapter{Personalizar los mensajes de Mercurial}
+\label{chap:template}
+
+Mercurial provee un poderoso mecanismo que permite controlar como
+despliega la información.  El mecanismo se basa en plantillas.  Puede
+usar plantillas para generar salida específica para una orden
+particular o para especificar la visualización completa de la interfaz
+web embebida.
+
+\section{Usar estilos que vienen con Mercurial}
+\label{sec:style}
+
+Hay ciertos estilos listos que vienen con Mercurial.  Un estilo es
+simplemente una plantilla predeterminada que alguien escribió e
+instaló en un sitio en el cual Mercurial puede encontrarla.
+
+Antes de dar un vistazo a los estilos que trae Mercurial, revisemos su
+salida usual.
+
+\interaction{template.simple.normal}
+
+Es en cierta medida informativa, pero ocupa mucho espacio---cinco
+líneas de salida por cada conjunto de cambios.  El estilo
+\texttt{compact} lo reduce a tres líneas, presentadas de forma
+suscinta.
+
+\interaction{template.simple.compact}
+
+El estilo de la \texttt{bitácora de cambios} vislumbra el poder
+expresivo del sistema de plantillas de Mercurial.  Este estilo busca
+seguir los estándares de bitácora de cambios del proyecto
+GNU\cite{web:changelog}.
+
+\interaction{template.simple.changelog}
+
+No es una sorpresa que el estilo predeterminado de Mercurial se llame
+\texttt{default}\ndt{predeterminado}.
+
+\subsection{Especificar un estilo predeterminado}
+
+Puede modificar el estilo de presentación que Mercurial usará para
+toda orden vía el fichero \hgrc\, indicando el estilo que prefiere
+usar.
+
+\begin{codesample2}
+  [ui]
+  style = compact
+\end{codesample2}
+
+Si escribe un estilo, puede usarlo bien sea proveyendo la ruta a su
+fichero de estilo o copiando su fichero de estilo a un lugar en el
+cual Mercurial pueda encontrarlo (típicamente el subdirectorio
+\texttt{templates} de su directorio de instalación de Mercurial).
+
+\section{Órdenes que soportan estilos y plantillas}
+
+Todas las órdenes de Mercurial``relacionadas con \texttt{log}'' le
+permiten usar estilos y plantillas: \hgcmd{incoming}, \hgcmd{log},
+\hgcmd{outgoing} y \hgcmd{tip}.
+
+Al momento de la escritura del manual estas son las únicas órdenes que
+soportan estilos y plantillas.  Dado que son las órdenes más
+importantes que necesitan personalización, no ha habido muchas
+solicitudes desde la comunidad de usuarios de Mercurial para añadir
+soporte de plantillas y estilos a otras órdenes.
+
+\section{Cuestiones básicas de plantillas}
+
+Una plantilla de Mercurial es sencillamente una pieza de texto.
+Cierta porción nunca cambia, otras partes se \emph{expanden}, o
+reemplazan con texto nuevo cuando es necesario.
+
+Antes de continuar, veamos de nuevo un ejemplo sencillo de la salida
+usual de Mercurial:
+
+\interaction{template.simple.normal}
+
+Ahora, ejecutemos la misma orden, pero usemos una plantilla para
+modificar su salida:
+
+\interaction{template.simple.simplest}
+
+El ejemplo anterior ilustra la plantilla más sencilla posible;  es
+solamente una porción estática de código que se imprime una vez por
+cada conjunto de cambios.  La opción \hgopt{log}{--template} de la
+orden \hgcmd{log} indica a Mercurial usar el texto dado como la
+plantilla cuando se imprime cada conjunto de cambios.
+
+Observe que la cadena de plantilla anterior termina con el texto
+``\Verb+\n+''.  Es una \emph{secuencia de control}, que le indica a
+Mercurial imprimira una nueva línea al final de cada objeto de la
+plantilla.  Si omite esta nueva línea, Mercurial colocará cada pieza
+de salida seguida.  Si desea más detalles acerca de secuencias de
+control, vea la sección~\ref{sec:template:escape}.
+
+Una plantilla que imprime una cadena fija de texto siempre no es muy
+útil; intentemos algo un poco más complejo.
+
+\interaction{template.simple.simplesub}
+
+Como puede ver, la cadena ``\Verb+{desc}+'' en la plantilla ha sido
+reemplazada en la salida con la descricipción de cada conjunto de
+cambios.  Cada vez que Mercurial encuentra texto encerrado entre
+corchetes (``\texttt{\{}'' y ``\texttt{\}}''), intentará reemplazar los
+corchetes y el texto con la expansión de lo que sea está adentro.
+Para imprimir un corchete de forma literal, debe escaparlo, como se
+describe en la sección~\ref{sec:template:escape}.
+
+\section{Palabras claves más comunes en las plantillas}
+\label{sec:template:keyword}
+
+Puede empezar a escribir plantillas sencillas rápidamente con las
+palabras claves descritas a continuación:
+
+\begin{itemize}
+\item[\tplkword{author}] Cadena.  El autor NO modificado del conjunto
+  de cambios.
+\item[\tplkword{branches}] Cadena.  El nombre de la rama en la cual se
+  consignó el conjunto de cambios.  Será vacía si el nombre de la rama es
+  \texttt{default}.
+\item[\tplkword{date}] Información de fecha.  La fecha en la cual se
+  consignó el conjunto de cambios.  \emph{No} es legible por un
+  humano, debe pasarla por un firltro que la desplegará
+  apropiadamente.  En la sección~\ref{sec:template:filter} hay más
+  detalles acerca de filtros.  La fecha se expresa como un par de
+  números.  El primer número corresponde a una marca de tiempo UNIX
+  UTC (segundos desde el primero de enero de 1970); la segunda es el
+  corrimiento horario de la zona horaria del UTC en la cual se encontraba
+  quien hizo la consignación, en segundos.
+\item[\tplkword{desc}] Cadena.  La descripción en texto del conjunto
+  de cambios.
+\item[\tplkword{files}] Lista de cadenas.  Todos los ficheros
+  modificados, adicionados o eliminados por este conjunto de cambios.
+\item[\tplkword{file\_adds}] Lista de cadenas.  Ficheros adicionados
+  por este conjunto de cambios.
+\item[\tplkword{file\_dels}] Lista de cadenas.  Ficheros eliminados
+  por este conjunto de cambios.
+\item[\tplkword{node}] Cadena.  El hash de identificación de este
+  conjunto de cambios como una cadena hexadecimal de 40 caracteres.
+\item[\tplkword{parents}] Lista de cadenas.  Los ancestros del
+  conjunto de cambios.
+\item[\tplkword{rev}] Entero.  El número de revisión del repositorio
+  local.
+\item[\tplkword{tags}] Lista de cadenas.  Todas las etiquetas
+  asociadas al conjunto de cambios.
+\end{itemize}
+
+Unos experimentos sencillos nos mostrarán qué esperar cuando usamos
+estas palabras claves; puede ver los resultados en la
+figura~\ref{fig:template:keywords}.
+
+\begin{figure}
+  \interaction{template.simple.keywords}
+  \caption{Template keywords in use}
+  \label{fig:template:keywords}
+\end{figure}
+
+Como mencionamos anteriormente, la palabra clave de fecha no produce
+salida legible por un humano, debemos tratarla de forma especial.
+Esto involucra usar un \emph{filtro}, acerca de lo cual hay más en la
+sección~\ref{sec:template:filter}.
+
+\interaction{template.simple.datekeyword}
+
+\section{Secuencias de Control}
+\label{sec:template:escape}
+
+El motor de plantillas de Mercurial reconoce las secuencias de control
+más comunmente usadas dentro de las cadenas.  Cuando ve un backslash
+(``\Verb+\+''), ve el caracter siguiente y sustituye los dos
+caracteres con un reemplazo sencillo, como se describe a continuación:
+
+\begin{itemize}
+\item[\Verb+\textbackslash\textbackslash+] Backslash, ``\Verb+\+'',
+  ASCII~134.
+\item[\Verb+\textbackslash n+] Nueva línea, ASCII~12.
+\item[\Verb+\textbackslash r+] Cambio de línea, ASCII~15.
+\item[\Verb+\textbackslash t+] Tab, ASCII~11.
+\item[\Verb+\textbackslash v+] Tab Vertical, ASCII~13.
+\item[\Verb+\textbackslash \{+] Corchete abierto, ``\Verb+{+'', ASCII~173.
+\item[\Verb+\textbackslash \}+] Corchete cerrado, ``\Verb+}+'', ASCII~175.
+\end{itemize}
+
+Como se indicó arriba, si desea que la expansión en una plantilla
+contenga un caracter literal ``\Verb+\+'', ``\Verb+{+'', o
+  ``\Verb+{+'', debe escaparlo.
+
+\section{Uso de filtros con palabras claves}
+\label{sec:template:filter}
+
+Algunos de los resultados de la expansión de la plantilla no son
+fáciles de usar de inmediato.  Mercurial le permite especificar una
+cadena de \emph{filtros} opcionales para modificar el resultado de
+expandir una palabra clave.  Ya ha visto el filtro usual
+\tplkwfilt{date}{isodate} en acción con anterioridad para hacer
+legible la fecha.
+
+A continuación hay una lista de los filtros de Mercurial más
+comunmente usados.  Ciertos filtros pueden aplicarse a cualquier
+texto, otros pueden usarse únicamente en circunstancias específicas.
+El nombre de cada filtro está seguido de la indicación de dónde puede
+ser usado y una descripción de su efecto.
+
+\begin{itemize}
+\item[\tplfilter{addbreaks}] Cualquier texto. Añade una etiqueta XHTML
+  ``\Verb+<br/>+'' antes del final de cada línea excepto en la final.
+  Por ejemplo, ``\Verb+foo\nbar+'' se convierte en ``\Verb+foo<br/>\nbar+''.
+\item[\tplkwfilt{date}{age}] palabra clave \tplkword{date}.  Muestra
+  la edad de la fecha, relativa al tiempo actual. Ofrece una cadena como
+  ``\Verb+10 minutes+''.
+\item[\tplfilter{basename}] Cualquier texto, pero de utilidad sobre
+  todo en palabras claves relativas a \tplkword{ficheros}.  Trata el
+  texto como una ruta, retornando el nombre base.  Por ejemplo,
+  ``\Verb+foo/bar/baz+'', se convierte en ``\Verb+baz+''.
+\item[\tplkwfilt{date}{date}] \tplkword{date} palabra clave.  Mostrar
+  la fecha en un formato similar a la orden \tplkword{date} de 
+  in a similar format to the Unix, pero con la zona horaria incluída.
+  Una cadena como ``\Verb+Mon Sep 04 15:13:13 2006 -0700+''.
+\item[\tplkwfilt{author}{domain}] Cualquier texto, pero de mayor
+  utilidad para la palabra clave \tplkword{author}.  Encuentra la
+  primera cadena que luce como una dirección de correo electrónico, y
+  extrae solamente el componente del dominio.  Por ejemplo, de 
+  ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' se extrae
+  ``\Verb+serpentine.com+''.
+\item[\tplkwfilt{author}{email}] Cualquier texto, pero de mayor
+  utilidad para la palabra clave \tplkword{author}.  Extrae la primera
+  cadena que luce como una dirección de correo. Por ejemplo, de
+  ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' extrae 
+  ``\Verb+bos@serpentine.com+''.
+\item[\tplfilter{escape}] Cualquier texto.  Reemplaza los caracteres
+  especiales de XML/XHTML: ``\Verb+&+'', ``\Verb+<+'' y ``\Verb+>+''
+  con las entidades XML.
+\item[\tplfilter{fill68}] Cualquier texto. Lograr que el texto ocupe
+  las primeras 68 columnas.  Es útil emplearlo antes de pasar el texto
+  por el filtro \tplfilter{tabindent}, y queremos que aún quepa en una
+  ventana de fuente fija y 80 columnas.
+\item[\tplfilter{fill76}] Cualquier texto.  Lograr que el texto quepa
+  en 76 columnas.
+\item[\tplfilter{firstline}] Cualquier texto.  Mostrar la primera
+  línea de texto sin saltos de línea.
+\item[\tplkwfilt{date}{hgdate}] \tplkword{date} palabra clave.
+  Mostrar la fecha como un par de números legibles.  Muestra una
+  cadena como ``\Verb+1157407993 25200+''.
+\item[\tplkwfilt{date}{isodate}] \tplkword{date} palabra clave.
+  Mostrar la fecha como una cadena de texto en el formato.  Muestra
+  una cadena como ``\Verb+2006-09-04 15:13:13 -0700+''.
+\item[\tplfilter{obfuscate}] Cualquier texto, pero de mayor utilidad
+  para la palabra clave \tplkword{author}.  Muestra el campo de texto
+  como una secuencia de entidades XML.  Esto ayuda a eliminar ciertos
+  robots estúpidos de adquisición de correo.
+\item[\tplkwfilt{author}{person}] Cualquier texto, útil sobre todo
+  para la palabra clave \tplkword{author}.  Muestra el texto que hay
+  antes de la dirección de correo electrónico.  Por ejemplo,
+  ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' mostraría
+  ``\Verb+Bryan O'Sullivan+''.
+\item[\tplkwfilt{date}{rfc822date}] \tplkword{date} palabra clave.
+  Muestra una fecha con el mismo formato que se usa en los encabezados
+  de correo.  Mostraría una cadena como
+ ``\Verb+Mon, 04 Sep 2006 15:13:13 -0700+''.
+\item[\tplkwfilt{node}{short}] Hash del conjunto de cambios.  Muestra
+  la forma corta de un hash de conjunto de cambios, 
+  of a changeset hash, p.e.~una cadena hexadecimal de 12 bytes.
+\item[\tplkwfilt{date}{shortdate}] \tplkword{date} palabra clave.
+  Mostrar año, mes y día de una fecha.  Muestrauna cadena como
+  ``\Verb+2006-09-04+''.
+\item[\tplfilter{strip}] Cualquier texto.  Elimina todos los espacios
+  en blanco al principio y al final de la cadena.
+\item[\tplfilter{tabindent}] Cualquier texto.  Muestra el texto con
+  todas las líneas excepto la primera que comience con el caracter tab.
+\item[\tplfilter{urlescape}] Cualquier texto.  Escapa todos los
+  caracteres que se consideren como ``especiales'' por los parsers de
+  URL.  Por ejemplo, \Verb+foo bar+ se convierte en \Verb+foo%20bar+.
+\item[\tplkwfilt{author}{user}] Cualquier texto, útil sobre todo para
+  la palabra clave \tplkword{author}.  Retorna el ``usuario'' de una
+  dirección de correo.  Por ejemplo, 
+  ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' se convierte en 
+  ``\Verb+bos+''.
+\end{itemize}
+
+\begin{figure}
+  \interaction{template.simple.manyfilters}
+  \caption{Filtros de plantilla en acción}
+  \label{fig:template:filters}
+\end{figure}
+
+\begin{note}
+  Si trata de aplicar un filtro a una porción de datos que no puede
+  procesarse, Mercurial fallará e imprimirá una excepción de Python.
+  Por ejemplo, el tratar de usar la salida de la palabra clave
+  \tplkword{desc} con el filtro \tplkwfilt{date}{isodate} no resultará
+  algo útil.
+\end{note}
+
+\subsection{Combinar filtros}
+
+Combinar filtros es para generar una salida en la forma como usted lo
+desea es muy sencillo.  La cadena de filtros siguientes arman una
+descripción, después aseguran que cabe limpiamente en 68 columnas, y
+las indenta con 8~caracteres (por lo menos en sistemas tipo Unix, en
+los que el tab por convención se extiende en 8~caracteres).
+
+\interaction{template.simple.combine}
+
+Observe el uso de ``\Verb+\t+'' (un caracter tab) en la plantilla para
+forzar que la primera línea se indente; esto es necesario para lograr
+que la primera línea luzca indentada;  es necesario debido a que
+\tplkword{tabindent} indenta todas las líneas \emph{excepto} la primera.
+
+Tenga en cuenta que el orden de los filtros importa.  El primer filtro
+se aplica primero al resultado de la palabra clave; el segundo al
+resultado de la aplicación del primer filtro y así sucesivamente.  Por
+ejemplo, usar \Verb+fill68|tabindent+ es muy distinto al resultado de
+usar \Verb+tabindent|fill68+.
+
+
+\section{De plantillas a estilos}
+
+Una plantilla provee una forma rápida y sencilla para dar formato a
+una salida.  Las plantillas pueden volvers verbosas, y es útil poder
+darle un nombre a una plantilla.  Un fichero de estilo es una
+plantilla con un nombre, almacenado en un fichero.
+
+Más aún, al usar un fichero de estilo se dispara el poder del motor de
+plantillas en un nivel imposible de alcanzar usando las opción
+\hgopt{log}{--template} desde la línea de órdenes.
+
+
+\subsection{Los ficheros de estilo más sencillos}
+
+Nuestro fichero sencillo de estilo contiene una sola línea:
+
+\interaction{template.simple.rev}
+
+Se le indica a Mercurial, ``si está imprimiendo un conjunto de
+cambios, use el texto de la derecha como la plantilla''.
+
+\subsection{Sintaxis de ficheros de estilo}
+
+Las reglas de sintaxis para un fichero de estilo son sencillas:
+
+\begin{itemize}
+\item El fichero se procesa línea por línea.
+
+\item Se ignoran el espacio en blanco circundante.
+
+\item Se omiten las líneas en blanco.
+
+\item Si una línea comienza con los caracteres ``\texttt{\#}'' o
+  ``\texttt{;}'', la línea completa se trata como un comentario, y se
+  omite como si fuera vacía.
+
+\item Una línea comienza con una palabra clave.  Esta debe comenzar
+  con una caracter alfabético o una raya al piso, y puede contener
+  subsecuentemente cualquier caracter alfanumérico o una raya al
+  piso.  (En notación de expresiones regulares debe coincidir con
+  \Verb+[A-Za-z_][A-Za-z0-9_]*+.)
+
+\item El próximo elemento debe ser un caracter ``\texttt{=}'', que
+  puede estar precedido o seguido por una cantidad arbitraria de
+  espacio.
+
+\item Si el resto de la línea comienza y termina con caracteres
+  encerrados entre caracteres de comillas (bien sea sencillas o
+  dobles),  se trata como cuerpo de la plantilla.
+
+\item Si el resto de la línea \emph{no} comienza con una comilla, se
+  trata como el nombre de un fichero; los contenidos de este fichero
+  se leerán y se usarán como cuerpo de la plantilla.
+\end{itemize}
+
+\section{Ejemplos de ficheros de estilos}
+
+Para ilustrar la creación de un fichero de estilo, construiremos
+algunos ejemplos.  En lugar de ofrecer un fichero completo de estilo y
+analizarlo, replicaremos el proceso usual de desarrollo de un fichero
+de estilo comenzando con algo muy sencillo, y avanzando por una serie
+de ejemplos sucesivos más completos.
+
+\subsection{Identificar equivocaciones en ficheros de estilo}
+
+Si Mercurial encuentra un problema en un fichero de estilo en el cual
+usted está trabajando, imprime un mensaje de error suscinto, cuando
+usted identifique lo que significa, resulta muy útil.
+
+\interaction{template.svnstyle.syntax.input}
+
+Tenga en cuenta que \filename{broken.style} trata de definir la
+palabra clave \texttt{changeset}, pero omite dar un contenido para esta.
+Cuando se le indica a Mercurial que use este fichero de estilo, se
+queja inmediatamente.
+
+\interaction{template.svnstyle.syntax.error}
+
+Este mensaje de error luce intimidante, pero no es muy difícil de
+seguir:
+
+\begin{itemize}
+\item El primer componente es la forma como Mercurial dice ``me rindo''.
+  \begin{codesample4}
+    \textbf{abort:} broken.style:1: parse error
+  \end{codesample4}
+
+\item A continuación viene el nombre del fichero que contiene el error.
+  \begin{codesample4}
+    abort: \textbf{broken.style}:1: parse error
+  \end{codesample4}
+
+\item Siguendo el nombre del fichero viene el número de línea en la
+  que se encontró el error.
+  \begin{codesample4}
+    abort: broken.style:\textbf{1}: parse error
+  \end{codesample4}
+
+\item Finalmente, la descripción de lo que falló.
+  \begin{codesample4}
+    abort: broken.style:1: \textbf{parse error}
+  \end{codesample4}
+  La descripción del problema no siempre es clara (como en este caso),
+  pero aunque sea críptica, casi siempre es trivial la inspección
+  visual de la línea en el fichero de estilo y encontrar lo que está
+  mal.
+\end{itemize}
+
+\subsection{Identificar de forma única un repositorio}
+
+Si desea identificar un repositorio de Mercurial ``de forma única''
+con una cadena corta como identificador, puede usar la primera
+revisión en el repositorio.
+\interaction{template.svnstyle.id} 
+No es garantía de unicidad, pero no es útill en ciertos casos:
+many cases.
+\begin{itemize}
+\item No funcionará en un repositorio completamente vacío, porque un
+  repositorio así no tiene una revisión~zero.
+\item Tampoco funcionará en caso (muy raro) cuando el repositorio sea
+  una fusión de dos repositorios independientes y tiene los dos
+  directorios por ahí.
+\end{itemize}
+Hay ciertos casos en los cuales podría colocar el identificador:
+\begin{itemize}
+\item Como una llave en la tabla de una base de datos que administra
+  repositorios en un servidor.
+\item Como una parte del par \{\emph{ID~repositorio}, \emph{ID~revisión}\}.
+  Almacene esta información de forma independiente cuando ejecute
+  construcciones automatizadas u otras actividades, de forma que pueda
+  ``reconstruir'' posteriormente en caso de ser necesario.
+\end{itemize}
+
+\subsection{Mostrando salida parecida a Subversion}
+
+Intentemos emular la salida usual que usa otro sistema de control de
+revisiones,  Subversion.
+\interaction{template.svnstyle.short}
+
+Dado que la salida de Subversion es sencilla, es fácil copiar y pegar
+una porción de su salida en un fichero, y reemplazar el texto
+producido previamente por Subversion con valores base que quisiéramos
+ver expandidos.
+\interaction{template.svnstyle.template}
+
+Esta plantilla difiere en algunos detalles de la salida producida por
+Subversion:
+\begin{itemize}
+\item Subversion imprime una fecha ``legible'' (el ``\texttt{Wed, 27 Sep
+    2006}'' en el ejemplo de salida anterior) en paréntesis.  El motor
+  de plantillas de Mercurial no ofrece una forma sencilla de desplegar
+  una fecha en este formato sin imprimir también la hora y la zona horaria.
+\item Emulamos las líneas de ``separación'' de subversion con caracteres
+  ``\texttt{-}'' en una línea.  Usamos la palabra clave
+  \tplkword{header} del motor de plantillas para imprimir una línea de
+  separación como la primera línea de salida (ver más abajo), para
+  lograr una salida similara a la de Subversion.
+\item La salida de subversion incluye un conteo en el encabezado del
+  número de líneas en el mensaje de consinación.  No podemos
+  replicarlo en Mercurial; el motor de plantilla no ofrece en la
+  actualidad un filtro que cuente la cantidad de objetos que se le
+  pasen.
+\end{itemize}
+No me tomó más de un minuto o dos de trabajo para reemplazar texto
+literal de un ejemplo de salida de la salida de Subversion con ciertas
+palabras claves y filtros para ofrecer la plantilla anterior.  El
+fichero de estilo se refiere sencillamente a la plantilla.
+\interaction{template.svnstyle.style}
+
+Podríamos haber incluído el texto del fichero plantilla directamente
+en el fichero de estilo encerrando entre comillas y reemplazando las
+nuevas líneas con secuencias ``\verb!\n!'', pero haría muy difícil de
+leer el fichero de estilos.  La facilidad para leer es importante
+cuando está decidiendo si un texto pertenece a un fichero de estilo o
+a un fichero de plantilla incluído en el estilo.  Si el fichero de
+estilo luce muy grande o complicado, si inserta una pieza de texto
+literal, mejor colóquelo en una plantilla.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/tour-basic.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,690 @@
+\chapter{Una gira de Mercurial: lo básico}
+\label{chap:tour-basic}
+
+\section{Instalar Mercurial en su sistema}
+\label{sec:tour:install}
+Hay paquetes binarios precompilados de Mercurial disponibles para cada
+sistema operativo popular. Esto hace fácil empezar a usar Mercurial
+en su computador inmediatamente.
+
+\subsection{Linux}
+
+Dado que cada distribución de Linux tiene sus propias herramientas de
+manejo de paquetes, políticas, y ritmos de desarrollo, es difícil dar
+un conjunto exhaustivo de instrucciones sobre cómo instalar el paquete
+de Mercurial. La versión de Mercurial que usted tenga a disposición
+puede variar dependiendo de qué tan activa sea la persona que mantiene
+el paquete para su distribución.
+
+Para mantener las cosas simples, me enfocaré en instalar Mercurial
+desde la línea de comandos en las distribuciones de Linux más
+populares. La mayoría de estas distribuciones proveen administradores
+de paquetes gráficos que le permitirán instalar Mercurial con un solo
+clic; el nombre de paquete a buscar es \texttt{mercurial}.
+
+\begin{itemize}
+\item[Debian]
+  \begin{codesample4}
+    apt-get install mercurial
+  \end{codesample4}
+
+\item[Fedora Core]
+  \begin{codesample4}
+    yum install mercurial
+  \end{codesample4}
+
+\item[Gentoo]
+  \begin{codesample4}
+    emerge mercurial
+  \end{codesample4}
+
+\item[OpenSUSE]
+  \begin{codesample4}
+    yum install mercurial
+  \end{codesample4}
+
+\item[Ubuntu] El paquete de Mercurial de Ubuntu está basado en el de
+    Debian. Para instalarlo, ejecute el siguiente comando.
+  \begin{codesample4}
+    apt-get install mercurial
+  \end{codesample4}
+  El paquete de Mercurial para Ubuntu tiende a atrasarse con respecto
+  a la versión de Debian por un margen de tiempo considerable
+  (al momento de escribir esto, 7 meses), lo que en algunos casos
+  significará que usted puede encontrarse con problemas que ya habrán
+  sido resueltos en el paquete de Debian.
+\end{itemize}
+
+\subsection{Solaris}
+
+SunFreeWare, en \url{http://www.sunfreeware.com}, es una buena fuente
+para un gran número de paquetes compilados para Solaris para las
+arquitecturas Intel y Sparc de 32 y 64 bits, incluyendo versiones
+actuales de Mercurial.
+
+\subsection{Mac OS X}
+
+Lee Cantey publica un instalador de Mercurial para Mac OS~X en 
+\url{http://mercurial.berkwood.com}.  Este paquete funciona en tanto
+en Macs basados en Intel como basados en PowerPC. Antes de que pueda
+usarlo, usted debe instalar una versión compatible de Universal
+MacPython~\cite{web:macpython}. Esto es fácil de hacer; simplemente
+siga las instrucciones del sitio de Lee.
+
+También es posible instalar Mercurial usando Fink o MacPorts, dos
+administradores de paquetes gratuitos y populares para Mac OS X. Si
+usted tiene Fink, use \command{sudo apt-get install mercurial-py25}.
+Si usa MacPorts, \command{sudo port install mercurial}.
+
+\subsection{Windows}
+
+Lee Cantey publica un instalador de Mercurial para Windows en
+\url{http://mercurial.berkwood.com}. Este paquete no tiene
+% TODO traducción de it just works. Agreed?
+dependencias externas; ``simplemente funciona''.
+
+\begin{note}
+    La versión de Windows de Mercurial no convierte automáticamente
+    los fines de línea entre estilos Windows y Unix. Si usted desea
+    compartir trabajo con usuarios de Unix, deberá hacer un trabajo
+    adicional de configuración. XXX Terminar esto.
+\end{note}
+
+\section{Arrancando}
+
+Para empezar, usaremos el comando \hgcmd{version} para revisar si
+Mercurial está instalado adecuadamente. La información de la versión
+que es impresa no es tan importante; lo que nos importa es si imprime
+algo en absoluto.
+
+\interaction{tour.version}
+
+% TODO builtin-> integrado?
+\subsection{Ayuda integrada}
+
+Mercurial provee un sistema de ayuda integrada. Esto es invaluable
+para ésas ocasiones en la que usted está atorado tratando de recordar
+cómo ejecutar un comando. Si está completamente atorado, simplemente
+ejecute \hgcmd{help}; esto imprimirá una breve lista de comandos,
+junto con una descripción de qué hace cada uno. Si usted solicita
+ayuda sobre un comando específico (como abajo), se imprime información
+más detallada.
+\interaction{tour.help}
+Para un nivel más impresionante de detalle (que usted no va a
+necesitar usualmente) ejecute \hgcmdargs{help}{\hggopt{-v}}. La opción
+\hggopt{-v} es la abreviación para \hggopt{--verbose}, y le indica a
+Mercurial que imprima más información de lo que haría usualmente.
+
+\section{Trabajar con un repositorio}
+
+En Mercurial, todo sucede dentro de un \emph{repositorio}. El
+repositorio para un proyecto contiene todos los ficheros que
+``pertenecen a'' ése proyecto, junto con un registro histórico de los
+ficheros de ese proyecto.
+
+No hay nada particularmente mágico acerca de un repositorio; es
+simplemente un árbol de directorios en su sistema de ficheros que
+Mercurial trata como especial. Usted puede renombrar o borrar un
+repositorio en el momento que lo desee, usando bien sea la línea de
+comandos o su explorador de ficheros.
+
+\subsection{Hacer una copia local de un repositorio}
+
+\emph{Copiar} un repositorio es sólo ligeramente especial. Aunque
+usted podría usar un programa normal de copia de ficheros para hacer
+una copia del repositorio, es mejor usar el comando integrado que
+Mercurial ofrece. Este comando se llama \hgcmd{clone}\ndt{Del término
+``clonar'' en inglés.}, porque crea una copia idéntica de un
+repositorio existente.
+\interaction{tour.clone}
+Si nuestro clonado tiene éxito, deberíamos tener un directorio local
+llamado \dirname{hello}. Este directorio contendrá algunos ficheros.
+\interaction{tour.ls}
+Estos ficheros tienen el mismo contenido e historial en nuestro
+repositorio y en el repositorio que clonamos.
+
+Cada repositorio Mercurial está completo, es autocontenido e
+independiente. Contiene su propia copia de los ficheros y el historial
+de un proyecto. Un repositorio clonado recuerda la ubicación de la que
+fue clonado, pero no se comunica con ese repositorio, ni con ningún
+otro, a menos que usted le indique que lo haga.
+
+Lo que esto significa por ahora es que somos libres de experimentar
+con nuestro repositorio, con la tranquilidad de saber que es una
+% TODO figure out what to say instead of sandbox
+``caja de arena'' privada que no afectará a nadie más.
+
+\subsection{Qué hay en un repositorio?}
+
+Cuando miramos en detalle dentro de un repositorio, podemos ver que
+contiene un directorio llamado \dirname{.hg}. Aquí es donde Mercurial
+mantiene todos los metadatos del repositorio.
+\interaction{tour.ls-a}
+
+Los contenidos del directorio \dirname{.hg} y sus subdirectorios son
+exclusivos de Mercurial. Usted es libre de hacer lo que desee con
+cualquier otro fichero o directorio en el repositorio.
+
+Para introducir algo de terminología, el directorio \dirname{.hg} es
+el repositorio ``real'', y todos los ficheros y directorios que
+coexisten con él están en el \emph{directorio de trabajo}. Una forma
+sencilla de recordar esta distinción es que el \emph{repositorio}
+contiene el \emph{historial} de su proyecto, mientras que el
+\emph{directorio de trabajo} contiene una \emph{instantánea} de su
+proyecto en un punto particular del historial.
+
+\section{Vistazo rápido al historial}
+
+Una de las primeras cosas que se desea hacer con un repositorio nuevo,
+poco conocido, es conocer su historial. El comando \hgcmd{log} nos
+permite ver el mismo.
+\interaction{tour.log}
+Por defecto este programa imprime un párrafo breve por cada cambio al
+proyecto que haya sido grabado. Dentro de la terminología de
+Mercurial, cada uno de estos eventos es llamado \emph{conjunto de
+cambios}, porque pueden contener un registro de cambios a varios
+ficheros.
+
+Los campos de la salida de \hgcmd{log} son los siguientes.
+\begin{itemize}
+    \item[\texttt{changeset}]\hspace{-0.5em}\ndt{Conjunto de cambios.} Este campo
+        tiene un número, seguido por un
+        % TODO digo mejor seguido por un dos puntos ? string =>
+        % cadena?
+        \texttt{:}, seguido por una cadena hexadecimal. Ambos son
+        \emph{identificadores} para el conjunto de cambios. Hay dos
+        identificadores porque el número es más corto y más fácil de
+        recordar que la cadena hexadecimal.
+        
+\item[\texttt{user}]\hspace{-0.5em}\ndt{Usuario.} La identidad de la
+    persona que creó el conjunto de cambios. Este es un campo en el
+    que se puede almacenar cualquier valor, pero en la mayoría de los
+    casos contiene el nombre de una persona y su dirección de correo
+    electrónico.
+    
+\item[\texttt{date}]\hspace{-0.5em}\ndt{Fecha.} La fecha y hora en la
+    que el conjunto de cambios fue creado, y la zona horaria en la que
+    fue creado. (La fecha y hora son locales a dicha zona horaria;
+    ambos muestran la fecha y hora para la persona que creó el
+    conjunto de cambios).
+    
+\item[\texttt{summary}]\hspace{-0.5em}\ndt{Sumario.} 
+    La primera línea del texto que usó la persona que creó el conjunto
+    de cambios para describir el mismo.
+\end{itemize}
+El texto impreso por \hgcmd{log} es sólo un sumario; omite una gran
+cantidad de detalles.
+
+La figura~\ref{fig:tour-basic:history} es una representación
+gráfica del historial del repositorio \dirname{hello}, para hacer más
+fácil ver en qué dirección está ``fluyendo'' el historial. Volveremos
+a esto varias veces en este capítulo y en los siguientes.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{tour-history}
+  \caption{Historial gráfico del repositorio \dirname{hello}}
+  \label{fig:tour-basic:history}
+\end{figure}
+
+\subsection{Conjuntos de cambios, revisiones, y comunicándose con
+otras personas}
+
+%TODO sloppy => desordenado ?  TODO hablar del inglés? o de español?
+Ya que el inglés es un lenguaje notablemente desordenado, y el área de
+ciencias de la computación tiene una notable historia de confusión de
+% TODO insertar ? al revés. no sé cómo en un teclado de estos.
+términos (porqué usar sólo un término cuando cuatro pueden servir?),
+el control de revisiones tiene una variedad de frases y palabras que
+tienen el mismo significado. Si usted habla acerca del historial de
+Mercurial con alguien, encontrará que la expresión ``conjunto de
+cambios'' es abreviada a menudo como ``cambio'' o (por escrito)
+``cset''\ndt{Abreviatura para la expresión ``changeset'' en inglés.},
+y algunas veces un se hace referencia a un conjunto de cambios como
+una ``revisión'' o ``rev''\ndt{De nuevo, como abreviación para el
+término en inglés para ``revisión'' (``revision'').}.
+
+Si bien no es relevante qué \emph{palabra} use usted para referirse al
+concepto ``conjunto de cambios'', el \emph{identificador} que usted
+use para referise a ``un \emph{conjunto de cambios} particular'' es
+muy importante. Recuerde que el campo \texttt{changeset} en la salida
+de \hgcmd{log} identifica un conjunto de cambios usando tanto un
+número como una cadena hexadecimal.
+
+\begin{itemize}
+    \item El número de revisión \emph{sólo es válido dentro del
+        repositorio}.
+    \item Por otro lado, la cadena hexadecimal es el
+        \emph{identificador permanente e inmutable} que siempre
+        identificará ése conjunto de cambios en \emph{todas} las
+        copias del repositorio.
+\end{itemize}
+La diferencia es importante. Si usted le envía a alguien un correo
+electrónico hablando acerca de la ``revisión~33'', hay una
+probabilidad alta de que la revisión~33 de esa persona \emph{no sea la
+misma suya}. Esto sucede porque el número de revisión depende del
+orden en que llegan los cambios al repositorio, y no hay ninguna
+garantía de que los mismos cambios llegarán en el mismo orden en
+diferentes repositorios. Tres cambios dados $a,b,c$ pueden aparecer en
+un repositorio como $0,1,2$, mientras que en otro aparecen como
+$1,0,2$.
+
+Mercurial usa los números de revisión simplemente como una abreviación
+conveniente. Si usted necesita hablar con alguien acerca de un
+conjunto de cambios, o llevar el registro de un conjunto de cambios
+por alguna otra razón (por ejemplo, en un reporte de fallo), use el
+identificador hexadecimal.
+
+\subsection{Ver revisiones específicas}
+
+Para reducir la salida de \hgcmd{log} a una sola revisión, use la  
+opción \hgopt{log}{-r} (o \hgopt{log}{--rev}).  Puede usar un número
+de revisión o un identificador hexadecimal de conjunto de cambios, y
+puede pasar tantas revisiones como desee.
+
+\interaction{tour.log-r}
+
+Si desea ver el historial de varias revisiones sin tener que mencionar
+cada una de ellas, puede usar la \emph{notación de rango}; esto le
+permite expresar el concepto ``quiero ver todas las revisiones entre
+$a$ y $b$, inclusive''.
+\interaction{tour.log.range}
+Mercurial también respeta el orden en que usted especifica las
+revisiones, así que \hgcmdargs{log}{-r 2:4} muestra $2,3,4$ mientras
+que \hgcmdargs{log}{-r 4:2} muestra $4,3,2$.
+
+\subsection{Información más detallada}
+Aunque la información presentada por \hgcmd{log} es útil si usted sabe
+de antemano qué está buscando, puede que necesite ver una descripción
+completa del cambio, o una lista de los ficheros que cambiaron, si
+está tratando de averiguar si un conjunto de cambios dado es el que
+usted está buscando. La opción \hggopt{-v} (or \hggopt{--verbose}) del
+comando \hgcmd{log} le da este nivel extra de detalle.
+\interaction{tour.log-v}
+
+Si desea ver tanto la descripción como el contenido de un cambio,
+añada la opción \hgopt{log}{-p} (o \hgopt{log}{--patch}). Esto muestra
+% TODO qué hacemos con diff unificado? convervarlo, por ser la
+% acepción usual?
+el contenido de un cambio como un \emph{diff unificado} (si usted
+nunca ha visto un diff unificado antes, vea la
+sección~\ref{sec:mq:patch} para un vistazo global).
+\interaction{tour.log-vp}
+
+\section{Todo acerca de las opciones para comandos}
+
+Tomemos un breve descanso de la tarea de explorar los comandos de
+Mercurial para hablar de un patrón en la manera en que trabajan; será
+útil tener esto en mente a medida que avanza nuestra gira.
+
+Mercurial tiene un enfoque directo y consistente en el manejo de las
+opciones que usted le puede pasar a los comandos. Se siguen las
+convenciones para opciones que son comunes en sistemas Linux y Unix
+modernos.
+\begin{itemize}
+\item Cada opción tiene un nombre largo. Por ejemplo, el comando
+    \hgcmd{log} acepta la opción \hgopt{log}{--rev}, como ya hemos
+    visto.
+\item Muchas opciones tienen también un nombre corto. En vez de
+    \hgopt{log}{--rev}, podemos usar \hgopt{log}{-r}.  (El motivo para
+    que algunas opciones no tengan nombres cortos es que dichas
+    opciones se usan rara vez.)
+\item Las opciones largas empiezan con dos guiones (p.ej.~\hgopt{log}{--rev}),
+    mientras que las opciones cortas empiezan con uno (e.g.~\hgopt{log}{-r}).
+\item El nombre  y uso de las opciones es consistente en todos los
+    comandos. Por ejemplo, cada comando que le permite pasar un ID de
+    conjunto de cambios o un número de revisión acepta tanto la opción
+    \hgopt{log}{-r} como la \hgopt{log}{--rev}.
+\end{itemize}
+En los ejemplos en este libro, uso las opciones cortas en vez de las
+largas. Esto sólo muestra mis preferencias, así que no le dé
+significado especial a eso.
+
+Muchos de los comandos que generan salida de algún tipo mostrarán más
+salida cuando se les pase la opción \hggopt{-v} (o
+\hggopt{--verbose}\ndt{Prolijo.}), y menos cuando se les pase la opción \hggopt{-q}
+(o \hggopt{--quiet}\ndt{Silencioso.}).
+
+\section{Hacer y repasar cambios}
+
+Ahora que tenemos una comprensión adecuada sobre cómo revisar el
+historial en Mercurial, hagamos algunos cambios y veamos cómo
+examinarlos.
+
+Lo primero que haremos será aislar nuestro experimento en un
+repositorio propio. Usaremos el comando \hgcmd{clone}, pero no hace
+falta clonar una copia del repositorio remoto. Como ya contamos con
+una copia local del mismo, podemos clonar esa. Esto es mucho más
+rápido que clonar a través de la red, y en la mayoría de los casos
+clonar un repositorio local usa menos espacio en disco también.
+\interaction{tour.reclone}
+A manera de recomendación, es considerado buena práctica mantener una
+copia ``prístina'' de un repositorio remoto a mano, del cual usted
+puede hacer clones temporales para crear cajas de arena para cada
+tarea en la que desee trabajar. Esto le permite trabajar en múltiples
+tareas en paralelo, teniendo cada una de ellas aislada de las otras
+hasta que estén completas y usted esté listo para integrar los cambios
+de vuelta. Como los clones locales son tan baratos, clonar y destruir
+repositorios no consume demasiados recursos, lo que facilita hacerlo
+en cualquier momento.
+
+En nuestro repositorio \dirname{my-hello}, hay un fichero
+\filename{hello.c} que contiene el clásico programa ``hello,
+world''\ndt{Hola, mundo.}. Usaremos el clásico y venerado comando
+\command{sed} para editar este fichero y hacer que imprima una segunda
+línea de salida. (Estoy usando el comando \command{sed} para hacer
+esto sólo porque es fácil escribir un ejemplo automatizado con él.
+Dado que usted no tiene esta restricción, probablemente no querrá usar
+\command{sed}; use su editor de texto preferido para hacer lo mismo).
+\interaction{tour.sed}
+
+El comando \hgcmd{status} de Mercurial nos dice lo que Mercurial sabe
+acerca de los ficheros en el repositorio.
+\interaction{tour.status}
+El comando \hgcmd{status} no imprime nada para algunos ficheros, sólo
+una línea empezando con ``\texttt{M}'' para el fichero
+\filename{hello.c}. A menos que usted lo indique explícitamente,
+\hgcmd{status} no imprimirá nada respecto a los ficheros que no han
+sido modificados.
+
+La ``\texttt{M}'' indica que Mercurial se dio cuenta de que nosotros
+modificamos \filename{hello.c}.  No tuvimos que \emph{decirle} a
+Mercurial que íbamos a modificar ese fichero antes de hacerlo, o que
+lo modificamos una vez terminamos de hacerlo; él fue capaz de darse
+cuenta de esto por sí mismo.
+
+Es algo útil saber que hemos modificado el fichero \filename{hello.c},
+pero preferiríamos saber exactamente \emph{qué} cambios hicimos.
+Para averiguar esto, usamos el comando \hgcmd{diff}.
+\interaction{tour.diff}
+
+\section{Grabar cambios en un nuevo conjunto de cambios}
+
+Podemos modificar, compilar y probar nuestros cambios, y usar
+\hgcmd{status} y \hgcmd{diff} para revisar los mismos, hasta que
+estemos satisfechos con los resultados y lleguemos a un momento en el
+que sea natural que querramos guardar nuestro trabajo en un nuevo
+conjunto de cambios.
+
+El comando \hgcmd{commit} nos permite crear un nuevo conjunto de
+cambios. Nos referiremos usualmente a esto como ``hacer una consigna''
+o consignar.
+
+\subsection{Definir un nombre de usuario}
+
+Cuando usted trata de ejecutar \hgcmd{commit}\ndt{Hacer una
+consignación} por primera vez, no está garantizado que lo logre.
+Mercurial registra su nombre y dirección en cada cambio que usted
+consigna, para que más adelante otros puedan saber quién es el
+responsable de cada cambio. Mercurial trata de encontrar un nombre de
+% TODO consigna o consignación?
+usuario adecuado con el cual registrar la consignación. Se intenta con
+cada uno de los siguientes métodos, en el orden presentado.
+\begin{enumerate}
+\item Si usted pasa la opción \hgopt{commit}{-u} al comando \hgcmd{commit}
+  en la línea de comandos, seguido de un nombre de usuario, se le da a
+  esto la máxima precedencia.
+\item A continuación se revisa si usted ha definido la variable de
+    entorno \envar{HGUSER}.
+\item Si usted crea un fichero en su directorio personal llamado
+  \sfilename{.hgrc}, con una entrada \rcitem{ui}{username}, se usa
+  luego. Para revisar cómo debe verse este fichero, refiérase a la
+  sección~\ref{sec:tour-basic:username} más abajo.
+\item Si usted ha definido la variable de entorno \envar{EMAIL}, será
+    usada a continuación.
+\item Mercurial le pedirá a su sistema buscar su nombre de usuario
+    % TODO host => máquina
+    local, y el nombre de máquina, y construirá un nombre de usuario a
+    partir de estos componentes. Ya que esto generalmente termina
+    generando un nombre de usuario no muy útil, se imprimirá una
+    advertencia si es necesario hacerlo.
+\end{enumerate}
+Si todos estos procedimientos fallan, Mercurial fallará, e imprimirá
+un mensaje de error. En este caso, no le permitirá hacer la
+consignación hasta que usted defina un nombre de usuario.
+
+Trate de ver la variable de entorno \envar{HGUSER} y la opción
+\hgopt{commit}{-u} del comando \hgcmd{commit} como formas de
+\emph{hacer caso omiso} de la selección de nombre de usuario que
+Mercurial hace normalmente.  Para uso normal, la manera más simple y
+sencilla de definir un nombre de usuario para usted es crear un
+fichero \sfilename{.hgrc}; los detalles se encuentran más adelante.
+
+\subsubsection{Crear el fichero de configuración de Mercurial}
+\label{sec:tour-basic:username}
+
+Para definir un nombre de usuario, use su editor de texto favorito
+para crear un fichero llamado \sfilename{.hgrc} en su directorio
+personal. Mercurial usará este fichero para obtener las
+configuraciones personalizadas que usted haya hecho. El contenido
+inicial de su fichero \sfilename{.hgrc} debería verse así.
+\begin{codesample2}
+  # Este es un fichero de configuración de Mercurial.
+  [ui]
+  username = Primernombre Apellido <correo.electronico@dominio.net>
+\end{codesample2}
+La línea ``\texttt{[ui]}'' define una \emph{section} del fichero de
+configuración, así que usted puede leer la línea ``\texttt{username =
+...}'' como ``defina el valor del elemento \texttt{username} en la
+sección \texttt{ui}''.
+Una sección continua hasta que empieza otra nueva, o se llega al final
+del fichero. Mercurial ignora las líneas vacías y considera cualquier
+texto desde el caracter ``\texttt{\#}'' hasta el final de la línea
+como un comentario.
+
+\subsubsection{Escoger un nombre de usuario}
+
+Usted puede usar el texto que desee como el valor del campo de
+configuración \texttt{username}, ya que esta información será leída
+por otras personas, e interpretada por Mercurial. La convención que
+sigue la mayoría de la gente es usar su nombre y dirección de correo,
+como en el ejemplo anterior.
+
+\begin{note}
+    % TODO web
+    El servidor web integrado de Mercurial ofusca las direcciones de
+    correo, para dificultar la tarea de las herramientas de
+    recolección de direcciones de correo que usan los
+    spammers\ndt{Personas que envían correo no solicitado, también
+    conocido como correo basura}. Esto reduce la probabilidad de que
+    usted empiece a recibir más correo basura si publica un
+    repositorio en la red.
+\end{note}
+
+\subsection{Escribir un mensaje de consignación}
+
+Cuando consignamos un cambio, Mercurial nos ubica dentro de un editor
+de texto, para ingresar un mensaje que describa las modificaciones que
+hemos introducido en este conjunto de cambios. Esto es conocido como
+un \emph{mensaje de consignación}. Será un registro de lo que hicimos
+y porqué lo hicimos, y será impreso por \hgcmd{log} una vez hayamos
+hecho la consignación.
+\interaction{tour.commit}
+
+El editor en que \hgcmd{commit} nos ubica contendrá una línea vacía,
+seguida de varias líneas que empiezan con la cadena ``\texttt{HG:}''.
+\begin{codesample2}
+  \emph{línea vacía}
+  HG: changed hello.c
+\end{codesample2}
+Mercurial ignora las líneas que empiezan con ``\texttt{HG:}''; sólo
+las usa para indicarnos para cuáles ficheros está registrando los
+cambios. Modificar o borrar estas líneas no tiene ningún efecto.
+
+\subsection{Escribir un buen mensaje de consignación}
+
+Ya que por defecto \hgcmd{log} sólo muestra la primera línea de un
+mensaje de consignación, lo mejor es escribir un mensaje cuya primera
+línea tenga significado por sí misma. A continuación se encuentra un
+ejemplo de un mensaje de consignación que \emph{no} sigue esta
+pauta, y debido a ello tiene un sumario que no es legible.
+\begin{codesample2}
+  changeset:   73:584af0e231be
+  user:        Persona Censurada <persona.censurada@ejemplo.org>
+  date:        Tue Sep 26 21:37:07 2006 -0700
+  summary:     se incluye buildmeister/commondefs.   Añade un módulo
+\end{codesample2}
+
+Con respecto al resto del contenido del mensaje de consignación, no
+hay reglas estrictas-y-rápidas. Mercurial no interpreta ni le da
+importancia a los contenidos del mensaje de consignación, aunque es
+posible que su proyecto tenga políticas que definan una manera
+particular de escribirlo.
+
+Mi preferencia personal es usar mensajes de consignación cortos pero
+informativos, que me digan algo que no puedo inferir con una mirada
+rápida a la salida de \hgcmdargs{log}{--patch}.
+
+\subsection{Cancelar una consignación}
+
+Si usted decide que no desea hacer la consignación mientras está
+editando el mensaje de la misma, simplemente cierre su editor sin
+guardar los cambios al fichero que está editando. Esto hará que no
+pase nada ni en el repositorio ni en el directorio de trabajo.
+
+Si ejecutamos el comando \hgcmd{commit} sin ningún argumento, se
+registran todos los cambios que hemos hecho, como lo indican
+\hgcmd{status} y \hgcmd{diff}.
+
+\subsection{Admirar nuestro trabajo}
+
+Una vez hemos terminado la consignación, podemos usar el comando
+\hgcmd{tip}\ndt{Punta.} para mostrar el conjunto de cambios que acabamos de crear.
+La salida de este comando es idéntica a la de \hgcmd{log}, pero sólo
+muestra la revisión más reciente en el repositorio.
+\interaction{tour.tip}
+Nos referimos a la revisión más reciente en el repositorio como la
+revisión de punta, o simplemente la punta.
+
+\section{Compartir cambios}
+
+Anteriormente mencionamos que los repositorios en Mercurial están auto
+contenidos. Esto quiere decir que el conjunto de cambios que acabamos
+de crear sólo existe en nuestro repositorio \dirname{my-hello}. Veamos
+unas cuantas formas de propagar este cambio a otros repositorios.
+
+\subsection{Jalar cambios desde otro repositorio}
+\label{sec:tour:pull}
+
+Para empezar, clonemos nuestro repositorio \dirname{hello} original,
+el cual no contiene el cambio que acabamos de consignar. Llamaremos a
+este repositorio temporal \dirname{hello-pull}.
+\interaction{tour.clone-pull}
+
+Usaremos el comando \hgcmd{pull} para traer los cambios de
+\dirname{my-hello} y ponerlos en \dirname{hello-pull}.  Sin embargo,
+traer cambios desconocidos y aplicarlos en un repositorio es una
+perspectiva que asusta al menos un poco.  Mercurial cuenta con el
+comando \hgcmd{incoming}\ndt{Entrante, o cambios entrantes.} para
+decirnos qué cambios \emph{jalaría} el comando \hgcmd{pull} al
+repositorio, sin jalarlos.
+\interaction{tour.incoming}
+(Por supuesto, alguien podría enviar más conjuntos de cambios al
+repositorio en el tiempo que pasa entre la ejecución de
+\hgcmd{incoming} y la ejecución de \hgcmd{pull} para jalar los
+cambios, así que es posible que terminemos jalando cambios que no
+esperábamos.)
+
+Traer cambios al repositorio simplemente es cuestión de ejecutar el
+comando \hgcmd{pull}, indicándole de qué repositorio debe jalarlos.
+\interaction{tour.pull}
+Como puede verse por las salidas antes-y-después de \hgcmd{tip}, hemos
+jalado exitosamente los cambios en nuestro repositorio. Aún falta un
+paso para que podamos ver estos cambios en nuestro directorio de
+trabajo.
+
+\subsection{Actualizar el directorio de trabajo}
+
+Hasta ahora hemos pasado por alto la relación entre un repositorio y
+su directorio de trabajo. El comando \hgcmd{pull} que ejecutamos en la
+sección~\ref{sec:tour:pull} trajo los cambios al repositorio, pero si
+revisamos, no hay rastro de esos cambios en el directorio de trabajo.
+Esto pasa porque \hgcmd{pull} (por defecto) no modifica el directorio de
+trabajo. En vez de eso, usamos el comando
+\hgcmd{update}\ndt{Actualizar.} para hacerlo.
+\interaction{tour.update}
+
+Puede parecer algo raro que \hgcmd{pull} no actualice el directorio de
+trabajo automáticamente. De hecho, hay una buena razón para esto:
+usted puede usar \hgcmd{update} para actualizar el directorio de
+trabajo al estado en que se encontraba en \emph{cualquier revisión}
+del historial del repositorio. Si usted hubiera actualizado el
+directorio de trabajo a una revisión anterior---digamos, para buscar
+el origen de un fallo---y hubiera corrido un \hgcmd{pull} que hubiera
+actualizado el directorio de trabajo automáticamente a la nueva
+revisión, puede que no estuviera particularmente contento.
+
+Sin embargo, como jalar-y-actualizar es una secuencia de operaciones
+muy común, Mercurial le permite combinarlas al pasar la opción
+\hgopt{pull}{-u}
+a \hgcmd{pull}.
+\begin{codesample2}
+  hg pull -u
+\end{codesample2}
+Si mira de vuelta la salida de \hgcmd{pull} en la
+sección~\ref{sec:tour:pull} cuando lo ejecutamos sin la opción \hgopt{pull}{-u},
+verá que el comando imprimió un amable recordatorio de que tenemos que
+encargarnos explícitamente de actualizar el directorio de trabajo:
+\begin{codesample2}
+  (run 'hg update' to get a working copy)
+\end{codesample2}
+
+Para averiguar en qué revisión se encuentra el directorio de trabajo,
+use el comando \hgcmd{parents}.
+\interaction{tour.parents}
+Si mira de nuevo la figura~\ref{fig:tour-basic:history}, verá flechas
+conectando cada conjunto de cambios. En cada caso, el nodo del que la flecha
+\emph{sale} es un padre, y el nodo al que la flecha \emph{llega} es 
+su hijo. El directorio de trabajo tiene un padre exactamente de la
+misma manera; ése es el conjunto de cambios que contiene actualmente
+el directorio de trabajo.
+
+Para actualizar el conjunto de trabajo a una revisión particular, pase
+un número de revisión o un ID de conjunto de cambios al comando
+\hgcmd{update}.
+\interaction{tour.older}
+Si no indica explícitamente una revisión, \hgcmd{update} actualizará
+hasta la revisión de punta, como se vio en la segunda llamada a
+\hgcmd{update} en el ejemplo anterior.
+
+\subsection{Empujar cambios a otro repositorio}
+
+Mercurial nos permite empujar cambios a otro repositorio, desde el
+% TODO cambié "visitando" por "usando"
+repositorio que estemos usando actualmente. De la misma forma que en
+el ejemplo de \hgcmd{pull} arriba, crearemos un repositorio temporal
+para empujar allí nuestros cambios.
+\interaction{tour.clone-push}
+El comando \hgcmd{outgoing}\ndt{Saliente. Cambios salientes.} nos dice
+qué cambios serían empujados en el otro repositorio.
+\interaction{tour.outgoing}
+Y el comando \hgcmd{push} se encarga de empujar dichos cambios.
+\interaction{tour.push}
+Al igual que \hgcmd{pull}, el comando \hgcmd{push} no actualiza el
+directorio de trabajo del repositorio en el que estamos empujando los
+cambios.  (A diferencia de \hgcmd{pull}, \hgcmd{push} no ofrece la
+opción \texttt{-u} para actualizar el directorio de trabajo del otro
+repositorio.)
+
+% TODO poner interrogante de apertura
+Qué pasa si tratamos de jalar o empujar cambios y el repositorio
+receptor ya tiene esos cambios? Nada emocionante.
+\interaction{tour.push.nothing}
+
+\subsection{Compartir cambios a través de una red}
+
+Los comandos que hemos presentando en las pocas secciones anteriores
+no están limitados a trabajar con repositorios locales. Cada uno de
+ellos funciona exactamente de la misma manera a través de una conexión
+% TODO poner ndt para URL
+de red. Simplemente pase una URL en vez de una ruta local.
+\interaction{tour.outgoing.net}
+En este ejemplo, podemos ver qué cambios empujaríamos al repositorio
+remoto, aunque, de manera entendible, el repositorio remoto está
+configurado para no permitir a usuarios anónimos empujar cambios a él.
+\interaction{tour.push.net}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/tour-history.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,298 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="tour-history.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective2812" />
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path2973"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3066"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4"
+     inkscape:cx="232.14286"
+     inkscape:cy="672.75296"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="5"
+     inkscape:window-y="49"
+     showgrid="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       style="opacity:1;fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1878"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="479.50504" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="493.12619"
+       id="text1872"><tspan
+         sodipodi:role="line"
+         id="tspan1874"
+         x="162.09892"
+         y="493.12619"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan1876">0</tspan>: REV0</tspan></text>
+    <rect
+       style="opacity:1;fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2800"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="432.63004" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="446.25119"
+       id="text2794"><tspan
+         sodipodi:role="line"
+         id="tspan2796"
+         x="162.09892"
+         y="446.25119"
+         style="font-family:Courier"><tspan
+   id="tspan2868"
+   style="font-weight:bold">1</tspan>: REV1</tspan></text>
+    <rect
+       style="opacity:1;fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2810"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="385.75504" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="399.37619"
+       id="text2804"><tspan
+         sodipodi:role="line"
+         id="tspan2806"
+         x="162.09892"
+         y="399.37619"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2866">2</tspan>: REV2</tspan></text>
+    <rect
+       style="opacity:1;fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2820"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="338.88007" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="352.50122"
+       id="text2814"><tspan
+         sodipodi:role="line"
+         id="tspan2816"
+         x="162.09892"
+         y="352.50122"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2864">3</tspan>: REV3</tspan></text>
+    <rect
+       style="opacity:1;fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2830"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="292.00504" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="305.62619"
+       id="text2824"><tspan
+         sodipodi:role="line"
+         id="tspan2826"
+         x="162.09892"
+         y="305.62619"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2862">4</tspan>: REV4</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="173.57143"
+       y="443.79074"
+       id="text2832"><tspan
+         sodipodi:role="line"
+         id="tspan2834"
+         x="173.57143"
+         y="443.79074" /></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="M 185.14286,478.50504 L 185.14286,454.34432"
+       id="path2894"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="M 185.14286,431.63004 L 185.14286,407.46932"
+       id="path2896"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="M 185.14286,384.75504 L 185.14286,360.59435"
+       id="path2898"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="M 185.14286,337.88007 L 185.14286,313.71932"
+       id="path2900"
+       inkscape:connector-type="polyline" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times"
+       x="244.60992"
+       y="305.245"
+       id="text1902"><tspan
+         sodipodi:role="line"
+         id="tspan1904"
+         x="244.60992"
+         y="305.245">(la más nueva)</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times"
+       x="244.60992"
+       y="492.745"
+       id="text1906"><tspan
+         sodipodi:role="line"
+         id="tspan1908"
+         x="244.60992"
+         y="492.745">(la más antigua)</tspan></text>
+    <rect
+       style="opacity:1;fill:#d2e1e4;fill-opacity:1;stroke:#b1cbd0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1907"
+       width="94.285713"
+       height="20.714285"
+       x="309.28571"
+       y="324.86218" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="333.38464"
+       y="338.48334"
+       id="text1909"><tspan
+         sodipodi:role="line"
+         id="tspan1911"
+         x="333.38464"
+         y="338.48334"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan1913">4</tspan>: REV4</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 332.14286,375.21932 L 335.71429,347.36218"
+       id="path2802" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 372.69968,375.21932 L 369.12825,347.36218"
+       id="path2986" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times"
+       x="335.14285"
+       y="387.21933"
+       id="text2988"><tspan
+         sodipodi:role="line"
+         x="335.14285"
+         y="387.21933"
+         id="tspan3020"
+         style="text-align:end;text-anchor:end">número de</tspan><tspan
+         sodipodi:role="line"
+         x="335.14285"
+         y="402.21933"
+         id="tspan3014"
+         style="text-align:end;text-anchor:end">revisión</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times"
+       x="368.71429"
+       y="387.21933"
+       id="text2994"><tspan
+         sodipodi:role="line"
+         id="tspan2996"
+         x="368.71429"
+         y="387.21933">identificador del</tspan><tspan
+         sodipodi:role="line"
+         x="368.71429"
+         y="402.21933"
+         id="tspan2998">conjunto de cambios</tspan></text>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/tour-merge-conflict.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="tour-merge-conflict.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective2861" />
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3053"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4"
+     inkscape:cx="251.65243"
+     inkscape:cy="733.42197"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="5"
+     inkscape:window-y="49"
+     showgrid="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <g
+       id="g1988"
+       transform="translate(84.85711,0)">
+      <g
+         id="g1876">
+        <path
+           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="M 118.57143,458.21933 L 118.57143,563.79075 L 191.42857,563.79075 L 204.28571,550.93361 L 203.57142,459.6479 L 118.57143,458.21933 z "
+           id="path1872"
+           sodipodi:nodetypes="cccccc" />
+        <path
+           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242"
+           id="path1874"
+           sodipodi:nodetypes="cccc" />
+      </g>
+      <flowRoot
+         style="font-size:8px;font-family:Times New Roman"
+         id="flowRoot1898"
+         xml:space="preserve"><flowRegion
+           id="flowRegion1900"><rect
+             style="font-size:8px;font-family:Times New Roman"
+             y="464.50504"
+             x="122.85714"
+             height="93.571426"
+             width="76.428574"
+             id="rect1902" /></flowRegion><flowPara
+           id="flowPara1904">Saludos!</flowPara><flowPara
+           id="flowPara1906" /><flowPara
+           id="flowPara1908">Soy Mariam Abacha, la esposa del anterior dictador de Nigeria Sani Abacha. Le contacto en secreto, buscando los medios para desarrollar</flowPara></flowRoot>    </g>
+    <g
+       id="g1966"
+       transform="translate(82,0.35715)">
+      <g
+         transform="translate(-77.85718,-140.0714)"
+         id="g1910">
+        <path
+           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="M 118.57143,458.21933 L 118.57143,563.79075 L 191.42857,563.79075 L 204.28571,550.93361 L 203.57142,459.6479 L 118.57143,458.21933 z "
+           id="path1912"
+           sodipodi:nodetypes="cccccc" />
+        <path
+           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242"
+           id="path1914"
+           sodipodi:nodetypes="cccc" />
+      </g>
+      <flowRoot
+         transform="translate(-77.85718,-140.0714)"
+         style="font-size:8px;font-family:Times New Roman"
+         id="flowRoot1916"
+         xml:space="preserve"><flowRegion
+           id="flowRegion1918"><rect
+             style="font-size:8px;font-family:Times New Roman"
+             y="464.50504"
+             x="122.85714"
+             height="93.571426"
+             width="76.428574"
+             id="rect1920" /></flowRegion><flowPara
+           id="flowPara1922">Saludos!</flowPara><flowPara
+           id="flowPara1924" /><flowPara
+           id="flowPara1926">Soy <flowSpan
+   style="font-style:italic;fill:#ff0000"
+   id="flowSpan3094">Shehu Musa Abacha, sobrina del</flowSpan> anterior dictador de Nigeria Sani Abacha. Le contacto en secreto, buscando los medios para desarrollar</flowPara></flowRoot>    </g>
+    <g
+       id="g1977"
+       transform="translate(81.99999,-0.35715)">
+      <g
+         transform="translate(83.57141,-139.3571)"
+         id="g1932">
+        <path
+           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="M 118.57143,458.21933 L 118.57143,563.79075 L 191.42857,563.79075 L 204.28571,550.93361 L 203.57142,459.6479 L 118.57143,458.21933 z "
+           id="path1934"
+           sodipodi:nodetypes="cccccc" />
+        <path
+           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+           d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242"
+           id="path1936"
+           sodipodi:nodetypes="cccc" />
+      </g>
+      <flowRoot
+         transform="translate(83.57141,-139.3571)"
+         style="font-size:8px;font-family:Times New Roman"
+         id="flowRoot1938"
+         xml:space="preserve"><flowRegion
+           id="flowRegion1940"><rect
+             style="font-size:8px;font-family:Times New Roman"
+             y="464.50504"
+             x="122.85714"
+             height="93.571426"
+             width="76.428574"
+             id="rect1942" /></flowRegion><flowPara
+           id="flowPara1944">Saludos!</flowPara><flowPara
+           id="flowPara1946" /><flowPara
+           id="flowPara1948">Soy <flowSpan
+   style="font-style:italic;fill:#ff0000"
+   id="flowSpan3096">Alhaji Abba Abacha, hijo del</flowSpan> anterior dictador de Nigeria Sani Abacha. Le contacto en secreto, buscando los medios para desarrollar</flowPara></flowRoot>    </g>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 215.502,457.71933 L 196.35507,424.5765"
+       id="path1999"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g1988"
+       inkscape:connection-end="#g1966" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 277.06936,457.71933 L 296.21629,424.5765"
+       id="path2001"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g1988"
+       inkscape:connection-end="#g1977" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="302.42859"
+       y="515.08905"
+       id="text1905"><tspan
+         sodipodi:role="line"
+         id="tspan1907"
+         x="302.42859"
+         y="515.08905">Versión inicial</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="30.57143"
+       y="374.1619"
+       id="text1917"><tspan
+         sodipodi:role="line"
+         id="tspan1919"
+         x="30.57143"
+         y="374.1619">Nuestros cambios</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="385.71429"
+       y="374.1619"
+       id="text1921"><tspan
+         sodipodi:role="line"
+         id="tspan1923"
+         x="385.71429"
+         y="374.1619">Sus cambios</tspan></text>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/tour-merge-merge.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,389 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="tour-merge-merge.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective2928" />
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path2973"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3066"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.98994949"
+     inkscape:cx="328.35015"
+     inkscape:cy="790.24518"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="1278"
+     inkscape:window-height="756"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     showgrid="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2995"
+       width="94.285713"
+       height="20.714285"
+       x="532.85718"
+       y="203.0479" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="173.57143"
+       y="443.79074"
+       id="text2832"><tspan
+         sodipodi:role="line"
+         id="tspan2834"
+         x="173.57143"
+         y="443.79074" /></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2830"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="297.76227" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="311.38342"
+       id="text2824"><tspan
+         sodipodi:role="line"
+         id="tspan2826"
+         x="162.09892"
+         y="311.38342"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2862">4</tspan>: REV4</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 185.14286,343.63731 L 185.14286,319.47656"
+       id="path2900"
+       inkscape:connector-type="polyline" />
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2863"
+       width="94.285713"
+       height="20.714285"
+       x="91.428574"
+       y="250.47656" />
+    <text
+       xml:space="preserve"
+       style="font-size:12.00001812px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="116.09886"
+       y="264.56592"
+       id="text1965"
+       transform="scale(1.000002,0.999998)"><tspan
+         sodipodi:role="line"
+         id="tspan1967"
+         x="116.09886"
+         y="264.56592"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan1973">5</tspan>: REV_my_new_hello</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.00000143px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       d="M 173.95727,296.76228 L 149.75702,272.19085"
+       id="path1971"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#rect2863"
+       inkscape:connection-start="#rect2830" />
+    <rect
+       style="fill:#78a5ad;fill-opacity:1;stroke:#507b84;stroke-width:2.00000286;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2911"
+       width="94.285995"
+       height="20.714283"
+       x="186.71414"
+       y="204.40514" />
+    <text
+       xml:space="preserve"
+       style="font-size:12.00001812px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="210.81311"
+       y="218.02673"
+       id="text2913"
+       transform="scale(1.000002,0.999998)"><tspan
+         sodipodi:role="line"
+         id="tspan2915"
+         x="210.81311"
+         y="218.02673"
+         style="font-family:Courier"><tspan
+   id="tspan1966"
+   style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.00000143px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       d="M 191.06908,296.76228 L 227.93092,226.11942"
+       id="path2919"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect2830" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman;text-anchor:start;text-align:start;writing-mode:lr;line-height:125%"
+       x="295.28571"
+       y="217.56711"
+       id="text2871"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan2441">punta (y frente)</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="57.817253"
+       y="263.90753"
+       id="text2875"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan2439"
+         x="57.817253"
+         y="263.90753">frente</tspan></text>
+    <rect
+       style="fill:#c8aaa5;fill-opacity:1;stroke:#a07163;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:2, 4;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect1913"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="156.90514" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 144.22399,249.47657 L 179.49029,178.61943"
+       id="path1915"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect2863"
+       inkscape:connection-end="#rect1913" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 222.20966,203.40514 L 196.79033,178.61943"
+       id="path1917"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect2911"
+       inkscape:connection-end="#rect1913" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="166.16823"
+       y="168.52228"
+       id="text2806"><tspan
+         sodipodi:role="line"
+         id="tspan2808"
+         x="166.16823"
+         y="168.52228"
+         style="font-family:Courier">fusión</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="246"
+       y="162.63338"
+       id="text2810"><tspan
+         sodipodi:role="line"
+         x="246"
+         y="162.63338"
+         id="tspan2814">directorio de trabajo</tspan><tspan
+         sodipodi:role="line"
+         x="246"
+         y="177.63338"
+         id="tspan3538">durante la fusión</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2816"
+       width="94.285713"
+       height="20.714285"
+       x="483.14636"
+       y="297.76227" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="507.24527"
+       y="311.38342"
+       id="text2818"><tspan
+         sodipodi:role="line"
+         id="tspan2820"
+         x="507.24527"
+         y="311.38342"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2822">4</tspan>: REV4</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 530.28921,343.6373 L 530.28921,319.47655"
+       id="path2824"
+       inkscape:connector-type="polyline" />
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2826"
+       width="94.285713"
+       height="20.714285"
+       x="436.57492"
+       y="250.47656" />
+    <text
+       xml:space="preserve"
+       style="font-size:12.00001812px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="461.24484"
+       y="264.56613"
+       id="text2828"
+       transform="scale(1.000002,0.999998)"><tspan
+         sodipodi:role="line"
+         id="tspan2830"
+         x="461.24484"
+         y="264.56613"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2832">5</tspan>: REV_my_new_hello</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.00000143px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       d="M 519.10362,296.76227 L 494.90337,272.19084"
+       id="path2834"
+       inkscape:connector-type="polyline" />
+    <rect
+       style="fill:#78a5ad;fill-opacity:1;stroke:#507b84;stroke-width:2.00000286;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2836"
+       width="94.285995"
+       height="20.714283"
+       x="483.14001"
+       y="156.548" />
+    <text
+       xml:space="preserve"
+       style="font-size:12.00001812px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="555.95911"
+       y="218.02698"
+       id="text2838"
+       transform="scale(1.000002,0.999998)"><tspan
+         sodipodi:role="line"
+         id="tspan2840"
+         x="555.95911"
+         y="218.02698"
+         style="font-family:Courier"><tspan
+   id="tspan2842"
+   style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.00000143px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       d="M 536.21543,296.76227 L 574.03453,224.76218"
+       id="path2844"
+       inkscape:connector-type="polyline" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="452.00058"
+       y="167.76765"
+       id="text2846"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan2443"
+         x="452.00058"
+         y="167.76765">punta</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 489.37034,249.47656 L 524.65575,178.26229"
+       id="path2856"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#rect2836" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+       d="M 567.85714,202.0479 L 542.42591,178.26229"
+       id="path2858"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#rect2836"
+       inkscape:connection-start="#rect2995" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="490.40295"
+       y="170.39714"
+       id="text2860"><tspan
+         sodipodi:role="line"
+         id="tspan2863"
+         x="490.40295"
+         y="170.39714"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2997">7</tspan>: REV7_my_new_hello</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="90.323105"
+       y="120.21933"
+       id="text2929"><tspan
+         sodipodi:role="line"
+         id="tspan2931"
+         x="90.323105"
+         y="120.21933"
+         style="font-weight:bold">Directorio de trabajo durante la fusión</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="435.35226"
+       y="120.21933"
+       id="text2937"><tspan
+         sodipodi:role="line"
+         id="tspan2939"
+         x="435.35226"
+         y="120.21933"
+         style="font-weight:bold">Repositorio después de consignar la fusión</tspan></text>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/tour-merge-pull.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="tour-merge-pull.svg"
+   sodipodi:docbase="/home/bos/hg/hgbook/en"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective2979" />
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path2973"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3066"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4"
+     inkscape:cx="233.63208"
+     inkscape:cy="704.83702"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="237"
+     inkscape:window-y="103"
+     showgrid="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="173.57143"
+       y="443.79074"
+       id="text2832"><tspan
+         sodipodi:role="line"
+         id="tspan2834"
+         x="173.57143"
+         y="443.79074" /></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1878"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="479.50504" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="493.12619"
+       id="text1872"><tspan
+         sodipodi:role="line"
+         id="tspan1874"
+         x="162.09892"
+         y="493.12619"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan1876">0</tspan>: REV0</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2800"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="432.63004" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="446.25119"
+       id="text2794"><tspan
+         sodipodi:role="line"
+         id="tspan2796"
+         x="162.09892"
+         y="446.25119"
+         style="font-family:Courier"><tspan
+   id="tspan2868"
+   style="font-weight:bold">1</tspan>: REV1</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2810"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="385.75504" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="399.37619"
+       id="text2804"><tspan
+         sodipodi:role="line"
+         id="tspan2806"
+         x="162.09892"
+         y="399.37619"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2866">2</tspan>: REV2</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2820"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="338.88007" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="352.50122"
+       id="text2814"><tspan
+         sodipodi:role="line"
+         id="tspan2816"
+         x="162.09892"
+         y="352.50122"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2864">3</tspan>: REV3</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2830"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="292.00504" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="305.62619"
+       id="text2824"><tspan
+         sodipodi:role="line"
+         id="tspan2826"
+         x="162.09892"
+         y="305.62619"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2862">4</tspan>: REV4</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 185.14286,478.50504 L 185.14286,454.34432"
+       id="path2894"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 185.14286,431.63004 L 185.14286,407.46932"
+       id="path2896"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 185.14286,384.75504 L 185.14286,360.59435"
+       id="path2898"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 185.14286,337.88007 L 185.14286,313.71932"
+       id="path2900"
+       inkscape:connector-type="polyline" />
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2863"
+       width="94.285713"
+       height="20.714285"
+       x="91.428574"
+       y="244.71933" />
+    <text
+       xml:space="preserve"
+       style="font-size:12.00001812px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="116.09886"
+       y="258.80865"
+       id="text1965"
+       transform="scale(1.000002,0.999998)"><tspan
+         sodipodi:role="line"
+         id="tspan1967"
+         x="116.09886"
+         y="258.80865"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan1973">5</tspan>: REV_my_new_hello</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.00000143px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       d="M 173.95727,291.00504 L 149.75702,266.43361"
+       id="path1971"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#rect2863"
+       inkscape:connection-start="#rect2830" />
+    <rect
+       style="fill:#78a5ad;fill-opacity:1;stroke:#507b84;stroke-width:2.00000286;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2911"
+       width="94.285995"
+       height="20.714283"
+       x="186.71414"
+       y="198.6479" />
+    <text
+       xml:space="preserve"
+       style="font-size:12.00001812px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="210.81311"
+       y="212.26949"
+       id="text2913"
+       transform="scale(1.000002,0.999998)"><tspan
+         sodipodi:role="line"
+         id="tspan2915"
+         x="210.81311"
+         y="212.26949"
+         style="font-family:Courier"><tspan
+   id="tspan1966"
+   style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.00000143px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       d="M 191.06908,291.00504 L 227.93092,220.36218"
+       id="path2919"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#rect2830" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="291"
+       y="225.3813"
+       id="text2871"><tspan
+         sodipodi:role="line"
+         id="tspan2873"
+         x="291"
+         y="225.3813">tip (y principal)</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="76"
+       y="259.16046"
+       id="text2875"><tspan
+         sodipodi:role="line"
+         id="tspan2877"
+         x="76"
+         y="259.16046"
+         style="text-align:end;text-anchor:end">principal</tspan></text>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/tour-merge-sep-repos.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,480 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg2"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docname="tour-merge-sep-repos.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs4">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective3067" />
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path2973"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path3066"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.4"
+     inkscape:cx="307.20351"
+     inkscape:cy="683.39831"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="5"
+     inkscape:window-y="49"
+     showgrid="false" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="173.57143"
+       y="443.79074"
+       id="text2832"><tspan
+         sodipodi:role="line"
+         id="tspan2834"
+         x="173.57143"
+         y="443.79074" /></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1878"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="479.50504" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="493.12619"
+       id="text1872"><tspan
+         sodipodi:role="line"
+         id="tspan1874"
+         x="162.09892"
+         y="493.12619"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan1876">0</tspan>: REV0</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2800"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="432.63004" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="446.25119"
+       id="text2794"><tspan
+         sodipodi:role="line"
+         id="tspan2796"
+         x="162.09892"
+         y="446.25119"
+         style="font-family:Courier"><tspan
+   id="tspan2868"
+   style="font-weight:bold">1</tspan>: REV1</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2810"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="385.75504" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="399.37619"
+       id="text2804"><tspan
+         sodipodi:role="line"
+         id="tspan2806"
+         x="162.09892"
+         y="399.37619"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2866">2</tspan>: REV2</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2820"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="338.88007" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="352.50122"
+       id="text2814"><tspan
+         sodipodi:role="line"
+         id="tspan2816"
+         x="162.09892"
+         y="352.50122"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2864">3</tspan>: REV3</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2830"
+       width="94.285713"
+       height="20.714285"
+       x="138"
+       y="292.00504" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09892"
+       y="305.62619"
+       id="text2824"><tspan
+         sodipodi:role="line"
+         id="tspan2826"
+         x="162.09892"
+         y="305.62619"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2862">4</tspan>: REV4</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 185.14286,478.50504 L 185.14286,454.34432"
+       id="path2894"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 185.14286,431.63004 L 185.14286,407.46932"
+       id="path2896"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 185.14286,384.75504 L 185.14286,360.59435"
+       id="path2898"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 185.14286,337.88007 L 185.14286,313.71932"
+       id="path2900"
+       inkscape:connector-type="polyline" />
+    <rect
+       style="fill:#78a5ad;fill-opacity:1;stroke:#507b84;stroke-width:2.00000286;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect1963"
+       width="94.285995"
+       height="20.714283"
+       x="138"
+       y="245.18723" />
+    <text
+       xml:space="preserve"
+       style="font-size:12.00001812px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="162.09877"
+       y="258.80865"
+       id="text1965"
+       transform="scale(1.000002,0.999998)"><tspan
+         sodipodi:role="line"
+         id="tspan1967"
+         x="162.09877"
+         y="258.80865"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan1973">5</tspan>: REV_my_hello</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.00000143px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 185.143,291.06218 L 185.143,266.90143"
+       id="path1971"
+       inkscape:connector-type="polyline" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="136.90039"
+       y="232.25546"
+       id="text2921"><tspan
+         sodipodi:role="line"
+         id="tspan2923"
+         x="136.90039"
+         y="232.25546">my-hello</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2863"
+       width="94.285713"
+       height="20.714285"
+       x="370.71414"
+       y="479.49289" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="394.81305"
+       y="493.11404"
+       id="text2865"><tspan
+         sodipodi:role="line"
+         id="tspan2867"
+         x="394.81305"
+         y="493.11404"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2869">0</tspan>: REV0</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2871"
+       width="94.285713"
+       height="20.714285"
+       x="370.71414"
+       y="432.61789" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="394.81305"
+       y="446.23904"
+       id="text2873"><tspan
+         sodipodi:role="line"
+         id="tspan2875"
+         x="394.81305"
+         y="446.23904"
+         style="font-family:Courier"><tspan
+   id="tspan2877"
+   style="font-weight:bold">1</tspan>: REV1</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2879"
+       width="94.285713"
+       height="20.714285"
+       x="370.71414"
+       y="385.74289" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="394.81305"
+       y="399.36404"
+       id="text2881"><tspan
+         sodipodi:role="line"
+         id="tspan2883"
+         x="394.81305"
+         y="399.36404"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2885">2</tspan>: REV2</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2887"
+       width="94.285713"
+       height="20.714285"
+       x="370.71414"
+       y="338.86792" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="394.81305"
+       y="352.48907"
+       id="text2889"><tspan
+         sodipodi:role="line"
+         id="tspan2891"
+         x="394.81305"
+         y="352.48907"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2893">3</tspan>: REV3</tspan></text>
+    <rect
+       style="fill:#a5c3c8;fill-opacity:1;stroke:#6396a0;stroke-width:2;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2895"
+       width="94.285713"
+       height="20.714285"
+       x="370.71414"
+       y="291.99289" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="394.81305"
+       y="305.61404"
+       id="text2897"><tspan
+         sodipodi:role="line"
+         id="tspan2899"
+         x="394.81305"
+         y="305.61404"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2901">4</tspan>: REV4</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 417.85701,478.4929 L 417.85701,454.33218"
+       id="path2903"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 417.85701,431.6179 L 417.85701,407.45718"
+       id="path2905"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 417.85701,384.7429 L 417.85701,360.58221"
+       id="path2907"
+       inkscape:connector-type="polyline" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 417.85701,337.86793 L 417.85701,313.70718"
+       id="path2909"
+       inkscape:connector-type="polyline" />
+    <rect
+       style="fill:#78a5ad;fill-opacity:1;stroke:#507b84;stroke-width:2.00000286;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2911"
+       width="94.285995"
+       height="20.714283"
+       x="370.71414"
+       y="245.17511" />
+    <text
+       xml:space="preserve"
+       style="font-size:12.00001812px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Courier"
+       x="394.81274"
+       y="258.79678"
+       id="text2913"
+       transform="scale(1.000002,0.999998)"><tspan
+         sodipodi:role="line"
+         id="tspan2915"
+         x="394.81274"
+         y="258.79678"
+         style="font-family:Courier"><tspan
+   style="font-weight:bold"
+   id="tspan2917">5</tspan>: REV_my_new_hello</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1.00000143px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+       d="M 417.85715,291.05004 L 417.85715,266.88929"
+       id="path2919"
+       inkscape:connector-type="polyline" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="369.61453"
+       y="232.25546"
+       id="text2925"><tspan
+         sodipodi:role="line"
+         id="tspan2927"
+         x="369.61453"
+         y="232.25546">my-new-hello</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="300.54352"
+       y="252.12723"
+       id="text2933"><tspan
+         sodipodi:role="line"
+         id="tspan2935"
+         x="300.54352"
+         y="252.12723"
+         style="text-align:center;text-anchor:middle">Los cambios</tspan><tspan
+         sodipodi:role="line"
+         x="300.54352"
+         y="267.12723"
+         style="text-align:center;text-anchor:middle"
+         id="tspan3494">más recientes</tspan><tspan
+         sodipodi:role="line"
+         x="300.54352"
+         y="282.12723"
+         style="text-align:center;text-anchor:middle"
+         id="tspan3132">difieren</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;text-align:start;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="262.15436"
+       y="398.37112"
+       id="text2929"><tspan
+         sodipodi:role="line"
+         x="262.15436"
+         y="398.37112"
+         id="tspan3013"
+         style="text-align:start;text-anchor:start">historia común</tspan></text>
+    <g
+       id="g3107"
+       transform="translate(0,0.855744)">
+      <path
+         id="path3101"
+         d="M 300.35713,381.29075 L 300.35713,304.50504"
+         style="fill:black;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:4, 4;stroke-dashoffset:0;stroke-opacity:1" />
+      <path
+         id="path3105"
+         d="M 291.07142,301.64789 L 309.28571,301.64789"
+         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#bfbfbf;stroke-width:0.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    </g>
+    <path
+       style="fill:black;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:4, 4;stroke-dashoffset:0;stroke-opacity:1"
+       d="M 300.53571,486.38926 L 300.53571,409.60355"
+       id="path3113" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#bfbfbf;stroke-width:0.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 291.25,488.49641 L 309.46429,488.49641"
+       id="path3115" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="480.71429"
+       y="250.91507"
+       id="text1949"><tspan
+         sodipodi:role="line"
+         id="tspan1951"
+         x="480.71429"
+         y="250.91507"
+         style="text-align:start;text-anchor:start">revisión principal</tspan><tspan
+         sodipodi:role="line"
+         x="480.71429"
+         y="265.91507"
+         id="tspan1953"
+         style="text-align:start;text-anchor:start">     (sin hijos)</tspan></text>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/tour-merge.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,308 @@
+\chapter{Una gira de Mercurial: fusionar trabajo}
+\label{chap:tour-merge}
+
+Hasta ahora hemos cubierto cómo clonar un repositorio, hacer cambios,
+y jalar o empujar dichos cambios de un repositorio a otro. Nuestro
+siguiente paso es \emph{fusionar} cambios de repositorios separados.
+
+% TODO cambié streams por líneas. check please
+\section{Fusionar líneas de trabajo}
+
+Fusionar es una parte fundamental de trabajar con una herramienta 
+de control distribuido de versiones.
+\begin{itemize}
+\item Alicia y Roberto tienen cada uno una copia personal del
+    repositorio de un proyecto en el que están trabajando. Alicia
+    arregla un fallo en su repositorio; Roberto añade una nueva
+    característica en el suyo. Ambos desean que el repositorio
+    compartido contenga el arreglo del fallo y la nueva
+    característica.
+\item Frecuentemente trabajo en varias tareas diferentes en un mismo
+    proyecto al mismo tiempo, cada una aislada convenientemente de las
+    otras en su propio repositorio. Trabajar de esta manera significa
+    que a menudo debo fusionar una parte de mi propio trabajo con
+    otra.
+\end{itemize}
+
+Como fusionar es una operación tan necesaria y común, Mercurial la
+facilita. Revisemos el proceso. Empezaremos clonando (otro)
+% TODO poner interrogante de apertura
+repositorio (ve lo seguido que aparecen?) y haciendo un cambio en él.
+\interaction{tour.merge.clone}
+Ahora deberíamos tener dos copias de \filename{hello.c} con contenidos
+diferentes.  El historial de los dos repositorios diverge ahora, como
+se ilustra en la figura~\ref{fig:tour-merge:sep-repos}.
+\interaction{tour.merge.cat}
+
+\begin{figure}[ht]
+  \centering
+  \grafix{tour-merge-sep-repos}
+  \caption{Historial reciente divergente de los repositorios
+      \dirname{my-hello} y \dirname{my-new-hello}}
+  \label{fig:tour-merge:sep-repos}
+\end{figure}
+
+Ya sabemos que jalar los cambios desde nuestro repositorio
+\dirname{my-hello} no tendrá efecto en el directorio de trabajo.
+\interaction{tour.merge.pull}
+Sin embargo, el comando \hgcmd{pull} dice algo acerca de
+``frentes''\ndt{El autor se refiere a \emph{heads} aquí.}.  
+
+\subsection{Conjuntos de cambios de frentes}
+
+Un frente es un cambio que no tiene descendientes, o hijos, como
+también se les conoce. La revisión de punta es, por tanto, un frente,
+porque la revisión más reciente en un repositorio no tiene ningún
+% TODO cambio en la redacción de la frase, pero espero que conserve el
+% sentido. Querido human@, apruebe o corrija :D
+hijo. Sin embargo, un repositorio puede contener más de un frente.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{tour-merge-pull}
+  \caption{Contenidos del repositorio después de jalar
+      \dirname{my-hello} a \dirname{my-new-hello}}
+  \label{fig:tour-merge:pull}
+\end{figure}
+
+En la figura~\ref{fig:tour-merge:pull} usted puede ver el efecto que
+tiene jalar los cambios de \dirname{my-hello} a \dirname{my-new-hello}.
+El historial que ya existía en \dirname{my-new-hello} se mantiene
+intacto, pero fue añadida una nueva revisión. Refiriéndonos a la
+figura~\ref{fig:tour-merge:sep-repos}, podemos ver que el \emph{ID del
+conjunto de cambios} se mantiene igual en el nuevo repositorio, pero
+el \emph{número de revisión} ha cambiado.  (Incidentalmente, éste es un
+buen ejemplo de porqué no es seguro usar números de revisión cuando se
+habla de conjuntos de cambios).  Podemos ver los frentes en un
+repositorio usando el comando \hgcmd{heads}\ndt{Frentes.}.
+\interaction{tour.merge.heads}
+
+\subsection{Hacer la fusión}
+
+% TODO poner interrogante de apertura
+Qué pasa si tratamos de usar el comando usual, \hgcmd{update}, para
+actualizar el nuevo frente?
+\interaction{tour.merge.update}
+Mercurial nos indica que el comando \hgcmd{update} no hará la fusión;
+no actualizará el directorio de trabajo cuando considera que lo que
+deseamos hacer es una fusión, a menos que lo obliguemos a hacerlo.
+En vez de \hgcmd{update}, usamos el comando \hgcmd{merge} para hacer
+la fusión entre los dos frentes.
+\interaction{tour.merge.merge}
+
+\begin{figure}[ht]
+  \centering
+  \grafix{tour-merge-merge}
+  \caption{Directorio de trabajo y repositorio durante la fusión, y
+  consignación consecuente}
+  \label{fig:tour-merge:merge}
+\end{figure}
+
+Esto actualiza el directorio de trabajo, de tal forma que contenga los
+cambios de \emph{ambos} frentes, lo que se ve reflejado tanto en la
+salida de \hgcmd{parents} como en los contenidos de \filename{hello.c}.
+\interaction{tour.merge.parents}
+
+\subsection{Consignar los resultados de la fusión}
+
+Siempre que hacemos una fusión, \hgcmd{parents} mostrará dos padres
+hasta que consignemos (\hgcmd{commit}) los resultados de la fusión.
+\interaction{tour.merge.commit}
+Ahora tenemos una nueva revisión de punta; note que tiene \emph{los
+dos} frentes anteriores como sus padres. Estos son las mismas
+revisiones que mostró previamente el comando \hgcmd{parents}.
+\interaction{tour.merge.tip}
+En la figura~\ref{fig:tour-merge:merge} usted puede apreciar una
+representación de lo que pasa en el directorio de trabajo durante la
+fusión cuando se hace la consignación. Durante la fusión, el
+directorio de trabajo tiene dos conjuntos de cambios como sus padres,
+y éstos se vuelven los padres del nuevo conjunto de cambios.
+
+\section{Fusionar cambios con conflictos}
+
+La mayoría de las fusiones son algo simple, pero a veces usted se
+encontrará fusionando cambios donde más de uno de ellos afecta las
+mismas secciones de los mismos ficheros. A menos que ambas
+modificaciones sean idénticas, el resultado es un \emph{conflicto}, en
+donde usted debe decidir cómo reconciliar ambos cambios y producir un
+resultado coherente.
+
+\begin{figure}[ht]
+  \centering
+  \grafix{tour-merge-conflict}
+  \caption{Cambios con conflictos a un documento}
+  \label{fig:tour-merge:conflict}
+\end{figure}
+
+La figura~\ref{fig:tour-merge:conflict} ilustra un ejemplo con dos
+cambios generando conflictos en un documento. Empezamos con una sola
+versión del fichero; luego hicimos algunos cambios; mientras tanto,
+alguien más  hizo cambios diferentes en el mismo texto. Lo que debemos
+hacer para resolver el conflicto causado por ambos cambios es decidir
+cómo debe quedar finalmente el fichero.
+
+Mercurial no tiene ninguna utilidad integrada para manejar conflictos.
+En vez de eso, ejecuta un programa externo llamado \command{hgmerge}.
+Es un guión de línea de comandos que es instalado junto con Mercurial;
+usted puede modificarlo para que se comporte como usted lo desee. Por
+defecto, lo que hace es tratar de encontrar una de varias herramientas
+para fusionar que es probable que estén instaladas en su sistema.
+Primero se intenta con unas herramientas para fusionar cambios
+automáticamente; si esto no tiene éxito (porque la fusión demanda
+una guía humana) o dichas herramientas no están presentes, el guión
+intenta con herramientas gráficas para fusionar.
+
+También es posible hacer que Mercurial ejecute otro programa o guión
+en vez de \command{hgmerge}, definiendo la variable de entorno
+\envar{HGMERGE} con el nombre del programa de su preferencia.
+
+\subsection{Usar una herramienta gráfica para fusión}
+
+Mi herramienta favorita para hacer fusiones es \command{kdiff3}, y la
+usaré para describir las características comunes de las herramientas
+gráficas para hacer fusiones. Puede ver una captura de pantalla de
+\command{kdiff3} ejecutándose, en la
+figura~\ref{fig:tour-merge:kdiff3}.  El tipo de fusión que la
+herramienta hace se conoce como \emph{fusión de tres vías}, porque hay
+tres versiones diferentes del fichero en que estamos interesados.
+Debido a esto la herramienta divide la parte superior de la ventana en
+tres paneles.
+\begin{itemize}
+\item A la izquierda está la revisión \emph{base} del fichero, p.ej.~la
+    versión más reciente de la que descienden las dos versiones que
+    estamos tratando de fusionar.
+\item En la mitad está ``nuestra'' versión del fichero, con las
+    modificaciones que hemos hecho.
+\item A la derecha está la versión del fichero de ``ellos'', la que
+    forma parte del conjunto de cambios que estamos tratando de
+    fusionar.
+\end{itemize}
+En el panel inferior se encuentra el \emph{resultado} actual de la
+fusión. Nuestra tarea es reemplazar todo el texto rojo, que muestra
+los conflictos sin resolver, con una fusión adecuada de ``nuestra''
+versión del fichero y la de ``ellos''.
+
+Los cuatro paneles están \emph{enlazados}; si avanzamos vertical o
+horizontalmente en cualquiera de ellos, los otros son actualizados
+para mostrar las secciones correspondientes del fichero que tengan
+asociado.
+
+\begin{figure}[ht]
+  \centering
+  \grafix[width=\textwidth]{kdiff3}
+  \caption{Usando \command{kdiff3} para fusionar versiones de un
+  fichero}
+  \label{fig:tour-merge:kdiff3}
+\end{figure}
+
+En cada conflicto del fichero podemos escoger resolverlo usando
+cualquier combinación del texto de la revisión base, la nuestra, o la
+de ellos. También podemos editar manualmente el fichero en que queda
+la fusión, si es necesario hacer cambios adicionales.
+
+Hay \emph{muchas} herramientas para fusionar ficheros disponibles. Se
+diferencian en las plataformas para las que están disponibles, y en
+sus fortalezas y debilidades particulares. La mayoría están afinadas
+para fusionar texto plano, mientras que otras están pensadas para
+formatos de ficheros especializados (generalmente XML).
+
+% TODO traduje "worked" como "real"
+\subsection{Un ejemplo real}
+
+En este ejemplo, reproduciremos el historial de modificaciones al
+fichero de la figura~\ref{fig:tour-merge:conflict} mostrada
+anteriormente.  Empecemos creando un repositorio con la versión base
+de nuestro documento.
+\interaction{tour-merge-conflict.wife}
+Clonaremos el repositorio y haremos un cambio al fichero.
+\interaction{tour-merge-conflict.cousin}
+Y haremos otro clon, para simular a alguien más haciendo un cambio al
+mismo fichero. (Esto introduce la idea de que no es tan inusual hacer
+fusiones consigo mismo, cuando usted aísla tareas en repositorios
+separados, y de hecho encuentra conflictos al hacerlo.)
+\interaction{tour-merge-conflict.son}
+Ahora que tenemos dos versiones diferentes de nuestro fichero,
+crearemos un entorno adecuado para hacer la fusión.
+\interaction{tour-merge-conflict.pull}
+
+En este ejemplo, no usaré el comando normal de Mercurial para hacer la
+fusión (\command{hgmerge}), porque lanzaría mi linda herramienta
+automatizada para correr ejemplos dentro de una interfaz gráfica de
+usuario. En vez de eso, definiré la variable de entorno
+\envar{HGMERGE} para indicarle a Mercurial que use el comando
+\command{merge}. Este comando forma parte de la instalación base de
+muchos sistemas Unix y similares. Si usted está ejecutando este
+ejemplo en su computador, no se moleste en definir \envar{HGMERGE}.
+\interaction{tour-merge-conflict.merge}
+Debido a que \command{merge} no puede resolver los conflictos que
+aparecen, él deja \emph{marcadores de fusión} en el fichero con
+conflictos, indicando si provienen de nuestra versión o de la de
+ellos.
+
+Mercurial puede saber ---por el código de salida del comando
+\command{merge}--- que no fue posible hacer la fusión exitosamente,
+así que nos indica qué comandos debemos ejecutar si queremos rehacer
+la fusión. Esto puede ser útil si, por ejemplo, estamos ejecutando una
+herramienta gráfica de fusión y salimos de ella porque nos confundimos
+o cometimos un error.
+
+Si la fusión ---automática o manual--- falla, no hay nada que nos
+impida ``arreglar'' los ficheros afectados por nosotros mismos, y
+consignar los resultados de nuestra fusión:
+% TODO este mercurial no tiene el comando resolve. Revisar si sigue
+% siendo necesario
+\interaction{tour-merge-conflict.commit}
+
+\section{Simplificar el ciclo jalar-fusionar-consignar}
+\label{sec:tour-merge:fetch}
+
+El proceso de fusionar cambios delineado anteriomente es directo, pero
+requiere la ejecución de tres comandos en sucesión.
+\begin{codesample2}
+  hg pull
+  hg merge
+  hg commit -m 'Fusionados cambios remotos'
+\end{codesample2}
+En la consignación final usted debe proveer un mensaje adecuado, que
+casi siempre es un fragmento de texto ``de relleno'' carente de valor
+particular.
+
+Sería agradable reducir la cantidad de pasos necesarios, si fuera
+posible. De hecho, Mercurial es distribuido junto con una extensión
+llamada \hgext{fetch}\ndt{Descargar, traer.} que hace precisamente
+esto.
+
+Mercurial cuenta con un mecanismo de extensión flexible que le permite
+% TODO lets people => permite a usuarios
+a sus usuarios extender su funcionalidad, manteniendo el núcleo de
+Mercurial pequeño y fácil de manejar. Algunas extensiones añaden
+nuevos comandos que usted puede usar desde la línea de comandos,
+mientras que otros funcionan ``tras bambalinas'', por ejemplo,
+añadiendo funcionalidad al servidor.
+
+La extensión \hgext{fetch} añade un comando llamado, no
+sorpresivamente, \hgcmd{fetch}.  Esta extensión actúa como una
+combinación de \hgcmd{pull}, \hgcmd{update} y \hgcmd{merge}.  Empieza
+jalando cambios de otro repositorio al repositorio actual. Si
+encuentra que los cambios añaden un nuevo frente en el repositorio
+actual, inicia una fusión, y luego consigna el resultado de la misma
+con un mensaje generado automáticamente. Si no se añadieron nuevos
+frentes, actualiza el directorio de trabajo con el nuevo conjunto de
+cambios de punta.
+
+Activar la extensión \hgext{fetch} es fácil. Edite su
+\sfilename{.hgrc}, y vaya a (o cree) la sección
+\rcsection{extensions}.  Luego añada una línea que diga simplemente
+``\Verb+fetch +''.
+\begin{codesample2}
+  [extensions]
+  fetch =
+\end{codesample2}
+(Normalmente, a la derecha del ``\texttt{=}'' debería aparecer la
+ubicación de la extensión, pero como el comando \hgext{fetch} es parte
+de la distribución estándar, Mercurial sabe dónde buscarla.)
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/undo-manual-merge.dot	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,8 @@
+digraph undo_manual {
+	"primer cambio" -> "segundo cambio";
+	"segundo cambio" -> "tercer cambio";
+	reversar [label="reversar\nsegundo cambio", shape=box];
+	"segundo cambio" -> reversar;
+	"tercer cambio" -> "fusión\nmanual";
+	reversar -> "fusión\nmanual";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/undo-manual.dot	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,6 @@
+digraph undo_manual {
+	"primer cambio" -> "segundo cambio";
+	"segundo cambio" -> "tercer cambio";
+	reversar [label="reversar\nsegundo cambio", shape=box];
+	"segundo cambio" -> reversar;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/undo-non-tip.dot	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,9 @@
+digraph undo_non_tip {
+	"primer cambio" -> "segundo cambio";
+	"segundo cambio" -> "tercer cambio";
+	reversar [label="reversar\nsegundo cambio", shape=box];
+	"segundo cambio" -> reversar;
+	merge [label="automatizar\nfusión", shape=box];
+	"tercer cambio" -> fusión;
+	reversar -> fusión;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/undo-simple.dot	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,4 @@
+digraph undo_simple {
+	"primer cambio" -> "segundo cambio";
+	"segundo cambio" -> "reversar\nsegundo cambio";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/undo.tex	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,799 @@
+\chapter{Encontrar y arreglar sus equivocaciones}
+\label{chap:undo}
+
+Errar es humano, pero tratar adecuadamente las consecuencias requiere
+un sistema de control de revisiones de primera categoría.  En este
+capítulo, discutiremos algunas técnicas que puede usar cuando
+encuentra que hay un problema enraizado en su proyecto.  Mercurial
+tiene unas características poderosas que le ayudarán a isolar las
+fuentes de los problemas, y a dar cuenta de ellas apropiadamente.
+
+\section{Borrar el historial local}
+
+\subsection{La consignación accidental}
+
+Tengo el problema ocasional, pero persistente de teclear más rápido de
+lo que pienso, que aveces resulta en consignar un conjunto de cambios
+incompleto o simplemente malo. En mi caso, el conjunto de cambios
+incompleto consiste en que creé un nuevo fichero fuente, pero olvidé
+hacerle \hgcmd{add}.  Un conjunto de cambios``simplemente malo'' no es
+tan común, pero sí resulta muy molesto.
+
+\subsection{Hacer rollback una transacción}
+\label{sec:undo:rollback}
+
+En la sección~\ref{sec:concepts:txn}, mencioné que Mercurial trata
+modificación a un repositorio como una \emph{transacción}.  Cada vez
+que consigna un conjunto de cambios o lo jala de otro repositorio,
+Mercurial recuerda lo que hizo.  Puede deshacer, o hacer \emph{roll back}\ndt{El significado igual que en los
+    ambientes de sistemas manejadores de bases de datos se refiere a
+    la atomicidad e integridad al devolver un conjunto de acciones que
+  permitan dejar el repositorio en un estado consistente previo},
+exactamente una de tales acciones usando la orden \hgcmd{rollback}.
+(Ver en la sección~\ref{sec:undo:rollback-after-push} una anotación
+importante acerca del uso de esta orden.)
+
+A continuación una equivocación que me sucede frecuentemente:
+consignar un cambio en el cual he creado un nuevo fichero, pero he
+olvidado hacerle \hgcmd{add}.
+\interaction{rollback.commit}
+La salida de \hgcmd{status} después de la consignación confirma
+inmediatamente este error.
+\interaction{rollback.status}
+La consignación capturó los cambios en el fichero \filename{a}, pero
+no el nuevo fichero \filename{b}.  Si yo publicara este conjunto de
+cambios a un repositorio compartido con un colega, es bastante
+probable que algo en \filename{a} se refiriera a \filename{b}, el cual
+podría no estar presente cuando jalen mis cambios del repositorio.  Me
+convertiría el sujeto de cierta indignación.
+
+Como sea, la suerte me acompaña---Encontré mi error antes de publicar
+el conjunto de cambios.  Uso la orden \hgcmd{rollback}, y Mercurial
+hace desaparecer el último conjunto de cambios.
+\interaction{rollback.rollback}
+El conjunto de cambios ya no está en el historial del repositorio, y el
+directorio de trabajo cree que el fichero \filename{a} ha sido
+modificado.  La consignación y el roll back dejaron el directorio de
+trabajo exactamente como estaba antes de la consignación; el conjunto
+de cambios ha sido eliminado totlamente. Ahora puedo hacer \hgcmd{add}
+al fichero \filename{b}, y hacer de nuevo la consignación.
+\interaction{rollback.add}
+
+\subsection{Erroneamente jalado}
+
+Mantener ramas de desarrollo separadas de un proyecto en distintos
+repositorios es una práctica común con Mercurial.  Su equipo de
+desarrollo puede tener un repositorio compartido para la versión ``0.9''
+y otra con cambios distintos para la versión ``1.0''.
+
+Con este escenario, puede imaginar las consecuencias si tuviera un
+repositorio local ``0.9'', y jalara accidentalmente los cambios del
+repositorio compartido de la versión ``1.0'' en este.  En el peor de
+los casos, por falta de atención, es posible que publique tales
+cambios en el árbol compartido ``0.9'', confundiendo a todo su equipo
+de trabajo (pero no se preocupe, volveremos a este terrorífico
+escenario posteriormente).  En todo caso, es muy probable que usted se
+de cuenta inmediatamente, dado que Mercurial mostrará el URL de donde
+está jalando, o que vea jalando una sospechosa gran cantidad de
+cambios en el repositorio.
+
+La orden \hgcmd{rollback} excluirá eficientemente los conjuntos de
+cambios que haya acabado de jalar.  Mercurial agrupa todos los cambios
+de un \hgcmd{pull} a una única transacción y bastará con un
+\hgcmd{rollback} para deshacer esta equivocación.
+
+\subsection{Después de publicar, un roll back es futil}
+\label{sec:undo:rollback-after-push}
+
+El valor de \hgcmd{rollback} se anula cuando ha publicado sus cambios
+a otro repositorio.  Un cambio desaparece totalmente al hacer roll back,
+pero \emph{solamente} en el repositorio en el cual aplica
+\hgcmd{rollback}.  Debido a que un roll back elimina el historial,
+no hay forma de que la desaparición de un cambio se propague entre
+repositorios.
+
+Si ha publicado un cambio en otro repositorio---particularmente si es
+un repositorio público---esencialmente está ``en terreno agreste,''
+y tendrá que reparar la equivocación de un modo distinto.  Lo que
+pasará si publica un conjunto de cambios en algún sitio, hacer
+rollback y después volver a jalar del repositorio del cual había
+publicado, es que el conjunto de cambios reaparecerá en su repositorio.
+
+(Si está absolutamente segruro de que el conjunto de cambios al que
+desea hacer rollback es el cambio más reciente del repositorio en el
+cual publicó, \emph{y} sabe que nadie más pudo haber jalado de tal
+repositorio, puede hacer rollback del conjunto de cambios allí, pero
+es mejor no confiar en una solución de este estilo.  Si lo hace, tarde
+o temprano un conjunto de cambios logrará colarse en un repositorio
+que usted no controle directamente (o del cual se ha olvidado), y
+volverá a hostigarle.)
+
+\subsection{Solamente hay un roll back}
+
+Mercurial almacena exactamente una transacción en su bitácora de
+transacciones; tal transacción es la más reciente de las que haya
+ocurrido en el repositorio. Esto significa que solamente puede hacer
+roll back a una transacción. Si espera poder hacer roll back a una
+transacción después al antecesor, observará que no es el
+comportamiento que obtendrá.
+\interaction{rollback.twice}
+Una vez que haya aplicado un rollback en una transacción a un
+repositorio, no podrá volver a hacer rollback hasta que haga una
+consignación o haya jalado.
+
+\section{Revertir un cambio equivocado}
+
+Si modifica un fichero y se da cuenta que no quería realmente cambiar
+tal fichero, y todavía no ha consignado los cambios, la orden
+necesaria es \hgcmd{revert}. Observa el conjunto de cambios padre del
+directorio y restaura los contenidos del fichero al estado de tal
+conjunto de cambios. (Es una forma larga de decirlo, usualmente
+deshace sus modificaciones.)
+
+Ilustremos como actúa la orden \hgcmd{revert} con un ejemplo
+pequeño. Comenzaremos modificando un fichero al cual Mercurial ya está
+siguiendo.
+\interaction{daily.revert.modify}
+Si no queremos ese cambio, podemos aplicar \hgcmd{revert} al fichero.
+\interaction{daily.revert.unmodify}
+La orden \hgcmd{revert} nos brinda un grado adicional de seguridad
+guardando nuestro fichero modificado con la extensión \filename{.orig}.
+\interaction{daily.revert.status}
+
+Este es un resumen de casos en los cuales la orden \hgcmd{revert} es
+de utilidad. Describiremos cada uno de ellos con más detalle en la
+sección siguiente.
+\begin{itemize}
+\item Si usted modifica un fichero, lo restaurará a su estado sin
+  modificación previo.
+\item Si usted hace \hgcmd{add} a un fichero, revertirá el estado de
+  ``adicionado'' del fichero, pero no lo tocará
+\item Si borra un fichero sin decirle a Mercurial, restaurará el
+  fichero con sus contenidos sin modificación.
+\item Si usa la orden \hgcmd{remove} para eliminar un fichero, deshará
+  el estado ``removido'' del fichero, y lo restaurará con sus
+  contenidos sin modificación.
+\end{itemize}
+
+\subsection{Errores al administrar ficheros}
+\label{sec:undo:mgmt}
+
+La orden \hgcmd{revert} es útil para más que ficheros modificados. Le
+permite reversar los resultados de todas las órdenes de administración
+de ficheros que provee Mercurial---\hgcmd{add}, \hgcmd{remove}, y las
+demás.
+
+Si usted hace \hgcmd{add} a un fichero, y no deseaba que Mercurial le
+diera seguimiento, use \hgcmd{revert} para deshacer la adición.  No se
+preocupe; Mercurial no modificará de forma alguna el fichero.
+Solamente lo ``desmarcará''.
+\interaction{daily.revert.add}
+
+De forma similar, Si le solicita a Mercurial hacer \hgcmd{remove} a un
+fichero, puede usar \hgcmd{revert} para restarurarlo a los contenidos
+que tenía la revisión padre del directorio de trabajo.
+\interaction{daily.revert.remove}
+Funciona de la misma manera para un fichero que usted haya eliminado
+manualmente, sin decirle a Mercurial (recuerde que en la terminología
+de Mercurial esta clase de fichero se llama ``faltante'').
+\interaction{daily.revert.missing}
+
+Si usted revierte un \hgcmd{copy}, el fichero a donde se copió
+permanece en su directorio de trabajo, pero sin seguimiento. Dado que
+una copia no afecta el fichero fuente de copiado de ninguna maner,
+Mercurial no hace nada con este.
+\interaction{daily.revert.copy}
+
+\subsubsection{Un caso ligeramente especial:revertir un renombramiento}
+
+Si hace \hgcmd{rename} a un fichero, hay un detalle que debe tener en
+cuenta. Cuando aplica \hgcmd{revert} a un cambio de nombre, no es
+suficiente proveer el nombre del fichero destino, como puede verlo en
+el siguiente ejemplo.
+\interaction{daily.revert.rename}
+Como puede ver en la salida de \hgcmd{status}, el fichero con el nuevo
+nombre no se identifica más como agregado, pero el fichero con el
+nombre-\emph{inicial} se elimna!  Esto es contra-intuitivo (por lo
+menos para mí), pero por lo menos es fácil arreglarlo.
+\interaction{daily.revert.rename-orig}
+Por lo tanto, recuerde, para revertir un \hgcmd{rename}, debe proveer
+\emph{ambos} nombres, la fuente y el destino.
+
+% TODO: the output doesn't look like it will be removed!
+
+(A propósito, si elimina un fichero, y modifica el fichero con el
+nuevo nombre, al revertir ambos componentes del renombramiento, cuando
+Mercurial restaure el fichero que fue eliminado como parte del
+renombramiento, no será modificado.
+Si necesita que las modificaciones en el fichero destino del
+renombramiento se muestren, no olvide copiarlas encima.)
+
+Estos aspectos engorrosos al revertir un renombramiento se constituyen
+discutiblemente en un fallo de Mercurial.
+
+\section{Tratar cambios consignados}
+
+Considere un caso en el que ha consignado el cambio $a$, y otro cambio
+$b$ sobre este; se ha dado cuenta que el cambio $a$ era
+incorrecto. Mercurial le permite ``retroceder'' un conjunto de cambios
+completo automáticamente, y construir bloques que le permitan revertir
+parte de un conjunto de cambios a mano.
+
+Antes de leer esta sección, hay algo para tener en cuenta: la orden
+\hgcmd{backout} deshace cambios \emph{adicionando} al historial, sin
+modificar o borrar.  Es la herramienta correcta si está arreglando
+fallos, pero no si está tratando de deshacer algún cambio que tiene
+consecuencias catastróficas.  Para tratar con esos, vea la sección~\ref{sec:undo:aaaiiieee}.
+
+\subsection{Retroceder un conjunto de cambios}
+
+La orden \hgcmd{backout} le permite ``deshacer'' los efectos de todo
+un conjunto de cambios de forma automatizada.  Dado que el historial de
+Mercurial es inmutable, esta orden \emph{no} se deshace del conjunto
+de cambios que usted desea deshacer.  En cambio, crea un nuevo
+conjunto de cambios que \emph{reversa} el conjunto de cambios que
+usted indique.
+
+La operación de la orden \hgcmd{backout} es un poco intrincada, y lo
+ilustraremos con algunos ejemplos. Primero crearemos un repositorio
+con algunos cambios sencillos.
+\interaction{backout.init}
+
+La orden \hgcmd{backout} toma un ID de conjunto de cambios como su
+argumento; el conjunto de cambios a retroceder. Normalmente
+\hgcmd{backout} le ofrecerá un editor de texto para escribir el
+mensaje de la consignación, para dejar un registro de por qué está
+retrocediendo. En este ejemplo, colocamos un mensaje en la
+consignación usando la opción \hgopt{backout}{-m}.
+
+\subsection{Retroceder el conjunto de cambios punta}
+
+Comenzamos retrocediendo el último conjunto de cambios que consignamos.
+\interaction{backout.simple}
+Puede ver que la segunda línea de \filename{myfile} ya no está
+presente.  La salida de \hgcmd{log} nos da una idea de lo que la orden
+\hgcmd{backout} ha hecho.
+\interaction{backout.simple.log}
+Vea que el nuevo conjunto de cambios que \hgcmd{backout} ha creado es
+un hijo del conjunto de cambios que retrocedimos. Es más sencillo de
+ver en la figura~\ref{fig:undo:backout}, que presenta una vista
+gráfica del historial de cambios.  Como puede ver, el historial es
+bonito y lineal.
+
+\begin{figure}[htb]
+  \centering
+  \grafix{undo-simple}
+  \caption{Retroceso de un cambio con la orden \hgcmd{backout}}
+  \label{fig:undo:backout}
+\end{figure}
+
+\subsection{Retroceso de un cambio que no es la punta}
+
+Si desea retrocede un cambio distinto al último que ha consignado, use
+la opción \hgopt{backout}{--merge} a la orden \hgcmd{backout}.
+\interaction{backout.non-tip.clone}
+Que resulta en un retroceso de un conjunto de cambios ``en un sólo
+tiro'', una operación que resulta normalmente rápida y sencilla.
+\interaction{backout.non-tip.backout}
+
+Si ve los contenidos del fichero \filename{myfile} después de
+finalizar el retroceso, verá que el primer y el tercer cambio están
+presentes, pero no el segundo.
+\interaction{backout.non-tip.cat}
+
+Como lo muestra el historial gráfico en la
+figura~\ref{fig:undo:backout-non-tip}, Mercurial realmente consigna
+\emph{dos} cambios en estas situaciones (los nodos encerrados en una
+caja son aquellos que Mercurial consigna automaticamente).  Antes de
+que Mercurial comience el proceso de retroceso, primero recuerda cuál
+es el padre del directorio de trabajo.  Posteriormente hace un
+retroceso al conjunto de cambios objetivo y lo consigna como un
+conjunto de cambios. Finalmente, fusiona con el padre anterior del
+directorio de trabajo, y consigna el resultado de la fusión.
+
+% TODO: to me it looks like mercurial doesn't commit the second merge automatically!
+
+\begin{figure}[htb]
+  \centering
+  \grafix{undo-non-tip}
+  \caption{Retroceso automatizado de un cambio a algo que no es la punta con la orden \hgcmd{backout}}
+  \label{fig:undo:backout-non-tip}
+\end{figure}
+
+El resultado es que usted termina ``donde estaba'', solamente con un
+poco de historial adicional que deshace el efecto de un conjunto de
+cambios que usted quería evitar.
+
+\subsubsection{Use siempre la opción \hgopt{backout}{--merge}}
+
+De hecho, dado que la opción \hgopt{backout}{--merge} siempre hara lo
+``correcto'' esté o no retrocediendo el conjunto de cambios punta
+(p.e.~no tratará de fusionar si está retrocediendo la punta, dado que
+no es necesario), usted debería usar \emph{siempre} esta opción cuando
+ejecuta la orden \hgcmd{backout}.
+
+\subsection{Más control sobre el proceso de retroceso}
+
+A pesar de que recomiendo usar siempre la opción 
+\hgopt{backout}{--merge} cuando está retrocediendo un cambio, la orden
+\hgcmd{backout} le permite decidir cómo mezclar un retroceso de un
+conjunto de cambios.  Es muy extraño que usted necestite tomar control
+del proceso de retroceso de forma manual, pero puede ser útil entender
+lo que la orden \hgcmd{backout} está haciendo automáticamente para
+usted. Para ilustrarlo, clonemos nuestro primer repositorio, pero
+omitamos el retroceso que contiene.
+
+\interaction{backout.manual.clone}
+Como en el ejemplo anterior, consignaremos un tercer cambio, después
+haremos retroceso de su padre, y veremos qué pasa.
+\interaction{backout.manual.backout} 
+Nuestro nuevo conjunto de cambios es de nuevo un descendiente del
+conjunto de cambio que retrocedimos; es por lo tanto una nueva cabeza,
+\emph{no} un descendiente del conjunto de cambios que era la punta. La
+orden \hgcmd{backout} fue muy explícita diciéndolo.
+\interaction{backout.manual.log}
+
+De nuevo, es más sencillo lo que pasó viendo una gráfica del
+historial de revisiones, en la figura~\ref{fig:undo:backout-manual}.
+Esto nos aclara que cuando usamos \hgcmd{backout} para retroceder un
+cambio a algo que no sea la punta, Mercurial añade una nueva cabeza al
+repositorio (el cambio que consignó está encerrado en una caja).
+
+\begin{figure}[htb]
+  \centering
+  \grafix{undo-manual}
+  \caption{Retroceso usando la orden \hgcmd{backout}}
+  \label{fig:undo:backout-manual}
+\end{figure}
+
+Después de que la orden \hgcmd{backout} ha terminado, deja un nuevo
+conjunto de cambios de ``retroceso'' como el padre del directorio de trabajo.
+\interaction{backout.manual.parents}
+Ahora tenemos dos conjuntos de cambios aislados.
+\interaction{backout.manual.heads}
+
+Reflexionemos acerca de lo que esperamos ver como contenidos de
+\filename{myfile}.  El primer cambio debería estar presente, porque
+nunca le hicimos retroceso.  El segundo cambio debió desaparecer,
+puesto que es el que retrocedimos.  Dado que la gráfica del historial
+muestra que el tercer camlio es una cabeza separada, \emph{no}
+esperamos ver el tercer cambio presente en \filename{myfile}.
+\interaction{backout.manual.cat}
+Para que el tercer cambio esté en el fichero, hacemos una fusión usual
+de las dos cabezas.
+\interaction{backout.manual.merge}
+Después de eso, el historial gráfica de nuestro repositorio luce como
+la figura~\ref{fig:undo:backout-manual-merge}.
+
+\begin{figure}[htb]
+  \centering
+  \grafix{undo-manual-merge}
+  \caption{Fusión manual de un retroceso}
+  \label{fig:undo:backout-manual-merge}
+\end{figure}
+
+\subsection{Por qué \hgcmd{backout} hace lo que hace}
+
+Esta es una descripción corta de cómo trabaja la orden \hgcmd{backout}.
+\begin{enumerate}
+\item Se asegura de que el directorio de trabajo es ``limpio'', esto
+  es, que la salida de \hgcmd{status} debería ser vacía.
+\item Recuerda el padre actual del directorio de trabajo. A este
+  conjunto de cambio lo llamaremos \texttt{orig}
+\item Hace el equivalente de un \hgcmd{update} para sincronizar el
+  directorio de trabajo con el conjunto de cambios que usted quiere
+  retroceder. Lo llamaremos \texttt{backout}
+\item Encuentra el padre del conjunto de cambios. Lo llamaremos
+  \texttt{parent}.
+\item Para cada fichero del conjunto de cambios que el
+  \texttt{retroceso} afecte, hará el equivalente a
+  \hgcmdargs{revert}{-r parent} sobre ese fichero, para restaurarlo a
+  los contenidos que tenía antes de que el conjunto de cambios fuera
+  consignado.
+\item Se consigna el resultado como un nuevo conjunto de cambios y
+  tiene a  \texttt{backout} como su padre.
+\item Si especifica \hgopt{backout}{--merge} en la línea de comandos,
+  se fusiona con \texttt{orig}, y se consigna el resultado de la
+  fusión.
+\end{enumerate}
+
+Una vía alternativa de implementar la orden \hgcmd{backout} sería usar
+\hgcmd{export} sobre el conjunto de cambios a retroceder como un diff
+y después usar laa opción \cmdopt{patch}{--reverse} de la orden
+\command{patch} para reversar el efecto del cambio sin molestar el
+directorio de trabajo.  Suena mucho más simple, pero no funcionaría
+bien ni de cerca.
+
+La razón por la cual \hgcmd{backout} hace una actualización, una
+consignación, una fusión y otra consignación es para dar a la
+maquinaria de fusión la mayor oportunidad de hacer un buen trabajo
+cuando se trata con todos los cambios \emph{entre} el cambio que está
+retrocediendo y la punta actual.
+
+Si está retrocediendo un conjunto de cambios que está a unas ~100
+atrás en su historial del proyecto, las posibilidades de que una orden
+\command{patch} sea capaz de ser aplicada a un diff reverso,
+claramente no son altas, porque los cambios que intervienen podrían
+``no coincidir con el contexto'' que \command{patch} usa  para
+determinar si puede aplicar un parche (si esto suena como cháchara,
+vea una discusión de la orden \command{patch} en \ref{sec:mq:patch}).
+Adicionalmente, la maquinaria de fusión de Mercurial manejará ficheros
+y directorios renombrados, cambios de permisos, y modificaciones a
+ficheros binarios, nada de lo cual la orden \command{patch} puede manejar.
+
+\section{Cambios que nunca debieron ocurrir}
+\label{sec:undo:aaaiiieee}
+
+En la mayoría de los casos, la orden \hgcmd{backout} es exactamente lo
+que necesita para deshacer los efectos de un cambio.  Deja un registro
+permanente y exacto de lo que usted hizo, cuando se consignó el
+conjunto de cambios original y cuando se hizo la limpieza.
+
+En ocasiones particulares, puede haber consignado un cambio que no
+debería estar de ninguna forma en el repositorio.  Por ejemplo, sería
+muy inusual, y considerado como una equivocación, consignar los
+ficheros objeto junto con el código fuente. Los ficheros objeto no
+tienen valor intrínseco y son \emph{grandes}, por lo tanto aumentan el
+tamaño del repositorio y la cantidad de tiempo que se emplea al clonar
+o jalar cambios.
+
+Antes de discutir las opciones que tiene si consignó cambio del tipo 
+``bolsa de papel deschable'' (el tipo que es tan malo que le gustaría
+colocarse una bolsa de papel desechable en su cabeza), permítame
+discutir primero unas aproximaciones que probablemente no funcionen.
+
+Dado que Mercurial trata de forma acumulativa al historial---cada
+cambio se coloca encima de todos los cambios que le
+preceden---usualmente usted no puede hacer que unos cambios desastrosos
+desaparezcan. La única excepción es cuando usted ha acabado de
+consignar un cambio y este no ha sido publicado o jalado en otro
+repositorio. Ahí es cuando puede usar la orden \hgcmd{rollback} con
+seguridad, como detallé en la sección~\ref{sec:undo:rollback}.
+
+Después de que usted haya publicado un cambio en otro repositorio, usted
+\emph{podría} usar la orden \hgcmd{rollback} para hacer que en su copia
+local desaparezca el cambio, pero no tendrá las consecuencias que
+desea. El cambio estará presente en un repositorio remoto, y
+reaparecerá en su repositorio local la próxima vez que jale
+
+Si una situación como esta se presenta, y usted sabe en qué
+repositorios su mal cambio se ha propagado, puede \emph{intentar}
+deshacerse del conjunto de cambios de \emph{todos} los repositorios en
+los que se pueda encontrar.  Esta por supuesto, no es una solución
+satisfactoria: si usted deja de hacerlo en un solo repositorio,
+mientras esté eliminándolo, el cambio todavía estará ``allí afuera'',
+y podría propagarse más tarde.
+
+Si ha consignado uno o más cambios \emph{después} del cambio que desea
+desaparecer, sus opciones son aún más reducidas. Mercurial no provee
+una forma de ``cabar un hueco'' en el historial, dejando los conjuntos
+de cambios intactos.
+
+%Dejamos de traducir lo que viene a continuación, porque será
+%modificado por upstream...
+
+XXX This needs filling out.  The \texttt{hg-replay} script in the
+\texttt{examples} directory works, but doesn't handle merge
+changesets.  Kind of an important omission.
+
+\subsection{Cómo protegerse de cambios que han ``escapado''}
+
+Si ha consignado cambios a su repositorio local y estos han sido
+publicados o jalados en cualquier otro sitio, no es necesariamente un
+desastre. Puede protegerse de antemano de ciertas clases de conjuntos
+de cambios malos. Esto es particularmente sencillo si su equipo de
+trabajo jala cambios de un repositorio central.
+
+Al configurar algunos ganchos en el repositorio central para validar
+conjuntos de cambios (ver capítulo~\ref{chap:hook}), puede prevenir la
+publicación automáticamente de cierta clase de cambios malos.  Con tal
+configuración, cierta clase de conjuntos de cambios malos tenderán
+naturalmente a``morir'' debido a que no pueden propagarse al
+repositorio central.  Esto sucederá sin necesidad de intervención
+explícita.
+
+Por ejemplo, un gancho de cambios de entrada que verifique que un
+conjunto de cambios compila, puede prevenir que la gente ``rompa 
+la compilación'' inadvertidamente.
+
+\section{Al encuentro de la fuente de un fallo}
+\label{sec:undo:bisect}
+
+Aunque es muy bueno poder retroceder el conjunto de cambios que
+originó un fallo, se requiere que usted sepa cual conjunto de cambios
+retroceder.  Mercurial brinda una orden invaluable, llamada
+\hgcmd{bisect}, que ayuda a automatizar este proceso y a alcanzarlo
+muy eficientemente.
+
+La idea tras la orden \hgcmd{bisect} es que el conjunto de cambios que
+ha introducido un cambio de comportamiento pueda identificarse con una
+prueba binaria sencilla. No tiene que saber qué pieza de código
+introdujo el cambio, pero si requiere que sepa cómo probar la
+existencia de un fallo. La orden \hgcmd{bisect} usa su prueba para
+dirigir su búsqueda del conjunto de cambios que introdujo el código
+causante del fallo.
+
+A continuación un conjunto de escenarios que puede ayudarle a entender
+cómo puede aplicar esta orden.
+\begin{itemize}
+\item La versión más reciente de su programa tiene un fallo que usted
+  recuerda no estaba hace unas semanas, pero no sabe cuándo fue
+  introducido. En este caso, su prueba binaria busca la presencia de
+  tal fallo.
+\item Usted arregló un fallo en un apurto, y es hora de dar por
+  cerrado el caso en la base de datos de fallos de su equipo de
+  trabajo.   La base de datos de fallos requiere el ID del conjunto de
+  cambios que permita dar por cerrado el caso, pero usted no recuerda
+  qué conjunto de cambios arregló tal fallo.  De nuevo la prueba
+  binaria revisa la presencia del fallo.
+\item Su programa funciona correctamente, pero  core ~15\% más lento
+  que la última vez que lo midió. Usted desea saber qué conjunto de
+  cambios introdujo esta disminución de desempeño.  En este caso su
+  prueba binaria mide el desempeño de su programa, para ver dónde es
+  ``rápido'' y dónde es ``lento''.
+\item Los tamaños de los componentes del proyecto que usted lleva se
+  expandieron recientemente, y sospecha que algo cambio en la forma en
+  que se construye su proyecto.
+\end{itemize}
+
+Para estos ejemplos debería ser claro que la orden \hgcmd{bisect}
+es útil no solamente para encontrar la fuente de los fallos. Puede
+usarla para encontrar cualquier ``propiedad emergente'' de un
+repositorio (Cualquier cosa que usted no pueda encontrar con una
+búsqueda de texto sencilla sobre los ficheros en el árbol) para la
+cual pueda escribir una prueba binaria.
+
+A continuación introduciremos algo terminología, para aclarar qué
+partes del proceso de búsqueda son su responsabilidad y cuáles de
+Mercurial.  Una \emph{prueba} es algo que \emph{usted} ejecuta cuando
+\hgcmd{bisect} elige un conjunto de cambios.  Un \emph{sondeo} es lo que
+\hgcmd{bisect} ejecuta para decidir si una revisión es buena.  Finalmente,
+usaremos la palabra ``biseccionar', en frases como ``buscar con la
+orden \hgcmd{bisect}''.
+
+Una forma sencilla de automatizar el proceso de búsqueda sería probar
+cada conjunto de cambios.  Lo cual escala muy poco. Si le tomó diez
+minutos hacer pruebas sobre un conjunto de cambios y tiene 10.000
+conjuntos de cambios en su repositorio, esta aproximación exhaustiva
+tomaría en promedio~35 \emph{días} para encontrar el conjunto de
+cambios que introdujo el fallo. Incluso si supiera que el fallo se
+introdujo en un de los últimos 500 conjuntos de cambios y limitara la
+búsqueda a ellos, estaría tomabdi más de 40 horas para encontrar al
+conjunto de cambios culpable.
+
+La orden \hgcmd{bisect} usa su conocimiento de la ``forma'' del
+historial de revisiones de su proyecto para hacer una búsqueda
+proporcional al \emph{logaritmo} del número de conjunto de cambios a
+revisar (el tipo de búsqueda que realiza se llama búsqueda
+binaria). Con esta aproximación, el buscar entre 10.000 conjuntos de
+cambios tomará menos de 3 horas, incluso a diez minutos por prueba (La
+búsqueda requerirá cerca de 14 pruebas). Al limitar la búsqueda a la
+última centena de conjuntos de cambios, tomará a lo sumo una
+hora (Apenas unas 7 pruebas).
+
+La orden \hgcmd{bisect} tiene en cuenta la naturaleza ``ramificada''
+del historial de revisiones del proyecto con Mercurial, así que no
+hay problemas al tratar con ramas, fusiones o cabezas múltiples en un
+repositorio.  Puede evitar ramas enteras de historial con un solo
+sondeo.
+
+\subsection{Uso de la orden \hgcmd{bisect}}
+
+A continuación un ejemplo de \hgcmd{bisect} en acción.
+
+\begin{note}
+  En las versiones 0.9.5 y anteriores de Mercurial, \hgcmd{bisect} no
+  era una orden incluída en la distribución principal: se ofrecía como
+  una extensión de Mercurial. Esta sección describe la orden embebida
+  y no la extensión anterior.
+\end{note}
+
+Creamos un repostorio para probar el comando \hgcmd{bisect} de forma
+aislada
+\interaction{bisect.init}
+Simularemos de forma sencilla un proyecto con un fallo: haremos
+cambios triviales en un ciclo, e indicaremos que un cambio específico
+sea el ``fallo''.  Este ciclo crea 35 conjuntos de cambios, cada uno
+añade un único fichero al repositorio. Representaremos nuestro ``fallo''
+con un fichero que contiene el texto ``tengo un gub''.
+\interaction{bisect.commits}
+
+A continuación observaremos cómo usar la orden \hgcmd{bisect}. Podemos
+usar el mecanismo de ayuda embebida que trae Mercurial.
+\interaction{bisect.help}
+
+La orden \hgcmd{bisect} trabaja en etapas, de la siguiente forma:
+\begin{enumerate}
+\item Usted ejecuta una prueba binaria.
+  \begin{itemize}
+  \item Si la prueba es exitosa, usted se lo indicará a \hgcmd{bisect}
+    ejecutando la orden \hgcmdargs{bisect}{good}.
+  \item Si falla, ejecutará la orden \hgcmdargs{bisect}{--bad}.
+  \end{itemize}
+\item La orden usa su información para decidir qué conjuntos de
+  cambios deben probarse a continuación.
+\item Actualiza el directorio de trabajo a tal conjunto de cambios y
+  el proceso se lleva a cabo de nuevo.
+\end{enumerate}
+El proceso termina cuando \hgcmd{bisect} identifica un único conjunto
+de cambios que marca el punto donde se encontró la transición de
+``exitoso'' a ``fallido''.
+
+Para comenzar la búsqueda, es indispensable ejecutar la orden
+\hgcmdargs{bisect}{--reset}.
+\interaction{bisect.search.init}
+
+En nuestro caso, la prueba binaria es sencilla: revisamos si el
+fichero en el repositorio contiene la cadena ``tengo un gub''.  Si la
+tiene, este conjunto de cambios contiene aquel que ``causó el fallo''.
+Por convención, un conjunto de cambios que tiene la propiedad que
+estamos buscando es ``malo'', mientras que el otro que no la tiene es
+``bueno''.
+
+En la mayoría de casos, la revisión del directorio actual (usualmente
+la punta) exhibe el problema introducido por el cambio con el fallo,
+por lo tanto la marcaremos como ``mala''.
+\interaction{bisect.search.bad-init}
+
+Nuestra próxima tarea es nominar al conjunto de cambios que sabemos
+\emph{no} tiene el fallo; la orden \hgcmd{bisect} ``acotará'' su
+búsqueda entre el primer par de conjuntos de cambios buenos y malos.
+En nuestro caso, sabemos que la revisión~10 no tenía el fallo.  (Más
+adelante diré un poco más acerca de la elección del conjunto de
+cambios ``bueno''.)
+\interaction{bisect.search.good-init}
+
+Note que esta orden mostró algo.
+\begin{itemize}
+\item Nos dijo cuántos conjuntos de cambios debe considerar antes de
+  que pueda identifica aquel que introdujo el fallo, y cuántas pruebas
+  se requerirán.
+\item Actualizó el directorio de trabajo al siguiente conjunto de
+  cambios, y nos dijo qué conjunto de cambios está evaluando.
+\end{itemize}
+
+Ahora ejecutamos nuestra prueba en el directorio de trabajo. Usamos la
+orden \command{grep} para ver si nuestro fichero ``malo'' está
+presente en el directorio de trabajo.  Si lo está, esta revisión es
+mala; si no esta revisión es buena.
+\interaction{bisect.search.step1}
+
+Esta prueba luce como candidata perfecta para automatizarse, por lo
+tanto la convertimos en una función de interfaz de comandos.
+\interaction{bisect.search.mytest}
+Ahora podemos ejecutar un paso entero de pruebas con un solo comando,
+\texttt{mytest}.
+\interaction{bisect.search.step2}
+Unas invocaciones más de nuestra prueba, y hemos terminado.
+\interaction{bisect.search.rest}
+
+Aunque teníamos unos~40 conjuntos de cambios en los cuales buscar, la
+orden \hgcmd{bisect} nos permitió encontrar el conjunto de cambios que
+introdujo el ``fallo'' con sólo cinco pruebas.  Porque el número de
+pruebas que la orden \hgcmd{bisect} ejecuta crece logarítmicamente con
+la cantidad de conjuntos de cambios a buscar, la ventaja que esto
+tiene frente a la  búsqueda por``fuerza bruta'' crece con cada
+conjunto de cambios que usted adicione.
+
+\subsection{Limpieza después de la búsqueda}
+
+Cuando haya terminado de usar la orden \hgcmd{bisect} en un
+repositorio, puede usar la orden \hgcmdargs{bisect}{reset} para
+deshacerse de la información que se estaba usando para lograr la
+búsqueda. Lar orden no usa mucho espacio, así que no hay problema si
+olvida ejecutar la orden.  En todo caso, \hgcmd{bisect} no le
+permitirá comenzar una nueva búsqueda sobre el repositorio hasta que
+no aplique \hgcmdargs{bisect}{reset}.
+\interaction{bisect.search.reset}
+
+\section{Consejos para encontrar fallos efectivamente}
+
+\subsection{Dar una entrada consistente}
+
+La orden \hgcmd{bisect} requiere que usted ofrezca un reporte correcto
+del resultado de cada prueba que aplique.  Si usted le dice que una
+prueba falla cuando en realidad era acertada, \emph{podría} detectar
+la inconsistencia. Si puede identificar una inconsistencia en sus
+reportes, le dirá que un conjunto de cambios particular es a la vez
+bueno y malo.  Aunque puede no hacerlo; estaría tratando de reportar
+un conjunto de cambios como el responsable de un fallo aunque no lo
+sea.
+
+\subsection{Automatizar tanto como se pueda}
+
+Cuando comencé a usar la orden \hgcmd{bisect}, intenté ejecutar
+algunas veces las pruebas a mano desde la línea de comandos. Es una
+aproximación a la cual no esta acostumbrado. Después de algunos
+intentos, me di cuenta que estaba cometiendo tantas equivocaciones que
+tenía que comenzar de nuevo con mis búsquedas varias veces antes de
+llegar a los resultados deseados.
+
+Mi problema inicial al dirigir a la orden \hgcmd{bisect} manualmente
+ocurrieron incluso con búsquedas en repositorios pequeños; si el
+problema que está buscando es más sutil, o el número de pruebas que
+\hgcmd{bisect} debe aplicar, la posibilidad de errar es mucho más
+alta. Una vez que comencé a automatizar mis pruebas, obtuve mejores
+resultados.
+
+La clave para las pruebas automatizadas se puede resumir en:
+\begin{itemize}
+\item pruebe siempre buscando el mismo síntoma y
+\item ofrezca siempre datos consistentes a la orden \hgcmd{bisect}.
+\end{itemize}
+En mi tutorial de ejemplo anterior, la orden \command{grep} busca el
+síntoma, y la construcción \texttt{if} toma el resultado de esta
+prueba y verifica que siempre alimentamos con los mismos datos a la
+orden \hgcmd{bisect}. La función \texttt{mytest} los une de una forma
+reproducible, logrando que cada prueba sea uniforme y consistente.
+
+\subsection{Verificar los resultados}
+
+Dado que la salida de la búsqueda de \hgcmd{bisect} es tan buena como
+los datos ofrecidos por usted, no confíe en esto como si fuera la
+verdad absoluta. Una forma sencilla de asegurarse es ejecutar
+manualmente su prueba a cada uno de los siguientes conjuntos de
+cambios:
+\begin{itemize}
+\item El conjunto de cambios que se reportó como la primera versión
+  erronea. Su prueba debería dar un reporte de fallo.
+\item El conjunto de cambios padre (cada padre, si es una fusión).
+  Su prueba debería reportar este(os) conjunto(s) de cambios como
+  bueno(s).
+\item Un hijo del conjunto de cambios. Su prueba debería reportar al
+  conjunto de cambios hijo como malo.
+\end{itemize}
+
+\subsection{Tener en cuenta la interferencia entre fallos}
+
+Es posible que su búsqueda de un fallo pueda viciarse por la presencia
+de otro. Por ejemplo, digamos que su programa se revienta en la
+revisión 100, y que funcionó correctamente en la revisión 50.  Sin su
+conocimiento, alguien introdujo un fallo con consecuencias grandes en
+la revisión 60, y lo arregló en la revisión 80. Sus resultados
+estarían distorcionados de una o muchas formas.
+
+Es posible que este fallo ``enmascare'' completamente al suyo, y que
+podría haberse revelado antes de que su propio fallo haya tenido
+oportunidad de manifestarse. Si no puede saltar el otro fallo (por
+ejemplo, este evita que su proyecto se arme o compile), y de esta
+forma no se pueda revisar si su fallo esté presente en un conjunto
+particular de cambios, la orden \hgcmd{bisect} no podrá ayudarle
+directamente. En cambio, puede marcar este conjunto de cambios como
+al ejecutar \hgcmdargs{bisect}{--skip}.
+
+Un problema distinto podría surgir si su prueba de la presencia de un
+fallo no es suficientemente específica. Si usted busca ``mi programa
+se revienta'', entonces tanto su fallo como el otro fallo sin relación
+que terminan presentando síntomas distintos, podría terminar
+confundiendo a \hgcmd{bisect}.
+
+Otra situación en la cual sería de mucha utilidad emplear a
+\hgcmdargs{bisect}{--skip} surge cuando usted no puede probar una
+revisión porque su proyecto estaba en una situación de rompimiento y
+por lo tanto en un estado en el cual era imposible hacer la prueba en
+esa revisión, tal vez porque alguien consignó un cambio que hacía
+imposible la construcción del proyecto.
+
+\subsection{Acotar la búsqueda perezosamente}
+
+Elegir los primeros ``buenos'' y ``malos'' conjuntos de cambios que
+marcarán los límites de su búsqueda en general es sencillo, pero vale
+la pena discutirlo.  Desde la perspectiva de \hgcmd{bisect}, el
+conjunto de cambios ``más nuevo'' por convención es el ``malo'', y el
+otro conjunto de cambios es el ``bueno''.
+
+Si no recuerda cuál podría ser el cambio ``bueno'', para informar a
+\hgcmd{bisect}, podría hacer pruebas aleatorias en el peor de los
+casos. Pero recuerde eliminar aquellos conjuntos de cambios que
+podrían no exhibir el fallo (tal vez porque la característica donde se
+presenta el fallo todavía no está presente) y aquellos en los cuales
+otro fallo puede enmascararlo (como se discutió anteriormente).
+
+Incluso si termina ``muy atrás'' por miles de conjuntos de cambios o
+meses de historial, solamente estaŕa adicionando unas pruebas contadas
+para \hgcmd{bisect}, gracias al comportamiento logarítmico.
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/wdir-after-commit.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,413 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg5971"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docbase="/home/bos/hg/hgbook/en"
+   sodipodi:docname="wdir-after-commit.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs5973">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective3128" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6445"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path4855"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <linearGradient
+       id="linearGradient6049">
+      <stop
+         style="stop-color:#686868;stop-opacity:1;"
+         offset="0"
+         id="stop6051" />
+      <stop
+         style="stop-color:#f0f0f0;stop-opacity:1;"
+         offset="1"
+         id="stop6053" />
+    </linearGradient>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path4852"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6083"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-240.0462,-8.633237e-6)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6142"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-42.00893,-30.49544)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6193"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-240.0462,-8.633237e-6)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6216"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-6.0462,-0.664361)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6232"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6772"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.90509668"
+     inkscape:cx="390.0539"
+     inkscape:cy="602.10507"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="11"
+     inkscape:window-y="8"
+     showgrid="false">
+    <sodipodi:guide
+       orientation="vertical"
+       position="-1.4285714"
+       id="guide6022" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata5976">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       y="245.98355"
+       x="328.23956"
+       height="258.57144"
+       width="174.28572"
+       id="rect6047"
+       style="fill:url(#linearGradient6216);fill-opacity:1;stroke:#686868;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <g
+       id="g6261"
+       transform="translate(234,0)">
+      <rect
+         y="258.7149"
+         x="114.11369"
+         height="44.537449"
+         width="134.53746"
+         id="rect5983"
+         style="fill:#b1b1b1;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text5985"
+         y="284.47562"
+         x="138.7962"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="284.47562"
+           x="138.7962"
+           id="tspan5987"
+           sodipodi:role="line">dfbbb33f3fa3</tspan></text>
+    </g>
+    <rect
+       style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect5996"
+       width="134.53746"
+       height="44.537449"
+       x="348.11371"
+       y="320.38159" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="372.7962"
+       y="346.1423"
+       id="text5998"><tspan
+         sodipodi:role="line"
+         id="tspan6000"
+         x="372.7962"
+         y="346.1423"
+         style="font-family:Courier">e7639888bb2f</tspan></text>
+    <rect
+       style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect6004"
+       width="134.53746"
+       height="44.537449"
+       x="348.11371"
+       y="382.04825" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="370.65421"
+       y="407.80896"
+       id="text6006"><tspan
+         sodipodi:role="line"
+         id="tspan6008"
+         x="370.65421"
+         y="407.80896"
+         style="font-family:Courier">7b064d8bac5e</tspan></text>
+    <path
+       inkscape:connector-type="polyline"
+       id="path6018"
+       d="M 415.38242,303.62646 L 415.38242,320.00744"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1" />
+    <path
+       inkscape:connection-end="#rect6004"
+       inkscape:connector-type="polyline"
+       id="path6020"
+       d="M 415.38242,365.29315 L 415.38243,381.67412"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1" />
+    <rect
+       style="fill:#ededed;fill-opacity:1;stroke:#797979;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect6039"
+       width="134.53746"
+       height="44.537449"
+       x="348.11359"
+       y="443.71487" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#979797;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="372.79706"
+       y="469.47556"
+       id="text6041"><tspan
+         sodipodi:role="line"
+         id="tspan6043"
+         x="372.79706"
+         y="469.47556"
+         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
+    <path
+       inkscape:connection-end="#rect6039"
+       inkscape:connector-type="polyline"
+       id="path6045"
+       d="M 415.38238,426.95981 L 415.38235,443.34087"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#686868;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="327.66046"
+       y="231.36218"
+       id="text6102"><tspan
+         sodipodi:role="line"
+         id="tspan6104"
+         x="327.66046"
+         y="231.36218">Historia en el repositorio</tspan></text>
+    <rect
+       y="245.94225"
+       x="557.28418"
+       height="204.51619"
+       width="174.36833"
+       id="rect6140"
+       style="fill:url(#linearGradient6232);fill-opacity:1;stroke:#686868;stroke-width:0.66539276;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <g
+       id="g6130"
+       transform="translate(262.3254,24.38544)">
+      <rect
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect6106"
+         width="134.53746"
+         height="44.537449"
+         x="314.87415"
+         y="257.95059" />
+      <text
+         xml:space="preserve"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         x="339.55664"
+         y="283.7113"
+         id="text6108"><tspan
+           sodipodi:role="line"
+           id="tspan6110"
+           x="339.55664"
+           y="283.7113"
+           style="font-family:Courier">dfbbb33f3fa3</tspan></text>
+    </g>
+    <g
+       id="g6135"
+       transform="translate(263.0396,49.83106)">
+      <rect
+         inkscape:transform-center-y="102.85714"
+         inkscape:transform-center-x="129.28571"
+         style="fill:#ededed;fill-opacity:1;stroke:#797979;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect6112"
+         width="134.53746"
+         height="44.537449"
+         x="314.15985"
+         y="326.52203" />
+      <text
+         inkscape:transform-center-y="102.7311"
+         inkscape:transform-center-x="128.69672"
+         xml:space="preserve"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#979797;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         x="338.84335"
+         y="352.28271"
+         id="text6114"><tspan
+           sodipodi:role="line"
+           id="tspan6116"
+           x="338.84335"
+           y="352.28271"
+           style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="576.63208"
+       y="270.479"
+       id="text6118"><tspan
+         sodipodi:role="line"
+         id="tspan6120"
+         x="576.63208"
+         y="270.479">Primer padre</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="576.07544"
+       y="364.49615"
+       id="text6122"><tspan
+         sodipodi:role="line"
+         id="tspan6124"
+         x="576.07544"
+         y="364.49615">Segundo padre</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="556.61743"
+       y="231.36218"
+       id="text6195"><tspan
+         sodipodi:role="line"
+         id="tspan6197"
+         x="556.61743"
+         y="231.36218">Padres del directorio de trabajo</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       d="M 576.82542,297.63008 L 483.02528,287.95831"
+       id="path6266"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g6130"
+       inkscape:connection-end="#g6261" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 665.12232,418.17579 L 665.12232,418.17579"
+       id="path6270"
+       inkscape:connector-type="polyline" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="316.86407"
+       y="275.6496"
+       id="text6573"><tspan
+         sodipodi:role="line"
+         id="tspan6575"
+         x="316.86407"
+         y="275.6496"
+         style="text-align:end;text-anchor:end">Nuevo</tspan><tspan
+         sodipodi:role="line"
+         x="316.86407"
+         y="290.6496"
+         id="tspan6577"
+         style="text-align:end;text-anchor:end">conjunto</tspan><tspan
+         sodipodi:role="line"
+         x="316.86407"
+         y="305.6496"
+         style="text-align:end;text-anchor:end"
+         id="tspan3470">de</tspan><tspan
+         sodipodi:role="line"
+         x="316.86407"
+         y="320.6496"
+         style="text-align:end;text-anchor:end"
+         id="tspan3472">cambios</tspan></text>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/wdir-branch.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,427 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg5971"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docbase="/home/bos/hg/hgbook/en"
+   sodipodi:docname="wdir-branch.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs5973">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective3193" />
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path4855"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <linearGradient
+       id="linearGradient6049">
+      <stop
+         style="stop-color:#686868;stop-opacity:1;"
+         offset="0"
+         id="stop6051" />
+      <stop
+         style="stop-color:#f0f0f0;stop-opacity:1;"
+         offset="1"
+         id="stop6053" />
+    </linearGradient>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path4852"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6083"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-240.0462,-8.633237e-6)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6142"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-42.00893,-30.49544)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6193"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-240.0462,-8.633237e-6)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6216"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6232"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6445"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6974"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6996"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.90509668"
+     inkscape:cx="345.85973"
+     inkscape:cy="690.49342"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="75"
+     inkscape:window-y="69"
+     showgrid="false">
+    <sodipodi:guide
+       orientation="vertical"
+       position="-1.4285714"
+       id="guide6022" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata5976">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       y="246.06918"
+       x="64.325172"
+       height="204.26233"
+       width="333.2135"
+       id="rect6047"
+       style="fill:url(#linearGradient6974);fill-opacity:1;stroke:#686868;stroke-width:0.91925466;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <g
+       id="g1935">
+      <rect
+         y="266.24374"
+         x="84.113708"
+         height="44.537449"
+         width="134.53746"
+         id="rect5996"
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text5998"
+         y="292.00446"
+         x="108.7962"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="292.00446"
+           x="108.7962"
+           id="tspan6000"
+           sodipodi:role="line">e7639888bb2f</tspan></text>
+    </g>
+    <g
+       id="g6976"
+       transform="translate(70,0)">
+      <rect
+         y="327.9104"
+         x="40.113693"
+         height="44.537449"
+         width="134.53746"
+         id="rect6004"
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text6006"
+         y="353.67111"
+         x="62.654205"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="353.67111"
+           x="62.654205"
+           id="tspan6008"
+           sodipodi:role="line">7b064d8bac5e</tspan></text>
+    </g>
+    <path
+       inkscape:connector-type="polyline"
+       id="path6020"
+       d="M 160.92915,311.15532 L 167.83571,327.53627"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       inkscape:connection-end="#g6976"
+       inkscape:connection-start="#g1935" />
+    <rect
+       style="fill:#ededed;fill-opacity:1;stroke:#797979;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect6039"
+       width="134.53746"
+       height="44.537449"
+       x="110.11359"
+       y="389.57703" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#979797;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="134.79706"
+       y="415.33771"
+       id="text6041"><tspan
+         sodipodi:role="line"
+         id="tspan6043"
+         x="134.79706"
+         y="415.33771"
+         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
+    <path
+       inkscape:connection-end="#rect6039"
+       inkscape:connector-type="polyline"
+       id="path6045"
+       d="M 177.38238,372.82195 L 177.38235,389.20303"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#686868;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1" />
+    <rect
+       y="245.94225"
+       x="447.28412"
+       height="204.51619"
+       width="174.36833"
+       id="rect6140"
+       style="fill:url(#linearGradient6996);fill-opacity:1;stroke:#686868;stroke-width:0.66539276;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <g
+       id="g6130"
+       transform="translate(152.3254,24.38544)">
+      <rect
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect6106"
+         width="134.53746"
+         height="44.537449"
+         x="314.87415"
+         y="257.95059" />
+      <text
+         xml:space="preserve"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         x="339.55664"
+         y="283.7113"
+         id="text6108"><tspan
+           sodipodi:role="line"
+           id="tspan6110"
+           x="339.55664"
+           y="283.7113"
+           style="font-family:Courier">ffb20e1701ea</tspan></text>
+    </g>
+    <g
+       id="g6135"
+       transform="translate(153.0396,49.83106)">
+      <rect
+         inkscape:transform-center-y="102.85714"
+         inkscape:transform-center-x="129.28571"
+         style="fill:#ededed;fill-opacity:1;stroke:#797979;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect6112"
+         width="134.53746"
+         height="44.537449"
+         x="314.15985"
+         y="326.52203" />
+      <text
+         inkscape:transform-center-y="102.7311"
+         inkscape:transform-center-x="128.69672"
+         xml:space="preserve"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#979797;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         x="338.84335"
+         y="352.28271"
+         id="text6114"><tspan
+           sodipodi:role="line"
+           id="tspan6116"
+           x="338.84335"
+           y="352.28271"
+           style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="466.63208"
+       y="270.479"
+       id="text6118"><tspan
+         sodipodi:role="line"
+         id="tspan6120"
+         x="466.63208"
+         y="270.479">Primer padre</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="466.07544"
+       y="364.49615"
+       id="text6122"><tspan
+         sodipodi:role="line"
+         id="tspan6124"
+         x="466.07544"
+         y="364.49615">Segundo padre</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="446.61743"
+       y="231.36218"
+       id="text6195"><tspan
+         sodipodi:role="line"
+         id="tspan6197"
+         x="446.61743"
+         y="231.36218">Padres del directorio de trabajo</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+       d="M 466.82542,300.21999 L 377.00207,294.39744"
+       id="path6266"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g6130"
+       inkscape:connection-end="#rect1925" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 665.12232,418.17579 L 665.12232,418.17579"
+       id="path6270"
+       inkscape:connector-type="polyline" />
+    <g
+       id="g2845">
+      <rect
+         y="266.24374"
+         x="242.09048"
+         height="44.537449"
+         width="134.53746"
+         id="rect1925"
+         style="fill:#9f9f9f;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text1927"
+         y="292.00446"
+         x="266.77298"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="292.00446"
+           x="266.77298"
+           id="tspan1929"
+           sodipodi:role="line">ffb20e1701ea</tspan></text>
+    </g>
+    <path
+       inkscape:connector-type="polyline"
+       id="path1933"
+       d="M 260.89978,311.15532 L 225.84185,327.53627"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       inkscape:connection-end="#g6976" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="109.45568"
+       y="231.4554"
+       id="text2837"><tspan
+         sodipodi:role="line"
+         id="tspan2839"
+         x="109.45568"
+         y="231.4554">Cabeza Pre-existente</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="237.54184"
+       y="231.4554"
+       id="text2841"><tspan
+         sodipodi:role="line"
+         id="tspan2843"
+         x="237.54184"
+         y="231.4554">Cabeza recién creada (y tip)</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="M 148.05048,235.87482 L 149.94915,265.86962"
+       id="path2850"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#g1935" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="M 303.83495,238.08453 L 306.87874,265.86962"
+       id="path2852"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#g2845" />
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/wdir-merge.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,434 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg5971"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docbase="/home/bos/hg/hgbook/en"
+   sodipodi:docname="wdir-merge.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs5973">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective3259" />
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path4855"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <linearGradient
+       id="linearGradient6049">
+      <stop
+         style="stop-color:#686868;stop-opacity:1;"
+         offset="0"
+         id="stop6051" />
+      <stop
+         style="stop-color:#f0f0f0;stop-opacity:1;"
+         offset="1"
+         id="stop6053" />
+    </linearGradient>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path4852"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6083"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-240.0462,-8.633237e-6)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6142"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-42.00893,-30.49544)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6193"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-240.0462,-8.633237e-6)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6216"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6232"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6445"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6974"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6996"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.28"
+     inkscape:cx="345.85973"
+     inkscape:cy="690.49342"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="338"
+     inkscape:window-y="50"
+     showgrid="false">
+    <sodipodi:guide
+       orientation="vertical"
+       position="-1.4285714"
+       id="guide6022" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata5976">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       y="246.06918"
+       x="64.325172"
+       height="204.26233"
+       width="333.2135"
+       id="rect6047"
+       style="fill:url(#linearGradient6974);fill-opacity:1;stroke:#686868;stroke-width:0.91925466;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <g
+       id="g6976"
+       transform="translate(70,0)">
+      <rect
+         y="327.9104"
+         x="40.113693"
+         height="44.537449"
+         width="134.53746"
+         id="rect6004"
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text6006"
+         y="353.67111"
+         x="62.654205"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="353.67111"
+           x="62.654205"
+           id="tspan6008"
+           sodipodi:role="line">7b064d8bac5e</tspan></text>
+    </g>
+    <path
+       inkscape:connector-type="polyline"
+       id="path6020"
+       d="M 160.92915,311.15532 L 167.83571,327.53627"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       inkscape:connection-end="#g6976"
+       inkscape:connection-start="#g1935" />
+    <rect
+       style="fill:#ededed;fill-opacity:1;stroke:#797979;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect6039"
+       width="134.53746"
+       height="44.537449"
+       x="110.11359"
+       y="389.57703" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#979797;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="134.79706"
+       y="415.33771"
+       id="text6041"><tspan
+         sodipodi:role="line"
+         id="tspan6043"
+         x="134.79706"
+         y="415.33771"
+         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
+    <path
+       inkscape:connection-end="#rect6039"
+       inkscape:connector-type="polyline"
+       id="path6045"
+       d="M 177.38238,372.82195 L 177.38235,389.20303"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#686868;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1" />
+    <rect
+       y="245.94225"
+       x="447.28412"
+       height="204.51619"
+       width="174.36833"
+       id="rect6140"
+       style="fill:url(#linearGradient6996);fill-opacity:1;stroke:#686868;stroke-width:0.66539276;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <g
+       id="g6130"
+       transform="translate(152.3254,24.38544)">
+      <rect
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect6106"
+         width="134.53746"
+         height="44.537449"
+         x="314.87415"
+         y="257.95059" />
+      <text
+         xml:space="preserve"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         x="339.55664"
+         y="283.7113"
+         id="text6108"><tspan
+           sodipodi:role="line"
+           id="tspan6110"
+           x="339.55664"
+           y="283.7113"
+           style="font-family:Courier">ffb20e1701ea</tspan></text>
+    </g>
+    <g
+       id="g6135"
+       transform="translate(153.0396,49.83106)">
+      <rect
+         inkscape:transform-center-y="102.85714"
+         inkscape:transform-center-x="129.28571"
+         style="fill:#d4d4d4;fill-opacity:1;stroke:#797979;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect6112"
+         width="134.53746"
+         height="44.537449"
+         x="314.15985"
+         y="326.52203" />
+      <text
+         inkscape:transform-center-y="102.7311"
+         inkscape:transform-center-x="128.69672"
+         xml:space="preserve"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#979797;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         x="338.84335"
+         y="352.28271"
+         id="text6114"><tspan
+           sodipodi:role="line"
+           id="tspan6116"
+           x="338.84335"
+           y="352.28271"
+           style="fill:black;fill-opacity:1;font-family:Courier">e7639888bb2f</tspan></text>
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="466.63208"
+       y="270.479"
+       id="text6118"><tspan
+         sodipodi:role="line"
+         id="tspan6120"
+         x="466.63208"
+         y="270.479">Primer padre (sin cambio)</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="466.07544"
+       y="364.49615"
+       id="text6122"><tspan
+         sodipodi:role="line"
+         id="tspan6124"
+         x="466.07544"
+         y="364.49615">Segundo padre</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="446.61743"
+       y="231.36218"
+       id="text6195"><tspan
+         sodipodi:role="line"
+         id="tspan6197"
+         x="446.61743"
+         y="231.36218">Padres del directorio de trabajo</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+       d="M 466.82542,300.21999 L 377.00207,294.39744"
+       id="path6266"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g6130"
+       inkscape:connection-end="#rect1925" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 665.12232,418.17579 L 665.12232,418.17579"
+       id="path6270"
+       inkscape:connector-type="polyline" />
+    <g
+       id="g2845">
+      <rect
+         y="266.24374"
+         x="242.09048"
+         height="44.537449"
+         width="134.53746"
+         id="rect1925"
+         style="fill:#9f9f9f;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text1927"
+         y="292.00446"
+         x="266.77298"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="292.00446"
+           x="266.77298"
+           id="tspan1929"
+           sodipodi:role="line">ffb20e1701ea</tspan></text>
+    </g>
+    <path
+       inkscape:connector-type="polyline"
+       id="path1933"
+       d="M 260.89978,311.15532 L 225.84185,327.53627"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1;display:inline"
+       inkscape:connection-end="#g6976" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="109.45568"
+       y="231.4554"
+       id="text2837"><tspan
+         sodipodi:role="line"
+         id="tspan2839"
+         x="109.45568"
+         y="231.4554">Cabeza pre-existente</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="237.54184"
+       y="231.4554"
+       id="text2841"><tspan
+         sodipodi:role="line"
+         id="tspan2843"
+         x="237.54184"
+         y="231.4554">Cabeza recién creada(y tip)</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="M 148.05048,235.87482 L 149.94915,265.86962"
+       id="path2850"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#g1935" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow1Mend)"
+       d="M 303.83495,238.08453 L 306.87874,265.86962"
+       id="path2852"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#g2845" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+       d="M 466.82545,379.17944 L 219.0253,307.95488"
+       id="path3016"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g6135"
+       inkscape:connection-end="#g1935" />
+    <g
+       id="g1935">
+      <rect
+         y="266.24374"
+         x="84.113708"
+         height="44.537449"
+         width="134.53746"
+         id="rect5996"
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text5998"
+         y="292.00446"
+         x="108.7962"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="292.00446"
+           x="108.7962"
+           id="tspan6000"
+           sodipodi:role="line">e7639888bb2f</tspan></text>
+    </g>
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/wdir-pre-branch.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,373 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg5971"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docbase="/home/bos/hg/hgbook/en"
+   sodipodi:docname="wdir-pre-branch.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs5973">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective3314" />
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path4855"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <linearGradient
+       id="linearGradient6049">
+      <stop
+         style="stop-color:#686868;stop-opacity:1;"
+         offset="0"
+         id="stop6051" />
+      <stop
+         style="stop-color:#f0f0f0;stop-opacity:1;"
+         offset="1"
+         id="stop6053" />
+    </linearGradient>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path4852"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6083"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-240.0462,-8.633237e-6)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6142"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-42.00893,-30.49544)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6193"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-240.0462,-8.633237e-6)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6216"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6232"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6445"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6974"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,-314.246,50.85694)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6996"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000473,0,0,0.790947,-85.16012,50.85693)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.64"
+     inkscape:cx="235.37429"
+     inkscape:cy="726.21069"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="2"
+     inkscape:window-y="43"
+     showgrid="false">
+    <sodipodi:guide
+       orientation="vertical"
+       position="-1.4285714"
+       id="guide6022" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata5976">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <rect
+       y="245.94225"
+       x="20.198257"
+       height="204.51619"
+       width="174.36833"
+       id="rect6047"
+       style="fill:url(#linearGradient6974);fill-opacity:1;stroke:#686868;stroke-width:0.66539276;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <rect
+       style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect5996"
+       width="134.53746"
+       height="44.537449"
+       x="40.113693"
+       y="266.24374" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="64.796204"
+       y="292.00446"
+       id="text5998"><tspan
+         sodipodi:role="line"
+         id="tspan6000"
+         x="64.796204"
+         y="292.00446"
+         style="font-family:Courier">e7639888bb2f</tspan></text>
+    <g
+       id="g6976">
+      <rect
+         y="327.9104"
+         x="40.113693"
+         height="44.537449"
+         width="134.53746"
+         id="rect6004"
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text6006"
+         y="353.67111"
+         x="62.654205"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="353.67111"
+           x="62.654205"
+           id="tspan6008"
+           sodipodi:role="line">7b064d8bac5e</tspan></text>
+    </g>
+    <path
+       inkscape:connection-end="#rect6004"
+       inkscape:connector-type="polyline"
+       id="path6020"
+       d="M 107.38242,311.15529 L 107.38242,327.53626"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1" />
+    <rect
+       style="fill:#ededed;fill-opacity:1;stroke:#797979;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+       id="rect6039"
+       width="134.53746"
+       height="44.537449"
+       x="40.113571"
+       y="389.57703" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#979797;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="64.797073"
+       y="415.33771"
+       id="text6041"><tspan
+         sodipodi:role="line"
+         id="tspan6043"
+         x="64.797073"
+         y="415.33771"
+         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
+    <path
+       inkscape:connection-end="#rect6039"
+       inkscape:connector-type="polyline"
+       id="path6045"
+       d="M 107.38238,372.82195 L 107.38235,389.20301"
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#686868;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1" />
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="19.660461"
+       y="231.36218"
+       id="text6102"><tspan
+         sodipodi:role="line"
+         id="tspan6104"
+         x="19.660461"
+         y="231.36218">Historia en el repositorio</tspan></text>
+    <rect
+       y="245.94225"
+       x="249.28412"
+       height="204.51619"
+       width="174.36833"
+       id="rect6140"
+       style="fill:url(#linearGradient6996);fill-opacity:1;stroke:#686868;stroke-width:0.66539276;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+    <g
+       id="g6130"
+       transform="translate(-45.67459,24.38544)">
+      <rect
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect6106"
+         width="134.53746"
+         height="44.537449"
+         x="314.87415"
+         y="257.95059" />
+      <text
+         xml:space="preserve"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         x="339.55664"
+         y="283.7113"
+         id="text6108"><tspan
+           sodipodi:role="line"
+           id="tspan6110"
+           x="339.55664"
+           y="283.7113"
+           style="font-family:Courier">7b064d8bac5e</tspan></text>
+    </g>
+    <g
+       id="g6135"
+       transform="translate(-44.96042,49.83106)">
+      <rect
+         inkscape:transform-center-y="102.85714"
+         inkscape:transform-center-x="129.28571"
+         style="fill:#ededed;fill-opacity:1;stroke:#797979;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect6112"
+         width="134.53746"
+         height="44.537449"
+         x="314.15985"
+         y="326.52203" />
+      <text
+         inkscape:transform-center-y="102.7311"
+         inkscape:transform-center-x="128.69672"
+         xml:space="preserve"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#979797;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         x="338.84335"
+         y="352.28271"
+         id="text6114"><tspan
+           sodipodi:role="line"
+           id="tspan6116"
+           x="338.84335"
+           y="352.28271"
+           style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="268.63208"
+       y="270.479"
+       id="text6118"><tspan
+         sodipodi:role="line"
+         id="tspan6120"
+         x="268.63208"
+         y="270.479">Primer padre</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="268.07544"
+       y="364.49615"
+       id="text6122"><tspan
+         sodipodi:role="line"
+         id="tspan6124"
+         x="268.07544"
+         y="364.49615">Segundo padre</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="248.61746"
+       y="231.36218"
+       id="text6195"><tspan
+         sodipodi:role="line"
+         id="tspan6197"
+         x="248.61746"
+         y="231.36218">Padres del directorio de trabajo</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+       d="M 268.82543,318.06163 L 175.02528,336.72225"
+       id="path6266"
+       inkscape:connector-type="polyline"
+       inkscape:connection-end="#g6976"
+       inkscape:connection-start="#g6130" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 665.12232,418.17579 L 665.12232,418.17579"
+       id="path6270"
+       inkscape:connector-type="polyline" />
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/es/wdir.svg	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,357 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="744.09448819"
+   height="1052.3622047"
+   id="svg5971"
+   sodipodi:version="0.32"
+   inkscape:version="0.46"
+   sodipodi:docbase="/home/bos/hg/hgbook/en"
+   sodipodi:docname="wdir.svg"
+   inkscape:output_extension="org.inkscape.output.svg.inkscape">
+  <defs
+     id="defs5973">
+    <inkscape:perspective
+       sodipodi:type="inkscape:persp3d"
+       inkscape:vp_x="0 : 526.18109 : 1"
+       inkscape:vp_y="0 : 1000 : 0"
+       inkscape:vp_z="744.09448 : 526.18109 : 1"
+       inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+       id="perspective3368" />
+    <marker
+       inkscape:stockid="Arrow1Mstart"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mstart"
+       style="overflow:visible">
+      <path
+         id="path4855"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
+         transform="scale(0.4) translate(10,0)" />
+    </marker>
+    <linearGradient
+       id="linearGradient6049">
+      <stop
+         style="stop-color:#686868;stop-opacity:1;"
+         offset="0"
+         id="stop6051" />
+      <stop
+         style="stop-color:#f0f0f0;stop-opacity:1;"
+         offset="1"
+         id="stop6053" />
+    </linearGradient>
+    <marker
+       inkscape:stockid="Arrow1Mend"
+       orient="auto"
+       refY="0.0"
+       refX="0.0"
+       id="Arrow1Mend"
+       style="overflow:visible;">
+      <path
+         id="path4852"
+         d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
+         transform="scale(0.4) rotate(180) translate(10,0)" />
+    </marker>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6083"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-240.0462,-8.633237e-6)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6142"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-42.00893,-30.49544)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6193"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="translate(-240.0462,-8.633237e-6)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6216"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6232"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient6049"
+       id="linearGradient6445"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
+       x1="333.91171"
+       y1="488.79077"
+       x2="508.94543"
+       y2="263.79077" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     gridtolerance="10000"
+     guidetolerance="10"
+     objecttolerance="10"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.8101934"
+     inkscape:cx="301.66555"
+     inkscape:cy="721.33993"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:window-width="906"
+     inkscape:window-height="659"
+     inkscape:window-x="355"
+     inkscape:window-y="55"
+     showgrid="false">
+    <sodipodi:guide
+       orientation="vertical"
+       position="-1.4285714"
+       id="guide6022" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata5976">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1">
+    <g
+       id="g6431"
+       transform="translate(0,-0.137863)">
+      <rect
+         style="fill:url(#linearGradient6445);fill-opacity:1;stroke:#686868;stroke-width:0.66539276;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect6047"
+         width="174.36833"
+         height="204.51619"
+         x="94.198257"
+         y="246.08011" />
+      <rect
+         y="266.38159"
+         x="114.11369"
+         height="44.537449"
+         width="134.53746"
+         id="rect5996"
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text5998"
+         y="292.1423"
+         x="138.7962"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="292.1423"
+           x="138.7962"
+           id="tspan6000"
+           sodipodi:role="line">e7639888bb2f</tspan></text>
+      <rect
+         y="328.04825"
+         x="114.11369"
+         height="44.537449"
+         width="134.53746"
+         id="rect6004"
+         style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text6006"
+         y="353.80896"
+         x="136.65421"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="font-family:Courier"
+           y="353.80896"
+           x="136.65421"
+           id="tspan6008"
+           sodipodi:role="line">7b064d8bac5e</tspan></text>
+      <path
+         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+         d="M 181.38242,311.29315 L 181.38242,327.67412"
+         id="path6020"
+         inkscape:connector-type="polyline"
+         inkscape:connection-end="#rect6004" />
+      <rect
+         y="389.71487"
+         x="114.11357"
+         height="44.537449"
+         width="134.53746"
+         id="rect6039"
+         style="fill:#ededed;fill-opacity:1;stroke:#797979;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
+      <text
+         id="text6041"
+         y="415.47556"
+         x="138.79707"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#979797;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           style="fill:#979797;fill-opacity:1;font-family:Courier"
+           y="415.47556"
+           x="138.79707"
+           id="tspan6043"
+           sodipodi:role="line">000000000000</tspan></text>
+      <path
+         style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:#686868;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
+         d="M 181.38238,372.95981 L 181.38235,389.34087"
+         id="path6045"
+         inkscape:connector-type="polyline"
+         inkscape:connection-end="#rect6039" />
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="93.660484"
+       y="231.36218"
+       id="text6102"><tspan
+         sodipodi:role="line"
+         id="tspan6104"
+         x="93.660484"
+         y="231.36218">Historia en el repositorio</tspan></text>
+    <g
+       id="g6416">
+      <rect
+         style="fill:url(#linearGradient6232);fill-opacity:1;stroke:#686868;stroke-width:0.66539276;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+         id="rect6140"
+         width="174.36833"
+         height="204.51619"
+         x="323.28412"
+         y="245.94225" />
+      <g
+         transform="translate(28.32541,24.38544)"
+         id="g6130">
+        <rect
+           y="257.95059"
+           x="314.87415"
+           height="44.537449"
+           width="134.53746"
+           id="rect6106"
+           style="fill:#d4d4d4;fill-opacity:1;stroke:black;stroke-width:0.7482574;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.49651474, 0.74825737;stroke-dashoffset:0;stroke-opacity:1" />
+        <text
+           id="text6108"
+           y="283.7113"
+           x="339.55664"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           xml:space="preserve"><tspan
+             style="font-family:Courier"
+             y="283.7113"
+             x="339.55664"
+             id="tspan6110"
+             sodipodi:role="line">e7639888bb2f</tspan></text>
+      </g>
+      <g
+         transform="translate(29.03958,49.83106)"
+         id="g6135">
+        <rect
+           y="326.52203"
+           x="314.15985"
+           height="44.537449"
+           width="134.53746"
+           id="rect6112"
+           style="fill:#ededed;fill-opacity:1;stroke:#797979;stroke-width:0.74800003;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+           inkscape:transform-center-x="129.28571"
+           inkscape:transform-center-y="102.85714" />
+        <text
+           id="text6114"
+           y="352.28271"
+           x="338.84335"
+           style="font-size:12px;font-style:normal;font-weight:normal;fill:#979797;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+           xml:space="preserve"
+           inkscape:transform-center-x="128.69672"
+           inkscape:transform-center-y="102.7311"><tspan
+             style="fill:#979797;fill-opacity:1;font-family:Courier"
+             y="352.28271"
+             x="338.84335"
+             id="tspan6116"
+             sodipodi:role="line">000000000000</tspan></text>
+      </g>
+      <text
+         id="text6118"
+         y="270.479"
+         x="342.63208"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           y="270.479"
+           x="342.63208"
+           id="tspan6120"
+           sodipodi:role="line">Primer padre</tspan></text>
+      <text
+         id="text6122"
+         y="364.49615"
+         x="342.07544"
+         style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+         xml:space="preserve"><tspan
+           y="364.49615"
+           x="342.07544"
+           id="tspan6124"
+           sodipodi:role="line">Segundo padre</tspan></text>
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
+       x="322.61746"
+       y="231.36218"
+       id="text6195"><tspan
+         sodipodi:role="line"
+         id="tspan6197"
+         x="322.61746"
+         y="231.36218">Padres del directorio de trabajo</tspan></text>
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline"
+       d="M 342.82543,299.89384 L 249.02528,293.36123"
+       id="path6266"
+       inkscape:connector-type="polyline"
+       inkscape:connection-start="#g6130"
+       inkscape:connection-end="#rect5996" />
+    <path
+       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 665.12232,418.17579 L 665.12232,418.17579"
+       id="path6270"
+       inkscape:connector-type="polyline" />
+  </g>
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/html/index.es.html	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,53 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html lang="es">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <link rel="icon" href="/hgicon.png" type="image/png">
+    <meta name="robots" content="index,follow">
+    <title>Control Distribuido de Revisiones con Mercurial</title>
+  </head>
+
+  <body>
+    <h1>Control Distribuido de Revisiones con Mercurial</h1>
+
+    <p>Bienvenido al sito del libro &ldquo;Control Distribuido de Revisiones con Mercurial&rdquo;, en español, 
+      por <a href="http://www.serpentine.com/blog/">Bryan O'Sullivan</a>.
+      Este libro está cobijado por una <a href="hgbookap4.html">licencia abierta</a>
+      y trata del sistema de control de revisiones
+      <a href="http://www.selenic.com/mercurial">Mercurial</a>.
+
+    <p>Los traductores son <a href="http://devnull.li/~jerojasro/blog/">Javier Rojas</a> e
+    <a href="http://igor.tamarapatino.org/">Igor Támara</a>. En este sitio usted puede encontrar:
+    <ul>
+      <li>La <a href="onepage.html">versi&oacute;n HTML</a> una sola página.</li>
+      <li>La <a href="hgbook.pdf">versi&oacute;n PDF</a> (1.9 megabytes.)</li>
+      <li>El <a href="http://mercurial.intuxication.org/hg/mercurial_book_es/">c&oacute;digo
+	fuente</a> de la traducci&oacute;n, si desea revisarla o colaborar con el proyecto. En 
+      <a href="http://hg.serpentine.com/mercurial/book">este sitio</a> puede
+      encontrar la versi&oacute;n original en ingl&eacute;s.</li>
+    </ul>
+    Para más detalles acerca del proceso de traducción, por favor vea <a
+        href="http://mercurial.intuxication.org/hg/mercurial_book_es/file/tip/es/Leame.1st">este
+        fichero</a>.
+
+    <h2>¿Cómo puede usted ayudar a Mercurial, y el software libre?</h2>
+
+    <p>Mercurial es miembro del <a
+	href="http://conservancy.softwarefreedom.org/">Conservatorio
+	de Software Libre</a>, una maravillosa organización sin ánimo
+      de lucro que ofrece a sus proyectos miembros consejo legal y
+      administrativo.  La SFC acepta <a href="http://conservancy.softwarefreedom.org/?donate">donaciones</a>
+      (deducibles de impuestos bajo IRS 501(c)(3), dentro de los Estados Unidos) 
+      en representación de sus proyectos miembros.  Si desea dar un apoyo
+      directo a Mercurial, por favor considere hacer una donación a SFC 
+      en su representación.</p>
+
+    <p>Si desea apoyar a los desarrolladores de software libre en su
+      importante servicio público sin estar impedido por cuestiones
+      legales, por favor considere donar a la organización hermana de
+      SFC, el <a
+	href="http://www.softwarefreedom.org/">Centro de Leyes de Software
+	Libre</a>.</p>
+  </body>
+</html>
--- a/html/index.html.var	Wed Jan 21 14:16:38 2009 +0100
+++ b/html/index.html.var	Mon Feb 09 22:59:50 2009 -0800
@@ -1,3 +1,7 @@
 URI: index.en.html
 Content-Language: en
 Content-Type: text/html; charset=UTF-8
+
+URI: index.es.html
+Content-Language: es
+Content-Type: text/html; charset=UTF-8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/latex-to-docbook	Mon Feb 09 22:59:50 2009 -0800
@@ -0,0 +1,192 @@
+#!/usr/bin/python
+#
+# This is the most horrible of hacks. Pretend you're not looking.</para>
+
+import cStringIO as StringIO
+import re, sys
+
+sections = {
+    'chapter': 'chapter',
+    'section': 'sect1',
+    'subsection': 'sect2',
+    'subsubsection': 'sect3',
+    }
+
+envs = {
+    'codesample2': 'programlisting',
+    'codesample4': 'programlisting',
+    'enumerate': 'orderedlist',
+    'figure': 'figure',
+    'itemize': 'itemizedlist',
+    'note': 'note',
+    'quote': 'blockquote',
+    }
+
+def process(ifp, ofp):
+    stack = []
+    para = True
+    inlist = False
+    for line in ifp:
+        if line.startswith('%%% Local Variables:'):
+            break
+        line = (line.rstrip()
+                .replace(' ', ' ')
+                .replace('&', '&amp;')
+                .replace('&emdash;', '&emdash;')
+                .replace('\_', '_')
+                .replace('\{', '{')
+                .replace('\}', '}')
+                .replace('\$', '$')
+                .replace('\%', '%')
+                .replace('\#', '#')
+                .replace('<', '&lt;')
+                .replace('>', '&gt;')
+                .replace('<quote>', '<quote>')
+                .replace("</quote>", '</quote>')
+                .replace('\\', '\\'))
+        line = re.sub(r'\s*\\(?:centering|small)\b\s*', '', line)
+        line = re.sub(r'\\(?:hgrc\\|hgrc)\b',
+                      r'<filename role="special"> /.hgrc</filename>', line)
+        line = re.sub(r'\\item\[(?P<key>[^]]+)\]', r'\item \g<key>:', line)
+        line = re.sub(r'\\bug{(?P<id>\d+)}',
+                      r'<ulink role="hg-bug" url="http://www.selenic.com/mercurial/bts/issue\g<id>">issue \g<id></ulink>', line)
+        line = re.sub(r'\\cite{([^}]+)}', r'<citation>\1</citation>', line)
+        line = re.sub(r'\\hggopt{(?P<opt>[^}]+)}',
+                      r'<option role="hg-opt-global">\g<opt></option>', line)
+        line = re.sub(r'\\hgxopt{(?P<ext>[^}]+)}{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
+                      r'<option role="hg-ext-\g<ext>-cmd-\g<cmd>-opt">\g<opt></option>', line)
+        line = re.sub(r'\\hgxcmd{(?P<ext>[^}]+)}{(?P<cmd>[^}]+)}',
+                      r'<command role="hg-ext-\g<ext>">\g<cmd></command>', line)
+        line = re.sub(r'\\hgext{(?P<ext>[^}]+)}',
+                      r'<literal role="hg-ext">\g<ext></literal>', line)
+        line = re.sub(r'\\hgopt{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
+                      r'<option role="hg-opt-\g<cmd>">\g<opt></option>',
+                      line)
+        line = re.sub(r'\\cmdopt{(?P<cmd>[^}]+)}{(?P<opt>[^}]+)}',
+                      r'<option role="cmd-opt-\g<cmd>">\g<opt></option>',
+                      line)
+        line = re.sub(r'\\hgcmd{(?P<cmd>[^}]+)}',
+                      r'<command role="hg-cmd">hg \g<cmd></command>', line)
+        line = re.sub(r'\\caption{(?P<text>[^}]+?)}',
+                      r'<caption>\g<text></caption>', line)
+        line = re.sub(r'\\grafix{(?P<name>[^}]+)}',
+                      r'<mediaobject><imageobject><imagedata fileref="\g<name>"/></imageobject><textobject><phrase>XXX add text</phrase></textobject></mediaobject>', line)
+        line = re.sub(r'\\envar{(?P<name>[^}]+)}',
+                      r'<envar>\g<name></envar>', line)
+        line = re.sub(r'\\rcsection{(?P<sect>[^}]+)}',
+                      r'<literal role="rc-\g<sect>">\g<sect></literal>', line)
+        line = re.sub(r'\\rcitem{(?P<sect>[^}]+)}{(?P<name>[^}]+)}',
+                      r'<envar role="rc-item-\g<sect>">\g<name></envar>', line)
+        line = re.sub(r'\\dirname{(?P<dir>[^}]+?)}',
+                      r'<filename class="directory">\g<dir></filename>', line)
+        line = re.sub(r'\\filename{(?P<file>[^}]+?)}',
+                      r'<filename>\g<file></filename>', line)
+        line = re.sub(r'\\tildefile{(?P<file>[^}]+)}',
+                      r'<filename role="home"> /\g<file></filename>', line)
+        line = re.sub(r'\\sfilename{(?P<file>[^}]+)}',
+                      r'<filename role="special">\g<file></filename>', line)
+        line = re.sub(r'\\sdirname{(?P<dir>[^}]+)}',
+                      r'<filename role="special" class="directory">\g<dir></filename>', line)
+        line = re.sub(r'\\interaction{(?P<id>[^}]+)}',
+                      r'<!-- &interaction.\g<id>; -->', line)
+        line = re.sub(r'\\excode{(?P<id>[^}]+)}',
+                      r'<!-- &example.\g<id>; -->', line)
+        line = re.sub(r'\\pymod{(?P<mod>[^}]+)}',
+                      r'<literal role="py-mod">\g<mod></literal>', line)
+        line = re.sub(r'\\pymodclass{(?P<mod>[^}]+)}{(?P<class>[^}]+)}',
+                      r'<literal url="py-mod-\g<mod>">\g<class></ulink>', line)
+        line = re.sub(r'\\url{(?P<url>[^}]+)}',
+                      r'<ulink url="\g<url>">\g<url></ulink>', line)
+        line = re.sub(r'\\href{(?P<url>[^}]+)}{(?P<text>[^}]+)}',
+                      r'<ulink url="\g<url>">\g<text></ulink>', line)
+        line = re.sub(r'\\command{(?P<cmd>[^}]+)}',
+                      r'<command>\g<cmd></command>', line)
+        line = re.sub(r'\\option{(?P<opt>[^}]+)}',
+                      r'<option>\g<opt></option>', line)
+        line = re.sub(r'\\ref{(?P<id>[^}]+)}', r'<xref id="\g<id>"/>', line)
+        line = re.sub(r'\\emph{(?P<txt>[^}]+)}',
+                      r'<emphasis>\g<txt></emphasis>', line)
+        line = re.sub(r'\\texttt{(?P<txt>[^}]+)}',
+                      r'<literal>\g<txt></literal>', line)
+        line = re.sub(r'\\textbf{(?P<txt>[^}]+)}',
+                      r'<emphasis role="bold">\g<txt></emphasis>', line)
+        line = re.sub(r'\\hook{(?P<name>[^}]+)}',
+                      r'<literal role="hook">\g<name></literal>', line)
+        line = re.sub(r'\\tplfilter{(?P<name>[^}]+)}',
+                      r'<literal role="template-filter">\g<name></literal>', line)
+        line = re.sub(r'\\tplkword{(?P<name>[^}]+)}',
+                      r'<literal role="template-keyword">\g<name></literal>', line)
+        line = re.sub(r'\\tplkwfilt{(?P<tpl>[^}]+)}{(?P<name>[^}]+)}',
+                      r'<literal role="template-kw-filt-\g<tpl>">\g<name></literal>', line)
+        line = re.sub(r'\\[vV]erb(.)(?P<txt>[^\1]+?)\1',
+                      r'<literal>\g<txt></literal>', line)
+        line = re.sub(r'\\package{(?P<name>[^}]+)}',
+                      r'<literal role="package">\g<name></literal>', line)
+        line = re.sub(r'\\hgcmdargs{(?P<cmd>[^}]+)}{(?P<args>[^}]+)}',
+                      r'<command role="hg-cmd">hg \g<cmd> \g<args></command>',
+                      line)
+        line = re.sub(r'\\cmdargs{(?P<cmd>[^}]+)}{(?P<args>[^}]+)}',
+                      r'<command>\g<cmd> \g<args></command>',
+                      line)
+        m = re.match(r'\\(chapter|section|subsection|subsubsection){(.*)}', line)
+        if m:
+            kind, content = m.groups()
+            sec = sections[kind]
+            while stack and stack[-1] >= sec:
+                close = stack.pop()
+                print >> ofp, '</%s>' % close
+            stack.append(sec)
+            print >> ofp, '<%s>\n<title>%s</title>' % (sec, content)
+        else:
+            m = re.match(r'\s*\\(begin|end){(?P<sect>[^}]+)}', line)
+            if m:
+                if not para:
+                    print >> ofp, '</para>'
+                    if inlist:
+                        ofp.write('</listitem>')
+                    para = True
+                state, env = m.groups()
+                env = envs[env]
+                if state == 'begin':
+                    ofp.write('<')
+                    if env == 'itemizedlist':
+                        inlist = True
+                else:
+                    ofp.write('</')
+                    if env == 'itemizedlist':
+                        inlist = False
+                print >> ofp, env + '>'
+            else:
+                if line.startswith('\\item '):
+                    para = True
+                    line = line[6:]
+                if line and para:
+                    if inlist:
+                        ofp.write('<listitem>')
+                    ofp.write('<para>')
+                    para = False
+                if not line and not para:
+                    print >> ofp, '</para>'
+                    if inlist:
+                        ofp.write('</listitem>')
+                    para = True
+                print >> ofp, line
+    while stack:
+        print >> ofp, '</%s>' % stack.pop()
+    ofp.write('\n'.join(['<!--',
+                         'local variables: ',
+                         'sgml-parent-document: ("00book.xml" "book" "chapter")',
+                         'end:',
+                         '-->']))
+
+
+if __name__ == '__main__':
+    for name in sys.argv[1:]:
+        if not name.endswith('.tex'):
+            continue
+        newname = name[:-3] + 'xml'
+        ofp = StringIO.StringIO()
+        process(open(name), ofp)
+        s = ofp.getvalue()
+        s = re.sub('\n+</para>', '</para>', s, re.M)
+        open(newname, 'w').write(s)