Commits

Josef Sipek committed fa8bafe Merge

Merge with upstream

Comments (0)

Files changed (17)

-% 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{enumerate}
-\usepackage{fullpage}
-\usepackage{makeidx}
-\usepackage{ifpdf}
-\usepackage{graphicx}
-\usepackage{pslatex}
-\usepackage{fancyvrb}
-% leave hyperref until last
-\usepackage[colorlinks=true,bookmarks=true]{hyperref}
-
-\include{99defs}
-
-\title{Distributed revision control with Mercurial}
-\author{Bryan O'Sullivan}
-\date{Copyright \copyright\ 2006 Bryan O'Sullivan.\\
-  This material may be distributed only subject to the terms and
-  conditions set forth in version 1.0 of the Open Publication License.
-  Please refer to Appendix~\ref{cha:opl} for the license text.\\
-  This book was prepared from revision \input{build_id}.}
-
-\makeindex
-
-\begin{document}
-
-\maketitle
-
-\addcontentsline{toc}{chapter}{Contents}
-\pagenumbering{roman}
-\tableofcontents
-\listoffigures
-%\listoftables
-
-\pagenumbering{arabic}
-
-\include{preface}
-\include{intro}
-\include{concepts}
-\include{hook}
-\include{mq}
-
-\appendix
-\include{license}
-\addcontentsline{toc}{chapter}{Bibliography}
-\bibliographystyle{alpha}
-\bibliography{99book}
-
-\printindex
-
-\end{document}
-
-%%% Local Variables: 
-%%% mode: latex
-%%% TeX-master: t
-%%% End: 
+% 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{enumerate}
+\usepackage{fullpage}
+\usepackage{makeidx}
+\usepackage{ifpdf}
+\usepackage{graphicx}
+\usepackage{pslatex}
+\usepackage{fancyvrb}
+% leave hyperref until last
+\usepackage[colorlinks=true,bookmarks=true]{hyperref}
+
+\include{99defs}
+
+\title{Distributed revision control with Mercurial}
+\author{Bryan O'Sullivan}
+\date{Copyright \copyright\ 2006 Bryan O'Sullivan.\\
+  This material may be distributed only subject to the terms and
+  conditions set forth in version 1.0 of the Open Publication License.
+  Please refer to Appendix~\ref{cha:opl} for the license text.\\
+  This book was prepared from revision \input{build_id}.}
+
+\makeindex
+
+\begin{document}
+
+\maketitle
+
+\addcontentsline{toc}{chapter}{Contents}
+\pagenumbering{roman}
+\tableofcontents
+\listoffigures
+%\listoftables
+
+\pagenumbering{arabic}
+
+\include{preface}
+\include{intro}
+\include{concepts}
+\include{daily}
+\include{hook}
+\include{mq}
+
+\appendix
+\include{license}
+\addcontentsline{toc}{chapter}{Bibliography}
+\bibliographystyle{alpha}
+\bibliography{99book}
+
+\printindex
+
+\end{document}
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: t
+%%% End: 
-\newcommand{\bug}[1]{\index{Mercurial issue!no.~#1}\href{http://www.selenic.com/mercurial/bts/issue#1}{Mercurial issue no.~#1}}
+% Bug ID.
+\newcommand{\bug}[1]{\index{Mercurial bug
+    database!\href{http://www.selenic.com/mercurial/bts/issue#1}{bug
+      ~#1}}\href{http://www.selenic.com/mercurial/bts/issue#1}{Mercurial
+    bug 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} file}\texttt{#1}}
+
+% Directory name, with index entry.
 \newcommand{\sdirname}[1]{\index{\texttt{#1} directory}\texttt{#1}}
+
+% Mercurial extension.
 \newcommand{\hgext}[1]{\index{\texttt{#1} extension}\texttt{#1}}
+
+% Mercurial command.
 \newcommand{\hgcmd}[1]{\index{\texttt{#1} command}``\texttt{hg #1}''}
+
+% Mercurial command, with arguments.
+\newcommand{\hgcmdargs}[2]{\index{\texttt{#1} command}``\texttt{hg #1 #2}''}
+
+% Shell/system command.
 \newcommand{\command}[1]{\index{\texttt{#1} command}\texttt{#1}}
+
+% Shell/system command, with arguments.
 \newcommand{\cmdargs}[2]{\index{\texttt{#1} command}``\texttt{#1 #2}''}
-\newcommand{\hgcmdargs}[2]{\index{\texttt{#1} command}``\texttt{hg #1 #2}''}
+
+% Mercurial command option.
 \newcommand{\hgopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}}
+
+% Mercurial global option.
+\newcommand{\hggopt}[1]{\index{global options!\texttt{#1} option}\texttt{#1}}
+
+% Shell/system command option.
 \newcommand{\cmdopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}}
+
+% Command option.
 \newcommand{\option}[1]{\texttt{#1}}
+
+% Software package.
 \newcommand{\package}[1]{\index{\texttt{#1} package}\texttt{#1}}
+
+% Section name from a hgrc file.
 \newcommand{\rcsection}[1]{\index{\texttt{hgrc} file!\texttt{#1} section}\texttt{[#1]}}
+
+% Named item in a hgrc file section.
 \newcommand{\rcitem}[2]{\index{\texttt{hgrc} file!\texttt{#1}
     section!\texttt{#2} entry}\texttt{#1.#2}}
+
+% hgrc file.
 \newcommand{\hgrc}{\index{\texttt{hgrc} file}\texttt{hgrc}}
+
+% Hook name.
 \newcommand{\hook}[1]{\index{\texttt{#1} hook}\index{hooks!\texttt{#1}}\texttt{#1}}
+
+% Environment variable.
 \newcommand{\envar}[1]{\index{\texttt{#1} environment
     variable}\index{environment variables!\texttt{#1}}\texttt{#1}}
 
+% Python module.
+\newcommand{\pymod}[1]{\index{\texttt{#1} module}\texttt{#1}}
+
+% Python class in a module.
+\newcommand{\pymodclass}[2]{\index{\texttt{#1} module!\texttt{#2}
+    class}\texttt{#1.#2}}
+
+% Note: blah blah.
 \newsavebox{\notebox}
 \newenvironment{note}%
   {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Note:}\space}%
   {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Caution:}\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.out}}
 
+% Graphics inclusion.
 \ifpdf
-  \newcommand{\grafix}[1]{\includegraphics[scale=0.2]{#1_pdf.png}}
+  \newcommand{\grafix}[1]{\includegraphics{#1}}
 \else
   \newcommand{\grafix}[1]{\includegraphics{#1.png}}
 \fi
-# This makefile requires GNU make.
-
-hg_id := $(shell hg parents --template '{node|short}\n' | head -1)
-
-sources := \
-	00book.tex \
-	99book.bib \
-	99defs.tex \
-	build_id.tex \
-	concepts.tex \
-	hook.tex \
-	intro.tex \
-	mq.tex \
-	preface.tex
-
-image-sources := \
-	mq-stack.svg
-
-example-sources := \
-	examples/run-example \
-	examples/hook.simple \
-	examples/concepts \
-	examples/mq.qinit-help \
-	examples/mq.diff \
-	examples/mq.tarball \
-	examples/mq.tools \
-	examples/mq.tutorial
-
-latex-options = \
-	-interaction batchmode \
-	-output-directory $(dir $(1)) \
-	-jobname $(basename $(notdir $(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) $(image-sources:%.svg=%.pdf) examples
-	$(call pdf)
-
-html: html/onepage/hgbook.html html/split/hgbook.html
-
-# 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,
-# so instead I mangle the script itself.
-
-define htlatex
-	mkdir -p $(dir $(1))
-	head -2 $(shell which htlatex) > $(dir $(1))/htlatex.book
-	cp 99book.bib $(dir $@)
-	echo '(cd $(dir $@) && bibtex $(basename $(notdir $@)))' >> $(dir $(1))/htlatex.book
-	echo '(cd $(dir $@) && makeindex $(basename $(notdir $@)))' >> $(dir $(1))/htlatex.book
-	head -3 $(shell which htlatex) >> $(dir $(1))/htlatex.book
-	echo 'echo status $$$$' >>  $(dir $(1))/htlatex.book
-	chmod 755 $(dir $(1))/htlatex.book
-	TEXINPUTS=$(dir $(2)): $(dir $(1))/htlatex.book $(2) "xhtml,html4-uni,$(3)" " -cunihtf -utf8" "" "$(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)))
-	perl -pi -e 's/&#x00([0-7][0-9a-f]);/chr(hex($$1))/egi' $(dir $(1))/*.html
-endef
-
-html/onepage/hgbook.html: $(sources) $(image-sources:%.svg=%.png) examples
-	$(call htlatex,$@,$<)
-	cp $(image-sources:%.svg=%.png) $(dir $@)
-
-html/split/hgbook.html: $(sources) $(image-sources:%.svg=%.png) examples
-	$(call htlatex,$@,$<,2)
-	cp $(image-sources:%.svg=%.png) $(dir $@)
-
-beta: beta/pdf/hgbook.pdf beta/html/onepage/hgbook.html beta/html/split/hgbook.html
-
-beta/%.tex: %.tex
-	./fblinks $(hg_id) $(dir $@) $<
-
-beta/pdf/hgbook.pdf: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.pdf) examples fblinks
-	$(call pdf)
-
-beta/html/onepage/hgbook.html: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.png) examples
-	$(call htlatex,$@,$<)
-	cp $(image-sources:%.svg=%.png) $(dir $@)
-
-beta/html/split/hgbook.html: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.png) examples
-	$(call htlatex,$@,$<,2)
-	cp $(image-sources:%.svg=%.png) $(dir $@)
-
-# Produce 90dpi PNGs for the web.
-
-%.png: %.svg
-	inkscape -D -e $@ $<
-
-# Produce eps & pdf for the pdf
-
-%.pdf: %.eps
-	epstopdf $<
-
-%.eps: %.svg
-	inkscape -E $@ $<
-
-examples: examples/.run
-
-examples/.run: $(example-sources)
-	cd examples && ./run-example
-
-build_id.tex: $(wildcard ../.hg/00changelog.[id])
-	echo -n $(hg_id) > build_id.tex
-
-clean:
-	rm -rf beta html pdf *.eps *.pdf *.png *.aux *.dvi *.log *.out \
-		examples/*.out examples/.run build_id.tex
+# This makefile requires GNU make.
+
+hg_id := $(shell hg parents --template '{node|short}\n' | head -1)
+
+sources := \
+	00book.tex \
+	99book.bib \
+	99defs.tex \
+	build_id.tex \
+	concepts.tex \
+	daily.tex \
+	hook.tex \
+	intro.tex \
+	mq.tex \
+	preface.tex
+
+image-sources := \
+	mq-stack.svg
+
+example-sources := \
+	examples/daily.files \
+	examples/hook.simple \
+	examples/hook.ws \
+	examples/concepts \
+	examples/mq.qinit-help \
+	examples/mq.dodiff \
+	examples/mq.tarball \
+	examples/mq.tools \
+	examples/mq.tutorial
+
+latex-options = \
+	-interaction batchmode \
+	-output-directory $(dir $(1)) \
+	-jobname $(basename $(notdir $(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) $(image-sources:%.svg=%.pdf) examples
+	$(call pdf)
+
+html: html/onepage/hgbook.html html/split/hgbook.html
+
+# 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,
+# so instead I mangle the script itself.
+
+define htlatex
+	mkdir -p $(dir $(1))
+	head -2 $(shell which htlatex) > $(dir $(1))/htlatex.book
+	cp 99book.bib $(dir $@)
+	echo '(cd $(dir $@) && bibtex $(basename $(notdir $@)))' >> $(dir $(1))/htlatex.book
+	echo '(cd $(dir $@) && makeindex $(basename $(notdir $@)))' >> $(dir $(1))/htlatex.book
+	head -3 $(shell which htlatex) >> $(dir $(1))/htlatex.book
+	echo 'echo status $$$$' >>  $(dir $(1))/htlatex.book
+	chmod 755 $(dir $(1))/htlatex.book
+	TEXINPUTS=$(dir $(2)): $(dir $(1))/htlatex.book $(2) "xhtml,html4-uni,$(3)" " -cunihtf -utf8" "" "$(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)))
+	perl -pi -e 's/&#x00([0-7][0-9a-f]);/chr(hex($$1))/egi' $(dir $(1))/*.html
+endef
+
+html/onepage/hgbook.html: $(sources) $(image-sources:%.svg=%.png) examples
+	$(call htlatex,$@,$<)
+	cp $(image-sources:%.svg=%.png) $(dir $@)
+
+html/split/hgbook.html: $(sources) $(image-sources:%.svg=%.png) examples
+	$(call htlatex,$@,$<,2)
+	cp $(image-sources:%.svg=%.png) $(dir $@)
+
+beta: beta/pdf/hgbook.pdf beta/html/onepage/hgbook.html beta/html/split/hgbook.html
+
+beta/%.tex: %.tex
+	./fblinks $(hg_id) $(dir $@) $<
+
+beta/pdf/hgbook.pdf: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.pdf) examples fblinks
+	$(call pdf)
+
+beta/html/onepage/hgbook.html: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.png) examples
+	$(call htlatex,$@,$<)
+	cp $(image-sources:%.svg=%.png) $(dir $@)
+
+beta/html/split/hgbook.html: $(sources:%.tex=beta/%.tex) $(image-sources:%.svg=%.png) examples
+	$(call htlatex,$@,$<,2)
+	cp $(image-sources:%.svg=%.png) $(dir $@)
+
+# Produce 90dpi PNGs for the web.
+
+%.png: %.svg
+	inkscape -D -e $@ $<
+
+# Produce eps & pdf for the pdf
+
+%.pdf: %.eps
+	epstopdf $<
+
+%.eps: %.svg
+	inkscape -E $@ $<
+
+examples: examples/.run
+
+examples/.run: $(example-sources:%=%.run)
+	touch examples/.run
+
+examples/%.run: examples/% examples/run-example
+	cd examples && ./run-example $(notdir $<)
+
+build_id.tex: $(wildcard ../.hg/00changelog.[id])
+	echo -n $(hg_id) > build_id.tex
+
+clean:
+	rm -rf beta html pdf *.eps *.pdf *.png *.aux *.dvi *.log *.out \
+		examples/*.{out,run} examples/.run build_id.tex
+\chapter{Mercurial in daily use}
+\label{chap:daily}
+
+\section{Routine file management tasks}
+
+\subsection{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}''.
+
+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 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.)
+
+\begin{figure}[ht]
+  \interaction{daily.files.add}
+  \caption{Telling Mercurial to track a file}
+  \label{ex:daily:add}
+\end{figure}
+
+Once you add a file, Mercurial will track every change you make to it
+until you either remove or rename the file.
+
+\subsubsection{Aside: Mercurial tracks files, not directories}
+
+Mercurial does not track directory information.  Instead, it tracks
+the path to a file, and creates directories along a path when it needs
+to.  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.
+
+\subsection{How to stop tracking a file}
+
+If 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}''.
+
+You might wonder why Mercurial requires you to explicitly tell it that
+you are deleting a file.  Earlier during the development of Mercurial,
+you could simply delete a file however you pleased; Mercurial would
+notice automatically when you next ran a \hgcmd{commit}, and stop
+tracking the file.  In practice, this made it too easy to accidentally
+stop Mercurial from tracking a file.
+
+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}.
+Other Mercurial commands will not do anything with missing files.
+
+If you have a missing file in your repository, you can run
+\hgcmdargs{remove}{\hgopt{remove}{--after}} later on, to tell
+Mercurial that you deleted the file.  If you deleted the file by
+accident, use \hgcmdargs{revert}{\emph{filename}} to restore the file
+to its last committed state.
+
+\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.  The
+\hgcmd{commit} command also provides a \hgopt{commit}{-A} option that
+performs an add-and-remove, immediately followed by a commit.  This
+lets you replace the following command sequence:
+\begin{codesample2}
+  hg add
+  hg remove --after
+  hg commit
+\end{codesample2}
+with a single command, \hgcmdargs{commit}{\hgopt{commit}{-A}}.
+
+\subsection{Renaming files}
+
+To rename a file that is tracked by Mercurial, use the \hgcmd{rename}
+command.  This command behaves similarly to the Unix \command{mv}
+command.  If the last argument is a directory, it moves all prior
+arguments into that directory.  Otherwise, it renames a single file or
+directory to the name given in the last argument.
+
+As with \hgcmd{remove}, you can tell Mercurial about a rename after
+the fact using the \hgopt{remove}{--after} option.
+
+The na\"{i}ve way to ``rename'' a file is simply to rename the file
+yourself, \hgcmd{remove} the old name, and \hgcmd{add} the new name.
+However, if you do this, Mercurial will not know that there was any
+relationship between the files in question, and it will not be able to
+merge
+
+\subsection{Copying files}
+
+You can copy a file in two ways using mercurial.  If you simply copy a
+file and then \hgcmd{add} the new file, Mercurial will not know that
+there was any relationship between the two files.  However, if you 
+
+%%% Local Variables: 
+%%% mode: latex
+%%% TeX-master: "00book"
+%%% End: 

en/examples/daily.files

+#!/bin/bash
+
+#$ name: add
+
+hg init a
+cd a
+echo content > filename
+mkdir subdir
+echo something > subdir/otherfile
+hg status
+
+#$ name: hidden
+
+mkdir empty
+touch empty/.hidden
+hg add empty/.hidden
+hg commit -m 'Manage an empty-looking directory'
+ls empty
+cd ..
+hg clone a b
+ls b
+ls b/empty

en/examples/data/check_whitespace.py

+#!/usr/bin/python
+
+import os, re, sys
+
+count = 0
+
+for line in os.popen('hg export tip'):
+    # remember the name of the file that this diff affects
+    m = re.match(r'^--- [^/]/([^\t])', line)
+    if m: 
+	filename = m.group(1)
+	continue
+    # remember the line number
+    m = re.match(r'^@@ -(\d+),')
+    if m:
+        linenum = m.group(1)
+        continue
+    linenum += 1
+    # check for an added line with trailing whitespace
+    m = re.match(r'^\+.*\s$', line)
+    if m:
+	print >> sys.stderr, ('%s:%d: trailing whitespace introduced' %
+                              (filename, linenum))
+        count += 1
+
+if count:
+    # 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(count)

en/examples/hook.simple

+#!/bin/bash
+
 #$ name: init
 
 hg init hook-test

en/examples/hook.ws

+#!/bin/bash
+
+cp $EXAMPLE_DIR/data/check_whitespace.py .
+
+hg init a
+cd a
+echo '[hooks]' > .hg/hgrc
+echo "pretxncommit.whitespace = hg export tip | (! grep -qP '^\\+.*[ \\t]$')" >> .hg/hgrc
+
+#$ name: simple
+
+cat .hg/hgrc
+echo 'a ' > a
+hg commit -A -m 'test with trailing whitespace'

en/examples/mq.diff

-#$ name: diff
-
-echo 'this is my first line' > oldfile
-echo 'my first line is here' > newfile
-
-diff -u oldfile newfile > tiny.patch
-
-cat tiny.patch
-
-patch < tiny.patch
-
-cat newfile

en/examples/mq.dodiff

+#!/bin/bash
+
+#$ name: diff
+
+echo 'this is my first line' > oldfile
+echo 'my first line is here' > newfile
+
+diff -u oldfile newfile > tiny.patch
+
+cat tiny.patch
+
+patch < tiny.patch
+
+cat newfile

en/examples/mq.qinit-help

+#!/bin/bash
+
 echo '[extensions]' >> $HGRC
 echo 'hgext.mq =' >> $HGRC
 

en/examples/mq.tarball

+#!/bin/bash
+
 cp $EXAMPLE_DIR/data/netplug-*.tar.bz2 .
 ln -s /bin/true download
 

en/examples/mq.tools

+#!/bin/bash
+
 cp $EXAMPLE_DIR/data/remove-redundant-null-checks.patch .
 
 #$ name: tools

en/examples/mq.tutorial

+#!/bin/bash
+
 echo '[extensions]' >> $HGRC
 echo 'hgext.mq =' >> $HGRC
 

en/examples/run-example

 import re
 import shutil
 import signal
+import stat
 import sys
 import tempfile
 import time
                     # then its output
                     ofp.write(tex_escape(output))
             self.status('\n')
+            open(self.name + '.run', 'w')
         finally:
             try:
                 output = self.sendreceive('exit\n')
     for name in os.listdir(path):
         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)
-        if os.path.isfile(pathname):
+        st = os.lstat(pathname)
+        if stat.S_ISREG(st.st_mode) and st.st_mode & 0111:
             example(pathname).run()
     print >> open(os.path.join(path, '.run'), 'w'), time.asctime()
 
 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{Using hooks with shared access to a repository}
+
+If you want to use hooks to so some automated work in a repository
+that a number of people have ahred 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 te 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 in which a
+reader can see the metadata for changesets that are, strictly
+speaking, not yet permanent.  The longer the hook runs, the bigger the
+window.
+
+A good use for the \hook{pretxnchangegroup} hook would be to
+automatically build and test incoming changes before they are accepted
+into the repository, so that you can 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; someone can pull untested changes.
+
+The safest answer to this challenge is to set up such a ``gatekeeper''
+repository as \emph{unidirectional}.  It can take changes pushed in
+from the outside, but nobody can 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.
+
 \section{A short tutorial on using hooks}
 \label{sec:hook:simple}
 
 comment contains a bug ID.  If it does, the commit can complete.  If
 not, the commit is rolled back.
 
-\section{Choosing how to write a hook}
-\label{sec:hook:impl}
+\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 called within the Mercurial
+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
 performance (probably the majority of hooks), a shell script is
 perfectly fine.
 
-\section{Hook parameters}
+\subsection{Hook parameters}
 \label{sec:hook:param}
 
 Mercurial calls each hook with a set of well-defined parameters.  In
 environment variable.
 
 Whether your hook is written in Python or as a shell script, the
-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'')
+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} Python, 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{Enforcing coding guidelines in your own repository}
+
+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 tend to 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.
+
+\section{Hook reference}
+\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 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.  If
+it were to do so, it would probably cause calls to the Mercurial API,
+or operations after the hook finishes, 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.
+
+\subsection{External hook execution}
+
+An external hook is passed to the user's shell for execution, so
+features of that shell, such as variable substitution and command
+redirection, are available.  The hook is run in the root directory of
+the repository.
+
+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 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{The \hook{changegroup} hook}
+\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}.
+\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{The \hook{commit} hook}
+\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{The \hook{incoming} hook}
+\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 othher
+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.
+\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{The \hook{outgoing} hook}
+\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.
+  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.
+\end{itemize}
+
+See also: \hook{preoutgoing} (section~\ref{sec:hook:preoutgoing})
+
+\subsection{The \hook{prechangegroup} hook}
+\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 to ``freeze'' a server-hosted branch
+temporarily or permanently.
+
+This hook is not passed any parameters.
+
+See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}),
+\hook{incoming} (section~\ref{sec:hook:incoming}), ,
+\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup})
+
+\subsection{The \hook{precommit} hook}
+\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{The \hook{preoutgoing} hook}
+\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 the
+  documentation for the \texttt{source} parameter to the
+  \hook{outgoing} hook, in section~\ref{sec:hook:outgoing}, for
+  possible values of this parameter..
+\end{itemize}
+
+See also: \hook{outgoing} (section~\ref{sec:hook:outgoing})
+
+\subsection{The \hook{pretag} hook}
+\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/tags}) 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{The \hook{pretxnchangegroup} hook}
+\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 are the same as for the \hook{changegroup}
+hook; see section~\ref{sec:hook:changegroup} for details.
+
+See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}),
+\hook{incoming} (section~\ref{sec:hook:incoming}),
+\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup})
+
+\subsection{The \hook{pretxncommit} hook}
+\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 are the same as for the \hook{commit} hook;
+see section~\ref{sec:hook:commit} for details.
+
+See also: \hook{precommit} (section~\ref{sec:hook:precommit})
+
+\subsection{The \hook{preupdate} hook}
+\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{The \hook{tag} hook}
+\label{sec:hook:tag}
+
+This hook is run after a tag has been created.
+
+Parameters to this hook are the same as for the \hook{pretag} hook;
+see section~\ref{sec:hook:pretag} for details.
+
+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{The \hook{update} hook}
+\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
 these commands in action.
 
 \begin{figure}[ht]
-  \interaction{mq.diff.diff}
+  \interaction{mq.dodiff.diff}
   \caption{Simple uses of the \command{diff} and \command{patch} commands}
   \label{ex:mq:diff}
 \end{figure}
 
 \begin{figure}[ht]
   \centering
-  \includegraphics{mq-stack}
+  \grafix{mq-stack}
   \caption{Applied and unapplied patches in the MQ patch stack}
   \label{fig:mq:stack}
 \end{figure}