hgbook

changeset 921:547d3aa25ef0

Initial copy from the english version, added package for french input.
author Romain PELISSE <romain.pelisse@atosorigin.com>
date Thu Feb 05 12:37:03 2009 +0100 (2009-02-05)
parents 51b5d56744c5
children f5d009f9e8e0
files fr/00book.tex fr/99book.bib fr/99defs.tex fr/Makefile fr/bookhtml.cfg fr/branch.tex fr/cmdref.py fr/cmdref.tex fr/collab.tex fr/concepts.tex fr/daily.tex fr/examples/backout fr/examples/bisect fr/examples/branch-named fr/examples/branch-repo fr/examples/branching fr/examples/cmdref fr/examples/daily.copy fr/examples/daily.files fr/examples/daily.rename fr/examples/daily.revert fr/examples/data/check_whitespace.py fr/examples/data/netplug-1.2.5.tar.bz2 fr/examples/data/netplug-1.2.8.tar.bz2 fr/examples/data/remove-redundant-null-checks.patch fr/examples/extdiff fr/examples/filenames fr/examples/hook.msglen fr/examples/hook.simple fr/examples/hook.ws fr/examples/issue29 fr/examples/mq.dodiff fr/examples/mq.guards fr/examples/mq.id fr/examples/mq.qinit-help fr/examples/mq.tarball fr/examples/mq.tools fr/examples/mq.tutorial fr/examples/rename.divergent fr/examples/rollback fr/examples/run-example fr/examples/svn-long.txt fr/examples/svn-short.txt fr/examples/svn.style fr/examples/svn.template fr/examples/tag fr/examples/template.simple fr/examples/template.svnstyle fr/examples/tour fr/examples/tour-merge-conflict fr/fblinks fr/feature-branches.dot fr/filelog.svg fr/filenames.tex fr/fixhtml.py fr/fixsvg fr/hgbook.css fr/hgext.tex fr/hook.tex fr/htlatex.book fr/intro.tex fr/kdiff3.png fr/license.tex fr/metadata.svg fr/mq-collab.tex fr/mq-ref.tex fr/mq-stack.svg fr/mq.tex fr/note.png fr/preface.tex fr/revlog.svg fr/snapshot.svg fr/srcinstall.tex fr/template.tex fr/tour-basic.tex fr/tour-history.svg fr/tour-merge-conflict.svg fr/tour-merge-merge.svg fr/tour-merge-pull.svg fr/tour-merge-sep-repos.svg fr/tour-merge.tex fr/undo-manual-merge.dot fr/undo-manual.dot fr/undo-non-tip.dot fr/undo-simple.dot fr/undo.tex fr/wdir-after-commit.svg fr/wdir-branch.svg fr/wdir-merge.svg fr/wdir-pre-branch.svg fr/wdir.svg
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/fr/00book.tex	Thu Feb 05 12:37:03 2009 +0100
     1.3 @@ -0,0 +1,80 @@
     1.4 +% The use of oneside here is a temporary hack; \marginpar entries
     1.5 +% don't show up on odd pages of PDF output without it.  Sigh.
     1.6 +\documentclass[oneside]{book}
     1.7 +\usepackage{enumerate}
     1.8 +\usepackage{fullpage}
     1.9 +\usepackage{makeidx}
    1.10 +\usepackage{ifpdf}
    1.11 +\usepackage{graphicx}
    1.12 +\usepackage{pslatex}
    1.13 +\usepackage{fancyvrb}
    1.14 +% adding package specific to the french version
    1.15 +\usepackage[french]{babel}
    1.16 +\usepackage[utf8]{inputenc}
    1.17 +% leave hyperref until last
    1.18 +\usepackage[colorlinks=true,bookmarks=true,pdftitle={Distributed
    1.19 +  revision control with Mercurial},pdfsubject={Revision
    1.20 +  control},pdfkeywords={Mercurial, Revision control, Distributed
    1.21 +  revision control},pdfauthor={Bryan O'Sullivan}]{hyperref}
    1.22 +
    1.23 +\include{99defs}
    1.24 +
    1.25 +\title{Gestion de source distribué avec Mercurial} \author{Bryan
    1.26 +  O'Sullivan}
    1.27 +\date{Copyright \copyright\ 2006, 2007 Bryan O'Sullivan.\\
    1.28 +  Ce document peut être librement distribué selon les termes et 
    1.29 +  les conditions décrites dans la version 1.0 de la licence Open Publication.
    1.30 +  La licence est en annexe~\ref{chap:opl} de ce document.\\
    1.31 +  
    1.32 +  Cette traduction a été généré depuis 
    1.33 +  \href{http://hg.serpentine.com/mercurial/book/}{rev~\input{build_id}}
    1.34 +  avec \href{http://www.selenic.com/hg/}{rev~\input{hg_id}} of Mercurial.}
    1.35 +
    1.36 +\makeindex
    1.37 +
    1.38 +\begin{document}
    1.39 +
    1.40 +\maketitle
    1.41 +
    1.42 +\addcontentsline{toc}{chapter}{Contents}
    1.43 +\pagenumbering{roman}
    1.44 +\tableofcontents
    1.45 +\listoffigures
    1.46 +%\listoftables
    1.47 +
    1.48 +\pagenumbering{arabic}
    1.49 +
    1.50 +\include{preface}
    1.51 +\include{intro}
    1.52 +\include{tour-basic}
    1.53 +\include{tour-merge}
    1.54 +\include{concepts}
    1.55 +\include{daily}
    1.56 +\include{collab}
    1.57 +\include{filenames}
    1.58 +\include{branch}
    1.59 +\include{undo}
    1.60 +\include{hook}
    1.61 +\include{template}
    1.62 +\include{mq}
    1.63 +\include{mq-collab}
    1.64 +\include{hgext}
    1.65 +
    1.66 +\appendix
    1.67 +\include{cmdref}
    1.68 +\include{mq-ref}
    1.69 +\include{srcinstall}
    1.70 +\include{license}
    1.71 +\addcontentsline{toc}{chapter}{Bibliography}
    1.72 +\bibliographystyle{alpha}
    1.73 +\bibliography{99book}
    1.74 +
    1.75 +\addcontentsline{toc}{chapter}{Index}
    1.76 +\printindex
    1.77 +
    1.78 +\end{document}
    1.79 +
    1.80 +%%% Local Variables: 
    1.81 +%%% mode: latex
    1.82 +%%% TeX-master: t
    1.83 +%%% End: 
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/fr/99book.bib	Thu Feb 05 12:37:03 2009 +0100
     2.3 @@ -0,0 +1,76 @@
     2.4 +@Unpublished{gruenbacher:2005,
     2.5 +  author = 	 {Andreas Gruenbacher},
     2.6 +  title = 	 {How To Survive With Many Patches (Introduction to \texttt{quilt})},
     2.7 +  year = 	 {2005},
     2.8 +  month = 	 {June},
     2.9 +  note =         {\url{http://www.suse.de/~agruen/quilt.pdf}},
    2.10 +}
    2.11 +
    2.12 +@InProceedings{web:europython,
    2.13 +  author = 	 {Bryan O'Sullivan},
    2.14 +  title = 	 {Achieving High Performance in Mercurial},
    2.15 +  booktitle = 	 {EuroPython Conference},
    2.16 +  year = 	 {2006},
    2.17 +  month = 	 {July},
    2.18 +  note = 	 {\url{XXX}},
    2.19 +}
    2.20 +
    2.21 +@Misc{web:diffstat,
    2.22 +  author = 	 {Thomas Dickey},
    2.23 +  title = 	 {\texttt{diffstat}--make a histogram of \texttt{diff} output},
    2.24 +  note = 	 {\url{http://dickey.his.com/diffstat/diffstat.html}},
    2.25 +}
    2.26 +
    2.27 +@Misc{web:quilt,
    2.28 +  author = 	 {Andreas Gruenbacher, Martin Quinson, Jean Delvare},
    2.29 +  title = 	 {Patchwork Quilt},
    2.30 +  note = 	 {\url{http://savannah.nongnu.org/projects/quilt}},
    2.31 +}
    2.32 +
    2.33 +@Misc{web:patchutils,
    2.34 +  author = 	 {Tim Waugh},
    2.35 +  title = 	 {\texttt{patchutils}--programs that operate on patch files},
    2.36 +  note = 	 {\url{http://cyberelk.net/tim/patchutils/}},
    2.37 +}
    2.38 +
    2.39 +@Misc{web:mpatch,
    2.40 +  author = 	 {Chris Mason},
    2.41 +  title = 	 {\texttt{mpatch}--help solve patch rejects},
    2.42 +  note = 	 {\url{http://oss.oracle.com/~mason/mpatch/}},
    2.43 +}
    2.44 +
    2.45 +@Misc{web:wiggle,
    2.46 +  author = 	 {Neil Brown},
    2.47 +  title = 	 {\texttt{wiggle}--apply conflicting patches},
    2.48 +  note = 	 {\url{http://cgi.cse.unsw.edu.au/~neilb/source/wiggle/}},
    2.49 +}
    2.50 +
    2.51 +@Misc{web:mysql-python,
    2.52 +  author =	 {Andy Dustman},
    2.53 +  title =	 {MySQL for Python},
    2.54 +  note =	 {\url{http://sourceforge.net/projects/mysql-python}},
    2.55 +}
    2.56 +
    2.57 +@Misc{web:changelog,
    2.58 +  author =	 {Richard Stallman, GNU Project volunteers},
    2.59 +  title =	 {GNU Coding Standards---Change Logs},
    2.60 +  note =	 {\url{http://www.gnu.org/prep/standards/html_node/Change-Logs.html}},
    2.61 +}
    2.62 +
    2.63 +@Misc{web:macpython,
    2.64 +  author =	 {Bob Ippolito, Ronald Oussoren},
    2.65 +  title =	 {Universal MacPython},
    2.66 +  note =	 {\url{http://bob.pythonmac.org/archives/2006/04/10/python-and-universal-binaries-on-mac-os-x/}},
    2.67 +}
    2.68 +
    2.69 +@Misc{web:putty,
    2.70 +  author =	 {Simon Tatham},
    2.71 +  title =	 {PuTTY---open source ssh client for Windows},
    2.72 +  note =	 {\url{http://www.chiark.greenend.org.uk/~sgtatham/putty/}},
    2.73 +}
    2.74 +
    2.75 +@Misc{web:configparser,
    2.76 +  author =       {Python.org},
    2.77 +  title =	 {\texttt{ConfigParser}---Configuration file parser},
    2.78 +  note =	 {\url{http://docs.python.org/lib/module-ConfigParser.html}},
    2.79 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/fr/99defs.tex	Thu Feb 05 12:37:03 2009 +0100
     3.3 @@ -0,0 +1,146 @@
     3.4 +% Bug ID.
     3.5 +\newcommand{\bug}[1]{\index{Mercurial bug
     3.6 +    database!\href{http://www.selenic.com/mercurial/bts/issue#1}{bug
     3.7 +      ~#1}}\href{http://www.selenic.com/mercurial/bts/issue#1}{Mercurial
     3.8 +    bug no.~#1}}
     3.9 +
    3.10 +% File name in the user's home directory.
    3.11 +\newcommand{\tildefile}[1]{\texttt{\~{}/#1}}
    3.12 +
    3.13 +% File name.
    3.14 +\newcommand{\filename}[1]{\texttt{#1}}
    3.15 +
    3.16 +% Directory name.
    3.17 +\newcommand{\dirname}[1]{\texttt{#1}}
    3.18 +
    3.19 +% File name, with index entry.
    3.20 +% The ``s'' prefix comes from ``special''.
    3.21 +\newcommand{\sfilename}[1]{\index{\texttt{#1} file}\texttt{#1}}
    3.22 +
    3.23 +% Directory name, with index entry.
    3.24 +\newcommand{\sdirname}[1]{\index{\texttt{#1} directory}\texttt{#1}}
    3.25 +
    3.26 +% Mercurial extension.
    3.27 +\newcommand{\hgext}[1]{\index{\texttt{#1} extension}\texttt{#1}}
    3.28 +
    3.29 +% Command provided by a Mercurial extension.
    3.30 +\newcommand{\hgxcmd}[2]{\index{\texttt{#2} command (\texttt{#1}
    3.31 +      extension)}\index{\texttt{#1} extension!\texttt{#2} command}``\texttt{hg #2}''}
    3.32 +
    3.33 +% Mercurial command.
    3.34 +\newcommand{\hgcmd}[1]{\index{\texttt{#1} command}``\texttt{hg #1}''}
    3.35 +
    3.36 +% Mercurial command, with arguments.
    3.37 +\newcommand{\hgcmdargs}[2]{\index{\texttt{#1} command}``\texttt{hg #1 #2}''}
    3.38 +
    3.39 +\newcommand{\tplkword}[1]{\index{\texttt{#1} template keyword}\index{template keywords!\texttt{#1}}\texttt{#1}}
    3.40 +
    3.41 +\newcommand{\tplkwfilt}[2]{\index{\texttt{#1} template keyword!\texttt{#2}
    3.42 +    filter}\index{template filters!\texttt{#2}}\index{\texttt{#2}
    3.43 +    template filter}\texttt{#2}}
    3.44 +
    3.45 +\newcommand{\tplfilter}[1]{\index{template
    3.46 +    filters!\texttt{#1}}\index{\texttt{#1} template
    3.47 +    filter}\texttt{#1}}
    3.48 +
    3.49 +% Shell/system command.
    3.50 +\newcommand{\command}[1]{\index{\texttt{#1} system command}\texttt{#1}}
    3.51 +
    3.52 +% Shell/system command, with arguments.
    3.53 +\newcommand{\cmdargs}[2]{\index{\texttt{#1} system command}``\texttt{#1 #2}''}
    3.54 +
    3.55 +% Mercurial command option.
    3.56 +\newcommand{\hgopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}}
    3.57 +
    3.58 +% Mercurial command option, provided by an extension command.
    3.59 +\newcommand{\hgxopt}[3]{\index{\texttt{#2} command (\texttt{#1} extension)!\texttt{#3} option}\index{\texttt{#1} extension!\texttt{#2} command!\texttt{#3} option}\texttt{#3}}
    3.60 +
    3.61 +% Mercurial global option.
    3.62 +\newcommand{\hggopt}[1]{\index{global options!\texttt{#1} option}\texttt{#1}}
    3.63 +
    3.64 +% Shell/system command option.
    3.65 +\newcommand{\cmdopt}[2]{\index{\texttt{#1} command!\texttt{#2} option}\texttt{#2}}
    3.66 +
    3.67 +% Command option.
    3.68 +\newcommand{\option}[1]{\texttt{#1}}
    3.69 +
    3.70 +% Software package.
    3.71 +\newcommand{\package}[1]{\index{\texttt{#1} package}\texttt{#1}}
    3.72 +
    3.73 +% Section name from a hgrc file.
    3.74 +\newcommand{\rcsection}[1]{\index{\texttt{hgrc} file!\texttt{#1} section}\texttt{[#1]}}
    3.75 +
    3.76 +% Named item in a hgrc file section.
    3.77 +\newcommand{\rcitem}[2]{\index{\texttt{hgrc} file!\texttt{#1}
    3.78 +    section!\texttt{#2} entry}\texttt{#2}}
    3.79 +
    3.80 +% hgrc file.
    3.81 +\newcommand{\hgrc}{\index{configuration file!\texttt{hgrc}
    3.82 +    (Linux/Unix)}\index{\texttt{hgrc} configuration file}\texttt{hgrc}}
    3.83 +
    3.84 +% Mercurial.ini file.
    3.85 +\newcommand{\hgini}{\index{configuration file!\texttt{Mercurial.ini}
    3.86 +    (Windows)}\index{\texttt{Mercurial.ini} configuration file}\texttt{Mercurial.ini}}
    3.87 +
    3.88 +% Hook name.
    3.89 +\newcommand{\hook}[1]{\index{\texttt{#1} hook}\index{hooks!\texttt{#1}}\texttt{#1}}
    3.90 +
    3.91 +% Environment variable.
    3.92 +\newcommand{\envar}[1]{\index{\texttt{#1} environment
    3.93 +    variable}\index{environment variables!\texttt{#1}}\texttt{#1}}
    3.94 +
    3.95 +% Python module.
    3.96 +\newcommand{\pymod}[1]{\index{\texttt{#1} module}\texttt{#1}}
    3.97 +
    3.98 +% Python class in a module.
    3.99 +\newcommand{\pymodclass}[2]{\index{\texttt{#1} module!\texttt{#2}
   3.100 +    class}\texttt{#1.#2}}
   3.101 +
   3.102 +% Python function in a module.
   3.103 +\newcommand{\pymodfunc}[2]{\index{\texttt{#1} module!\texttt{#2}
   3.104 +    function}\texttt{#1.#2}}
   3.105 +
   3.106 +% Note: blah blah.
   3.107 +\newsavebox{\notebox}
   3.108 +\newenvironment{note}%
   3.109 +  {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Note:}\space}%
   3.110 +  {\end{minipage}\end{lrbox}\fbox{\usebox{\notebox}}}
   3.111 +\newenvironment{caution}%
   3.112 +  {\begin{lrbox}{\notebox}\begin{minipage}{0.7\textwidth}\textbf{Caution:}\space}%
   3.113 +  {\end{minipage}\end{lrbox}\fbox{\usebox{\notebox}}}
   3.114 +
   3.115 +% Code sample, eating 4 characters of leading space.
   3.116 +\DefineVerbatimEnvironment{codesample4}{Verbatim}{frame=single,gobble=4,numbers=left,commandchars=\\\{\}}
   3.117 +
   3.118 +% Code sample, eating 2 characters of leading space.
   3.119 +\DefineVerbatimEnvironment{codesample2}{Verbatim}{frame=single,gobble=2,numbers=left,commandchars=\\\{\}}
   3.120 +
   3.121 +% Interaction from the examples directory.
   3.122 +\newcommand{\interaction}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{examples/#1.lxo}}
   3.123 +% Example code from the examples directory.
   3.124 +\newcommand{\excode}[1]{\VerbatimInput[frame=single,numbers=left,commandchars=\\\{\}]{../examples/#1}}
   3.125 +
   3.126 +% Graphics inclusion.
   3.127 +\ifpdf
   3.128 +  \newcommand{\grafix}[1]{\includegraphics{#1}}
   3.129 +\else
   3.130 +  \newcommand{\grafix}[1]{\includegraphics{#1.png}}
   3.131 +\fi
   3.132 +
   3.133 +% Reference entry for a command.
   3.134 +\newcommand{\cmdref}[2]{\section{\hgcmd{#1}---#2}\label{cmdref:#1}\index{\texttt{#1} command}}
   3.135 +
   3.136 +% Reference entry for a command option with long and short forms.
   3.137 +\newcommand{\optref}[3]{\subsubsection{\hgopt{#1}{--#3}, also \hgopt{#1}{-#2}}}
   3.138 +
   3.139 +% Reference entry for a command option with only long form.
   3.140 +\newcommand{\loptref}[2]{\subsubsection{\hgopt{#1}{--#2} option}}
   3.141 +
   3.142 +% command to generate a footnote to be used as a translator's note
   3.143 +\newcommand{\ndt}[1]{\footnote{\textbf{N. del T.} #1}}
   3.144 +
   3.145 +
   3.146 +%%% Local Variables: 
   3.147 +%%% mode: latex
   3.148 +%%% TeX-master: "00book"
   3.149 +%%% End: 
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/fr/Makefile	Thu Feb 05 12:37:03 2009 +0100
     4.3 @@ -0,0 +1,220 @@
     4.4 +# This makefile requires GNU make.
     4.5 +
     4.6 +sources := \
     4.7 +	00book.tex \
     4.8 +	99book.bib \
     4.9 +	99defs.tex \
    4.10 +	build_id.tex \
    4.11 +	branch.tex \
    4.12 +	cmdref.tex \
    4.13 +	collab.tex \
    4.14 +	concepts.tex \
    4.15 +	daily.tex \
    4.16 +	filenames.tex \
    4.17 +	hg_id.tex \
    4.18 +	hgext.tex \
    4.19 +	hook.tex \
    4.20 +	intro.tex \
    4.21 +	mq.tex \
    4.22 +	mq-collab.tex \
    4.23 +	mq-ref.tex \
    4.24 +	preface.tex \
    4.25 +	srcinstall.tex \
    4.26 +	template.tex \
    4.27 +	tour-basic.tex \
    4.28 +	tour-merge.tex \
    4.29 +	undo.tex
    4.30 +
    4.31 +image-sources := \
    4.32 +	feature-branches.dot \
    4.33 +	filelog.svg \
    4.34 +	kdiff3.png \
    4.35 +	metadata.svg \
    4.36 +	mq-stack.svg \
    4.37 +	note.png \
    4.38 +	revlog.svg \
    4.39 +	snapshot.svg \
    4.40 +	tour-history.svg \
    4.41 +	tour-merge-conflict.svg \
    4.42 +	tour-merge-merge.svg \
    4.43 +	tour-merge-pull.svg \
    4.44 +	tour-merge-sep-repos.svg \
    4.45 +	undo-manual.dot \
    4.46 +	undo-manual-merge.dot \
    4.47 +	undo-non-tip.dot \
    4.48 +	undo-simple.dot \
    4.49 +	wdir.svg \
    4.50 +	wdir-after-commit.svg \
    4.51 +	wdir-branch.svg \
    4.52 +	wdir-merge.svg \
    4.53 +	wdir-pre-branch.svg
    4.54 +
    4.55 +image-dot := $(filter %.dot,$(image-sources))
    4.56 +image-svg := $(filter %.svg,$(image-sources))
    4.57 +image-png := $(filter %.png,$(image-sources))
    4.58 +
    4.59 +image-pdf := $(image-dot:%.dot=%.pdf) $(image-svg:%.svg=%.pdf) $(image-png)
    4.60 +image-html := $(image-dot:%.dot=%.png) $(image-svg:%.svg=%.png) $(image-png)
    4.61 +
    4.62 +example-sources := \
    4.63 +	backout \
    4.64 +	bisect \
    4.65 +	branching \
    4.66 +	branch-named \
    4.67 +	branch-repo \
    4.68 +	cmdref \
    4.69 +	daily.copy \
    4.70 +	daily.files \
    4.71 +	daily.rename \
    4.72 +	daily.revert \
    4.73 +	extdiff \
    4.74 +	filenames \
    4.75 +	hook.msglen \
    4.76 +	hook.simple \
    4.77 +	hook.ws \
    4.78 +	issue29 \
    4.79 +	mq.guards \
    4.80 +	mq.qinit-help \
    4.81 +	mq.dodiff \
    4.82 +	mq.id \
    4.83 +	mq.tarball \
    4.84 +	mq.tools \
    4.85 +	mq.tutorial \
    4.86 +	rename.divergent \
    4.87 +	rollback \
    4.88 +	tag \
    4.89 +	template.simple \
    4.90 +	template.svnstyle \
    4.91 +	tour \
    4.92 +	tour-merge-conflict
    4.93 +
    4.94 +example-prereqs := \
    4.95 +	/usr/bin/merge
    4.96 +
    4.97 +dist-sources := \
    4.98 +	../html/hgicon.png \
    4.99 +	../html/index.html.var \
   4.100 +	../html/index.en.html
   4.101 +
   4.102 +latex-options = \
   4.103 +	-interaction batchmode \
   4.104 +	-output-directory $(dir $(1)) \
   4.105 +	-jobname $(basename $(notdir $(1)))
   4.106 +
   4.107 +hg = $(shell which hg)
   4.108 +
   4.109 +hg-id = $(shell hg parents --template '{node|short}, dated {date|isodate},\n')
   4.110 +
   4.111 +hg-version = $(shell hg version -q | \
   4.112 +		     sed 's,.*(version \(unknown\|[a-f0-9+]*\)),\1,')
   4.113 +
   4.114 +all: pdf html
   4.115 +
   4.116 +pdf: pdf/hgbook.pdf
   4.117 +
   4.118 +define pdf
   4.119 +	mkdir -p $(dir $@)
   4.120 +	TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1)
   4.121 +	cp 99book.bib $(dir $@)
   4.122 +	cd $(dir $@) && bibtex $(basename $(notdir $@))
   4.123 +	cd $(dir $@) && makeindex $(basename $(notdir $@))
   4.124 +	TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1)
   4.125 +	TEXINPUTS=$(dir $<): pdflatex $(call latex-options,$@) $< || (rm -f $@; exit 1)
   4.126 +	if grep 'Reference.*undefined' $(@:.pdf=.log); then exit 1; fi
   4.127 +endef
   4.128 +
   4.129 +pdf/hgbook.pdf: $(sources) examples $(image-pdf)
   4.130 +	$(call pdf)
   4.131 +
   4.132 +html: onepage split
   4.133 +
   4.134 +onepage: $(htlatex) html/onepage/hgbook.html html/onepage/hgbook.css $(image-html:%=html/onepage/%)
   4.135 +
   4.136 +html/onepage/%: %
   4.137 +	cp $< $@
   4.138 +
   4.139 +split: $(htlatex) html/split/hgbook.html html/split/hgbook.css $(image-html:%=html/split/%)
   4.140 +
   4.141 +html/split/%: %
   4.142 +	cp $< $@
   4.143 +
   4.144 +# This is a horrible hack to work around the fact that the htlatex
   4.145 +# command in tex4ht is itself a horrible hack.  I really don't want to
   4.146 +# include verbatim the big wad of TeX that is repeated in that script,
   4.147 +# but I've given up and run a hacked copy as htlatex.book here.
   4.148 +
   4.149 +define htlatex
   4.150 +	mkdir -p $(dir $(1))
   4.151 +	cp 99book.bib $(dir $(1))
   4.152 +	TEXINPUTS=$(dir $(2)): ./htlatex.book $(2) "bookhtml,html4-uni,$(3)" " -cunihtf -utf8" "$(dir $(1))" "$(call latex-options,$(1))" || (rm -f $(1); exit 1)
   4.153 +	cd $(dir $(1)) && tex4ht -f/$(basename $(notdir $(1))) -cvalidate -cunihtf
   4.154 +	cd $(dir $(1)) && t4ht -f/$(basename $(notdir $(1)))
   4.155 +	./fixhtml.py $(dir $(1))/*.html
   4.156 +	rm $(dir $(1))/hgbook.css
   4.157 +endef
   4.158 +
   4.159 +html/onepage/hgbook.html: $(sources) examples $(image-html) bookhtml.cfg
   4.160 +	$(call htlatex,$@,$<)
   4.161 +
   4.162 +html/split/hgbook.html: $(sources) examples bookhtml.cfg
   4.163 +	$(call htlatex,$@,$<,2)
   4.164 +
   4.165 +# Produce 90dpi PNGs for the web.
   4.166 +
   4.167 +%.png: %.svg fixsvg
   4.168 +	./fixsvg $<
   4.169 +	inkscape -D -e $@ $<-tmp.svg
   4.170 +	rm $<-tmp.svg
   4.171 +
   4.172 +%.svg: %.dot
   4.173 +	dot -Tsvg -o $@ $<
   4.174 +
   4.175 +# Produce eps & pdf for the pdf
   4.176 +
   4.177 +%.pdf: %.eps
   4.178 +	epstopdf $<
   4.179 +
   4.180 +%.eps: %.svg
   4.181 +	./fixsvg $<
   4.182 +	inkscape -E $@ $<-tmp.svg
   4.183 +	rm $<-tmp.svg
   4.184 +
   4.185 +%.eps: %.dot
   4.186 +	dot -Tps -o $@ $<
   4.187 +
   4.188 +examples: $(example-prereqs) examples/.run
   4.189 +
   4.190 +examples/.run: $(example-sources:%=examples/%.run)
   4.191 +	touch examples/.run
   4.192 +
   4.193 +examples/%.run: examples/% examples/run-example
   4.194 +	cd examples && ./run-example $(notdir $<)
   4.195 +
   4.196 +changelog := $(wildcard ../.hg/store/00changelog.[id])
   4.197 +ifeq ($(changelog),)
   4.198 +changelog := $(wildcard ../.hg/00changelog.[id])
   4.199 +endif
   4.200 +
   4.201 +build_id.tex: $(changelog)
   4.202 +	echo -n '$(hg-id)' > build_id.tex
   4.203 +
   4.204 +hg_id.tex: $(hg)
   4.205 +	echo -n '$(hg-version)' > hg_id.tex
   4.206 +
   4.207 +clean:
   4.208 +	rm -rf dist html pdf \
   4.209 +		$(image-dot:%.dot=%.pdf) \
   4.210 +		$(image-dot:%.dot=%.png) \
   4.211 +		$(image-svg:%.svg=%.pdf) \
   4.212 +		$(image-svg:%.svg=%.png) \
   4.213 +		examples/*.{lxo,run} examples/.run build_id.tex hg_id.tex
   4.214 +
   4.215 +install: pdf split $(dist-sources)
   4.216 +	rm -rf dist
   4.217 +	mkdir -p dist
   4.218 +	cp pdf/hgbook.pdf dist
   4.219 +	cp html/split/*.{css,html,png} dist
   4.220 +	cp $(dist-sources) dist
   4.221 +
   4.222 +rsync: install
   4.223 +	rsync -avz --delete dist sp.red-bean.com:public_html/hgbook
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/fr/bookhtml.cfg	Thu Feb 05 12:37:03 2009 +0100
     5.3 @@ -0,0 +1,18 @@
     5.4 +% -*- latex -*-
     5.5 +
     5.6 +\Preamble{xhtml}
     5.7 +
     5.8 +% Tex4ht's default definition of lists is complete crap.
     5.9 +% Unfortunately, it can't distinguish between "ul" and "dl" lists.
    5.10 +
    5.11 +\ConfigureList{itemize}%
    5.12 +   {\EndP\HCode{<ul>}\let\endItem=\empty}
    5.13 +   {\ifvmode \IgnorePar\fi
    5.14 +    \EndP\HCode{</li></ul>}\ShowPar}
    5.15 +   {\endItem \def\endItem{\EndP\Tg</span>}\HCode{<li><span class="dt">}}
    5.16 +   {\HCode{</span><span class="dd">}}
    5.17 +\def\textbullet{}
    5.18 +
    5.19 +\begin{document}
    5.20 +
    5.21 +\EndPreamble
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/fr/branch.tex	Thu Feb 05 12:37:03 2009 +0100
     6.3 @@ -0,0 +1,392 @@
     6.4 +\chapter{Managing releases and branchy development}
     6.5 +\label{chap:branch}
     6.6 +
     6.7 +Mercurial provides several mechanisms for you to manage a project that
     6.8 +is making progress on multiple fronts at once.  To understand these
     6.9 +mechanisms, let's first take a brief look at a fairly normal software
    6.10 +project structure.
    6.11 +
    6.12 +Many software projects issue periodic ``major'' releases that contain
    6.13 +substantial new features.  In parallel, they may issue ``minor''
    6.14 +releases.  These are usually identical to the major releases off which
    6.15 +they're based, but with a few bugs fixed.
    6.16 +
    6.17 +In this chapter, we'll start by talking about how to keep records of
    6.18 +project milestones such as releases.  We'll then continue on to talk
    6.19 +about the flow of work between different phases of a project, and how
    6.20 +Mercurial can help you to isolate and manage this work.
    6.21 +
    6.22 +\section{Giving a persistent name to a revision}
    6.23 +
    6.24 +Once you decide that you'd like to call a particular revision a
    6.25 +``release'', it's a good idea to record the identity of that revision.
    6.26 +This will let you reproduce that release at a later date, for whatever
    6.27 +purpose you might need at the time (reproducing a bug, porting to a
    6.28 +new platform, etc).
    6.29 +\interaction{tag.init}
    6.30 +
    6.31 +Mercurial lets you give a permanent name to any revision using the
    6.32 +\hgcmd{tag} command.  Not surprisingly, these names are called
    6.33 +``tags''.
    6.34 +\interaction{tag.tag}
    6.35 +
    6.36 +A tag is nothing more than a ``symbolic name'' for a revision.  Tags
    6.37 +exist purely for your convenience, so that you have a handy permanent
    6.38 +way to refer to a revision; Mercurial doesn't interpret the tag names
    6.39 +you use in any way.  Neither does Mercurial place any restrictions on
    6.40 +the name of a tag, beyond a few that are necessary to ensure that a
    6.41 +tag can be parsed unambiguously.  A tag name cannot contain any of the
    6.42 +following characters:
    6.43 +\begin{itemize}
    6.44 +\item Colon (ASCII 58, ``\texttt{:}'')
    6.45 +\item Carriage return (ASCII 13, ``\Verb+\r+'')
    6.46 +\item Newline (ASCII 10, ``\Verb+\n+'')
    6.47 +\end{itemize}
    6.48 +
    6.49 +You can use the \hgcmd{tags} command to display the tags present in
    6.50 +your repository.  In the output, each tagged revision is identified
    6.51 +first by its name, then by revision number, and finally by the unique
    6.52 +hash of the revision.  
    6.53 +\interaction{tag.tags}
    6.54 +Notice that \texttt{tip} is listed in the output of \hgcmd{tags}.  The
    6.55 +\texttt{tip} tag is a special ``floating'' tag, which always
    6.56 +identifies the newest revision in the repository.
    6.57 +
    6.58 +In the output of the \hgcmd{tags} command, tags are listed in reverse
    6.59 +order, by revision number.  This usually means that recent tags are
    6.60 +listed before older tags.  It also means that \texttt{tip} is always
    6.61 +going to be the first tag listed in the output of \hgcmd{tags}.
    6.62 +
    6.63 +When you run \hgcmd{log}, if it displays a revision that has tags
    6.64 +associated with it, it will print those tags.
    6.65 +\interaction{tag.log}
    6.66 +
    6.67 +Any time you need to provide a revision~ID to a Mercurial command, the
    6.68 +command will accept a tag name in its place.  Internally, Mercurial
    6.69 +will translate your tag name into the corresponding revision~ID, then
    6.70 +use that.
    6.71 +\interaction{tag.log.v1.0}
    6.72 +
    6.73 +There's no limit on the number of tags you can have in a repository,
    6.74 +or on the number of tags that a single revision can have.  As a
    6.75 +practical matter, it's not a great idea to have ``too many'' (a number
    6.76 +which will vary from project to project), simply because tags are
    6.77 +supposed to help you to find revisions.  If you have lots of tags, the
    6.78 +ease of using them to identify revisions diminishes rapidly.
    6.79 +
    6.80 +For example, if your project has milestones as frequent as every few
    6.81 +days, it's perfectly reasonable to tag each one of those.  But if you
    6.82 +have a continuous build system that makes sure every revision can be
    6.83 +built cleanly, you'd be introducing a lot of noise if you were to tag
    6.84 +every clean build.  Instead, you could tag failed builds (on the
    6.85 +assumption that they're rare!), or simply not use tags to track
    6.86 +buildability.
    6.87 +
    6.88 +If you want to remove a tag that you no longer want, use
    6.89 +\hgcmdargs{tag}{--remove}.  
    6.90 +\interaction{tag.remove}
    6.91 +You can also modify a tag at any time, so that it identifies a
    6.92 +different revision, by simply issuing a new \hgcmd{tag} command.
    6.93 +You'll have to use the \hgopt{tag}{-f} option to tell Mercurial that
    6.94 +you \emph{really} want to update the tag.
    6.95 +\interaction{tag.replace}
    6.96 +There will still be a permanent record of the previous identity of the
    6.97 +tag, but Mercurial will no longer use it.  There's thus no penalty to
    6.98 +tagging the wrong revision; all you have to do is turn around and tag
    6.99 +the correct revision once you discover your error.
   6.100 +
   6.101 +Mercurial stores tags in a normal revision-controlled file in your
   6.102 +repository.  If you've created any tags, you'll find them in a file
   6.103 +named \sfilename{.hgtags}.  When you run the \hgcmd{tag} command,
   6.104 +Mercurial modifies this file, then automatically commits the change to
   6.105 +it.  This means that every time you run \hgcmd{tag}, you'll see a
   6.106 +corresponding changeset in the output of \hgcmd{log}.
   6.107 +\interaction{tag.tip}
   6.108 +
   6.109 +\subsection{Handling tag conflicts during a merge}
   6.110 +
   6.111 +You won't often need to care about the \sfilename{.hgtags} file, but
   6.112 +it sometimes makes its presence known during a merge.  The format of
   6.113 +the file is simple: it consists of a series of lines.  Each line
   6.114 +starts with a changeset hash, followed by a space, followed by the
   6.115 +name of a tag.
   6.116 +
   6.117 +If you're resolving a conflict in the \sfilename{.hgtags} file during
   6.118 +a merge, there's one twist to modifying the \sfilename{.hgtags} file:
   6.119 +when Mercurial is parsing the tags in a repository, it \emph{never}
   6.120 +reads the working copy of the \sfilename{.hgtags} file.  Instead, it
   6.121 +reads the \emph{most recently committed} revision of the file.
   6.122 +
   6.123 +An unfortunate consequence of this design is that you can't actually
   6.124 +verify that your merged \sfilename{.hgtags} file is correct until
   6.125 +\emph{after} you've committed a change.  So if you find yourself
   6.126 +resolving a conflict on \sfilename{.hgtags} during a merge, be sure to
   6.127 +run \hgcmd{tags} after you commit.  If it finds an error in the
   6.128 +\sfilename{.hgtags} file, it will report the location of the error,
   6.129 +which you can then fix and commit.  You should then run \hgcmd{tags}
   6.130 +again, just to be sure that your fix is correct.
   6.131 +
   6.132 +\subsection{Tags and cloning}
   6.133 +
   6.134 +You may have noticed that the \hgcmd{clone} command has a
   6.135 +\hgopt{clone}{-r} option that lets you clone an exact copy of the
   6.136 +repository as of a particular changeset.  The new clone will not
   6.137 +contain any project history that comes after the revision you
   6.138 +specified.  This has an interaction with tags that can surprise the
   6.139 +unwary.
   6.140 +
   6.141 +Recall that a tag is stored as a revision to the \sfilename{.hgtags}
   6.142 +file, so that when you create a tag, the changeset in which it's
   6.143 +recorded necessarily refers to an older changeset.  When you run
   6.144 +\hgcmdargs{clone}{-r foo} to clone a repository as of tag
   6.145 +\texttt{foo}, the new clone \emph{will not contain the history that
   6.146 +  created the tag} that you used to clone the repository.  The result
   6.147 +is that you'll get exactly the right subset of the project's history
   6.148 +in the new repository, but \emph{not} the tag you might have expected.
   6.149 +
   6.150 +\subsection{When permanent tags are too much}
   6.151 +
   6.152 +Since Mercurial's tags are revision controlled and carried around with
   6.153 +a project's history, everyone you work with will see the tags you
   6.154 +create.  But giving names to revisions has uses beyond simply noting
   6.155 +that revision \texttt{4237e45506ee} is really \texttt{v2.0.2}.  If
   6.156 +you're trying to track down a subtle bug, you might want a tag to
   6.157 +remind you of something like ``Anne saw the symptoms with this
   6.158 +revision''.
   6.159 +
   6.160 +For cases like this, what you might want to use are \emph{local} tags.
   6.161 +You can create a local tag with the \hgopt{tag}{-l} option to the
   6.162 +\hgcmd{tag} command.  This will store the tag in a file called
   6.163 +\sfilename{.hg/localtags}.  Unlike \sfilename{.hgtags},
   6.164 +\sfilename{.hg/localtags} is not revision controlled.  Any tags you
   6.165 +create using \hgopt{tag}{-l} remain strictly local to the repository
   6.166 +you're currently working in.
   6.167 +
   6.168 +\section{The flow of changes---big picture vs. little}
   6.169 +
   6.170 +To return to the outline I sketched at the beginning of a chapter,
   6.171 +let's think about a project that has multiple concurrent pieces of
   6.172 +work under development at once.
   6.173 +
   6.174 +There might be a push for a new ``main'' release; a new minor bugfix
   6.175 +release to the last main release; and an unexpected ``hot fix'' to an
   6.176 +old release that is now in maintenance mode.
   6.177 +
   6.178 +The usual way people refer to these different concurrent directions of
   6.179 +development is as ``branches''.  However, we've already seen numerous
   6.180 +times that Mercurial treats \emph{all of history} as a series of
   6.181 +branches and merges.  Really, what we have here is two ideas that are
   6.182 +peripherally related, but which happen to share a name.
   6.183 +\begin{itemize}
   6.184 +\item ``Big picture'' branches represent the sweep of a project's
   6.185 +  evolution; people give them names, and talk about them in
   6.186 +  conversation.
   6.187 +\item ``Little picture'' branches are artefacts of the day-to-day
   6.188 +  activity of developing and merging changes.  They expose the
   6.189 +  narrative of how the code was developed.
   6.190 +\end{itemize}
   6.191 +
   6.192 +\section{Managing big-picture branches in repositories}
   6.193 +
   6.194 +The easiest way to isolate a ``big picture'' branch in Mercurial is in
   6.195 +a dedicated repository.  If you have an existing shared
   6.196 +repository---let's call it \texttt{myproject}---that reaches a ``1.0''
   6.197 +milestone, you can start to prepare for future maintenance releases on
   6.198 +top of version~1.0 by tagging the revision from which you prepared
   6.199 +the~1.0 release.
   6.200 +\interaction{branch-repo.tag}
   6.201 +You can then clone a new shared \texttt{myproject-1.0.1} repository as
   6.202 +of that tag.
   6.203 +\interaction{branch-repo.clone}
   6.204 +
   6.205 +Afterwards, if someone needs to work on a bug fix that ought to go
   6.206 +into an upcoming~1.0.1 minor release, they clone the
   6.207 +\texttt{myproject-1.0.1} repository, make their changes, and push them
   6.208 +back.
   6.209 +\interaction{branch-repo.bugfix}
   6.210 +Meanwhile, development for the next major release can continue,
   6.211 +isolated and unabated, in the \texttt{myproject} repository.
   6.212 +\interaction{branch-repo.new}
   6.213 +
   6.214 +\section{Don't repeat yourself: merging across branches}
   6.215 +
   6.216 +In many cases, if you have a bug to fix on a maintenance branch, the
   6.217 +chances are good that the bug exists on your project's main branch
   6.218 +(and possibly other maintenance branches, too).  It's a rare developer
   6.219 +who wants to fix the same bug multiple times, so let's look at a few
   6.220 +ways that Mercurial can help you to manage these bugfixes without
   6.221 +duplicating your work.
   6.222 +
   6.223 +In the simplest instance, all you need to do is pull changes from your
   6.224 +maintenance branch into your local clone of the target branch.
   6.225 +\interaction{branch-repo.pull}
   6.226 +You'll then need to merge the heads of the two branches, and push back
   6.227 +to the main branch.
   6.228 +\interaction{branch-repo.merge}
   6.229 +
   6.230 +\section{Naming branches within one repository}
   6.231 +
   6.232 +In most instances, isolating branches in repositories is the right
   6.233 +approach.  Its simplicity makes it easy to understand; and so it's
   6.234 +hard to make mistakes.  There's a one-to-one relationship between
   6.235 +branches you're working in and directories on your system.  This lets
   6.236 +you use normal (non-Mercurial-aware) tools to work on files within a
   6.237 +branch/repository.
   6.238 +
   6.239 +If you're more in the ``power user'' category (\emph{and} your
   6.240 +collaborators are too), there is an alternative way of handling
   6.241 +branches that you can consider.  I've already mentioned the
   6.242 +human-level distinction between ``small picture'' and ``big picture''
   6.243 +branches.  While Mercurial works with multiple ``small picture''
   6.244 +branches in a repository all the time (for example after you pull
   6.245 +changes in, but before you merge them), it can \emph{also} work with
   6.246 +multiple ``big picture'' branches.
   6.247 +
   6.248 +The key to working this way is that Mercurial lets you assign a
   6.249 +persistent \emph{name} to a branch.  There always exists a branch
   6.250 +named \texttt{default}.  Even before you start naming branches
   6.251 +yourself, you can find traces of the \texttt{default} branch if you
   6.252 +look for them.
   6.253 +
   6.254 +As an example, when you run the \hgcmd{commit} command, and it pops up
   6.255 +your editor so that you can enter a commit message, look for a line
   6.256 +that contains the text ``\texttt{HG: branch default}'' at the bottom.
   6.257 +This is telling you that your commit will occur on the branch named
   6.258 +\texttt{default}.
   6.259 +
   6.260 +To start working with named branches, use the \hgcmd{branches}
   6.261 +command.  This command lists the named branches already present in
   6.262 +your repository, telling you which changeset is the tip of each.
   6.263 +\interaction{branch-named.branches}
   6.264 +Since you haven't created any named branches yet, the only one that
   6.265 +exists is \texttt{default}.
   6.266 +
   6.267 +To find out what the ``current'' branch is, run the \hgcmd{branch}
   6.268 +command, giving it no arguments.  This tells you what branch the
   6.269 +parent of the current changeset is on.
   6.270 +\interaction{branch-named.branch}
   6.271 +
   6.272 +To create a new branch, run the \hgcmd{branch} command again.  This
   6.273 +time, give it one argument: the name of the branch you want to create.
   6.274 +\interaction{branch-named.create}
   6.275 +
   6.276 +After you've created a branch, you might wonder what effect the
   6.277 +\hgcmd{branch} command has had.  What do the \hgcmd{status} and
   6.278 +\hgcmd{tip} commands report?
   6.279 +\interaction{branch-named.status}
   6.280 +Nothing has changed in the working directory, and there's been no new
   6.281 +history created.  As this suggests, running the \hgcmd{branch} command
   6.282 +has no permanent effect; it only tells Mercurial what branch name to
   6.283 +use the \emph{next} time you commit a changeset.
   6.284 +
   6.285 +When you commit a change, Mercurial records the name of the branch on
   6.286 +which you committed.  Once you've switched from the \texttt{default}
   6.287 +branch to another and committed, you'll see the name of the new branch
   6.288 +show up in the output of \hgcmd{log}, \hgcmd{tip}, and other commands
   6.289 +that display the same kind of output.
   6.290 +\interaction{branch-named.commit}
   6.291 +The \hgcmd{log}-like commands will print the branch name of every
   6.292 +changeset that's not on the \texttt{default} branch.  As a result, if
   6.293 +you never use named branches, you'll never see this information.
   6.294 +
   6.295 +Once you've named a branch and committed a change with that name,
   6.296 +every subsequent commit that descends from that change will inherit
   6.297 +the same branch name.  You can change the name of a branch at any
   6.298 +time, using the \hgcmd{branch} command.  
   6.299 +\interaction{branch-named.rebranch}
   6.300 +In practice, this is something you won't do very often, as branch
   6.301 +names tend to have fairly long lifetimes.  (This isn't a rule, just an
   6.302 +observation.)
   6.303 +
   6.304 +\section{Dealing with multiple named branches in a repository}
   6.305 +
   6.306 +If you have more than one named branch in a repository, Mercurial will
   6.307 +remember the branch that your working directory on when you start a
   6.308 +command like \hgcmd{update} or \hgcmdargs{pull}{-u}.  It will update
   6.309 +the working directory to the tip of this branch, no matter what the
   6.310 +``repo-wide'' tip is.  To update to a revision that's on a different
   6.311 +named branch, you may need to use the \hgopt{update}{-C} option to
   6.312 +\hgcmd{update}.
   6.313 +
   6.314 +This behaviour is a little subtle, so let's see it in action.  First,
   6.315 +let's remind ourselves what branch we're currently on, and what
   6.316 +branches are in our repository.
   6.317 +\interaction{branch-named.parents}
   6.318 +We're on the \texttt{bar} branch, but there also exists an older
   6.319 +\hgcmd{foo} branch.
   6.320 +
   6.321 +We can \hgcmd{update} back and forth between the tips of the
   6.322 +\texttt{foo} and \texttt{bar} branches without needing to use the
   6.323 +\hgopt{update}{-C} option, because this only involves going backwards
   6.324 +and forwards linearly through our change history.
   6.325 +\interaction{branch-named.update-switchy}
   6.326 +
   6.327 +If we go back to the \texttt{foo} branch and then run \hgcmd{update},
   6.328 +it will keep us on \texttt{foo}, not move us to the tip of
   6.329 +\texttt{bar}.
   6.330 +\interaction{branch-named.update-nothing}
   6.331 +
   6.332 +Committing a new change on the \texttt{foo} branch introduces a new
   6.333 +head.
   6.334 +\interaction{branch-named.foo-commit}
   6.335 +
   6.336 +\section{Branch names and merging}
   6.337 +
   6.338 +As you've probably noticed, merges in Mercurial are not symmetrical.
   6.339 +Let's say our repository has two heads, 17 and 23.  If I
   6.340 +\hgcmd{update} to 17 and then \hgcmd{merge} with 23, Mercurial records
   6.341 +17 as the first parent of the merge, and 23 as the second.  Whereas if
   6.342 +I \hgcmd{update} to 23 and then \hgcmd{merge} with 17, it records 23
   6.343 +as the first parent, and 17 as the second.
   6.344 +
   6.345 +This affects Mercurial's choice of branch name when you merge.  After
   6.346 +a merge, Mercurial will retain the branch name of the first parent
   6.347 +when you commit the result of the merge.  If your first parent's
   6.348 +branch name is \texttt{foo}, and you merge with \texttt{bar}, the
   6.349 +branch name will still be \texttt{foo} after you merge.
   6.350 +
   6.351 +It's not unusual for a repository to contain multiple heads, each with
   6.352 +the same branch name.  Let's say I'm working on the \texttt{foo}
   6.353 +branch, and so are you.  We commit different changes; I pull your
   6.354 +changes; I now have two heads, each claiming to be on the \texttt{foo}
   6.355 +branch.  The result of a merge will be a single head on the
   6.356 +\texttt{foo} branch, as you might hope.
   6.357 +
   6.358 +But if I'm working on the \texttt{bar} branch, and I merge work from
   6.359 +the \texttt{foo} branch, the result will remain on the \texttt{bar}
   6.360 +branch.
   6.361 +\interaction{branch-named.merge}
   6.362 +
   6.363 +To give a more concrete example, if I'm working on the
   6.364 +\texttt{bleeding-edge} branch, and I want to bring in the latest fixes
   6.365 +from the \texttt{stable} branch, Mercurial will choose the ``right''
   6.366 +(\texttt{bleeding-edge}) branch name when I pull and merge from
   6.367 +\texttt{stable}.
   6.368 +
   6.369 +\section{Branch naming is generally useful}
   6.370 +
   6.371 +You shouldn't think of named branches as applicable only to situations
   6.372 +where you have multiple long-lived branches cohabiting in a single
   6.373 +repository.  They're very useful even in the one-branch-per-repository
   6.374 +case.  
   6.375 +
   6.376 +In the simplest case, giving a name to each branch gives you a
   6.377 +permanent record of which branch a changeset originated on.  This
   6.378 +gives you more context when you're trying to follow the history of a
   6.379 +long-lived branchy project.
   6.380 +
   6.381 +If you're working with shared repositories, you can set up a
   6.382 +\hook{pretxnchangegroup} hook on each that will block incoming changes
   6.383 +that have the ``wrong'' branch name.  This provides a simple, but
   6.384 +effective, defence against people accidentally pushing changes from a
   6.385 +``bleeding edge'' branch to a ``stable'' branch.  Such a hook might
   6.386 +look like this inside the shared repo's \hgrc.
   6.387 +\begin{codesample2}
   6.388 +  [hooks]
   6.389 +  pretxnchangegroup.branch = hg heads --template '{branches} ' | grep mybranch
   6.390 +\end{codesample2}
   6.391 +
   6.392 +%%% Local Variables: 
   6.393 +%%% mode: latex
   6.394 +%%% TeX-master: "00book"
   6.395 +%%% End: 
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/fr/cmdref.py	Thu Feb 05 12:37:03 2009 +0100
     7.3 @@ -0,0 +1,156 @@
     7.4 +#!/usr/bin/env python
     7.5 +
     7.6 +import getopt
     7.7 +import itertools
     7.8 +import os
     7.9 +import re
    7.10 +import sys
    7.11 +
    7.12 +def usage(exitcode):
    7.13 +    print >> sys.stderr, ('usage: %s [-H|--hidden] hg_repo' % 
    7.14 +                          os.path.basename(sys.argv[0]))
    7.15 +    sys.exit(exitcode)
    7.16 +
    7.17 +try:
    7.18 +    opts, args = getopt.getopt(sys.argv[1:], 'AHh?', ['all', 'help', 'hidden'])
    7.19 +    opt_all = False
    7.20 +    opt_hidden = False
    7.21 +    for o, a in opts:
    7.22 +        if o in ('-h', '-?', '--help'):
    7.23 +            usage(0)
    7.24 +        if o in ('-A', '--all'):
    7.25 +            opt_all = True
    7.26 +        if o in ('-H', '--hidden'):
    7.27 +            opt_hidden = True
    7.28 +except getopt.GetoptError, err:
    7.29 +    print >> sys.stderr, 'error:', err
    7.30 +    usage(1)
    7.31 +
    7.32 +try:
    7.33 +    hg_repo, ltx_file = args
    7.34 +except ValueError:
    7.35 +    usage(1)
    7.36 +
    7.37 +if not os.path.isfile(os.path.join(hg_repo, 'mercurial', 'commands.py')):
    7.38 +    print >> sys.stderr, ('error: %r does not contain mercurial code' %
    7.39 +                          hg_repo)
    7.40 +    sys.exit(1)
    7.41 +
    7.42 +sys.path.insert(0, hg_repo)
    7.43 +
    7.44 +from mercurial import commands
    7.45 +
    7.46 +def get_commands():
    7.47 +    seen = {}
    7.48 +    for name, info in sorted(commands.table.iteritems()):
    7.49 +        aliases = name.split('|', 1)
    7.50 +        name = aliases.pop(0).lstrip('^')
    7.51 +        function, options, synopsis = info
    7.52 +        seen[name] = {}
    7.53 +        for shortopt, longopt, arg, desc in options:
    7.54 +            seen[name][longopt] = shortopt
    7.55 +    return seen
    7.56 +
    7.57 +def cmd_filter((name, aliases, options)):
    7.58 +    if opt_all:
    7.59 +        return True
    7.60 +    if opt_hidden:
    7.61 +        return name.startswith('debug')
    7.62 +    return not name.startswith('debug')
    7.63 +
    7.64 +def scan(ltx_file):
    7.65 +    cmdref_re = re.compile(r'^\\cmdref{(?P<cmd>\w+)}')
    7.66 +    optref_re = re.compile(r'^\\l?optref{(?P<cmd>\w+)}'
    7.67 +                           r'(?:{(?P<short>[^}])})?'
    7.68 +                           r'{(?P<long>[^}]+)}')
    7.69 +
    7.70 +    seen = {}
    7.71 +    locs = {}
    7.72 +    for lnum, line in enumerate(open(ltx_file)):
    7.73 +        m = cmdref_re.match(line)
    7.74 +        if m:
    7.75 +            d = m.groupdict()
    7.76 +            cmd = d['cmd']
    7.77 +            seen[cmd] = {}
    7.78 +            locs[cmd] = lnum + 1
    7.79 +            continue
    7.80 +        m = optref_re.match(line)
    7.81 +        if m:
    7.82 +            d = m.groupdict()
    7.83 +            seen[d['cmd']][d['long']] = d['short']
    7.84 +            continue
    7.85 +    return seen, locs
    7.86 +    
    7.87 +documented, locs = scan(ltx_file)
    7.88 +known = get_commands()
    7.89 +
    7.90 +doc_set = set(documented)
    7.91 +known_set = set(known)
    7.92 +
    7.93 +errors = 0
    7.94 +
    7.95 +for nonexistent in sorted(doc_set.difference(known_set)):
    7.96 +    print >> sys.stderr, ('%s:%d: %r command does not exist' %
    7.97 +                          (ltx_file, locs[nonexistent], nonexistent))
    7.98 +    errors += 1
    7.99 +
   7.100 +def optcmp(a, b):
   7.101 +    la, sa = a
   7.102 +    lb, sb = b
   7.103 +    sc = cmp(sa, sb)
   7.104 +    if sc:
   7.105 +        return sc
   7.106 +    return cmp(la, lb)
   7.107 +
   7.108 +for cmd in doc_set.intersection(known_set):
   7.109 +    doc_opts = documented[cmd]
   7.110 +    known_opts = known[cmd]
   7.111 +    
   7.112 +    do_set = set(doc_opts)
   7.113 +    ko_set = set(known_opts)
   7.114 +
   7.115 +    for nonexistent in sorted(do_set.difference(ko_set)):
   7.116 +        print >> sys.stderr, ('%s:%d: %r option to %r command does not exist' %
   7.117 +                              (ltx_file, locs[cmd], nonexistent, cmd))
   7.118 +        errors += 1
   7.119 +
   7.120 +    def mycmp(la, lb):
   7.121 +        sa = known_opts[la]
   7.122 +        sb = known_opts[lb]
   7.123 +        return optcmp((la, sa), (lb, sb))
   7.124 +
   7.125 +    for undocumented in sorted(ko_set.difference(do_set), cmp=mycmp):
   7.126 +        print >> sys.stderr, ('%s:%d: %r option to %r command not documented' %
   7.127 +                              (ltx_file, locs[cmd], undocumented, cmd))
   7.128 +        shortopt = known_opts[undocumented]
   7.129 +        if shortopt:
   7.130 +            print '\optref{%s}{%s}{%s}' % (cmd, shortopt, undocumented)
   7.131 +        else:
   7.132 +            print '\loptref{%s}{%s}' % (cmd, undocumented)
   7.133 +        errors += 1
   7.134 +    sys.stdout.flush()
   7.135 +
   7.136 +if errors:
   7.137 +    sys.exit(1)
   7.138 +
   7.139 +sorted_locs = sorted(locs.iteritems(), key=lambda x:x[1])
   7.140 +
   7.141 +def next_loc(cmd):
   7.142 +    for i, (name, loc) in enumerate(sorted_locs):
   7.143 +        if name >= cmd:
   7.144 +            return sorted_locs[i-1][1] + 1
   7.145 +    return loc
   7.146 +
   7.147 +for undocumented in sorted(known_set.difference(doc_set)):
   7.148 +    print >> sys.stderr, ('%s:%d: %r command not documented' %
   7.149 +                          (ltx_file, next_loc(undocumented), undocumented))
   7.150 +    print '\cmdref{%s}' % undocumented
   7.151 +    for longopt, shortopt in sorted(known[undocumented].items(), cmp=optcmp):
   7.152 +        if shortopt:
   7.153 +            print '\optref{%s}{%s}{%s}' % (undocumented, shortopt, longopt)
   7.154 +        else:
   7.155 +            print '\loptref{%s}{%s}' % (undocumented, longopt)
   7.156 +    sys.stdout.flush()
   7.157 +    errors += 1
   7.158 +
   7.159 +sys.exit(errors and 1 or 0)
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/fr/cmdref.tex	Thu Feb 05 12:37:03 2009 +0100
     8.3 @@ -0,0 +1,176 @@
     8.4 +\chapter{Command reference}
     8.5 +\label{cmdref}
     8.6 +
     8.7 +\cmdref{add}{add files at the next commit}
     8.8 +\optref{add}{I}{include}
     8.9 +\optref{add}{X}{exclude}
    8.10 +\optref{add}{n}{dry-run}
    8.11 +
    8.12 +\cmdref{diff}{print changes in history or working directory}
    8.13 +
    8.14 +Show differences between revisions for the specified files or
    8.15 +directories, using the unified diff format.  For a description of the
    8.16 +unified diff format, see section~\ref{sec:mq:patch}.
    8.17 +
    8.18 +By default, this command does not print diffs for files that Mercurial
    8.19 +considers to contain binary data.  To control this behaviour, see the
    8.20 +\hgopt{diff}{-a} and \hgopt{diff}{--git} options.
    8.21 +
    8.22 +\subsection{Options}
    8.23 +
    8.24 +\loptref{diff}{nodates}
    8.25 +
    8.26 +Omit date and time information when printing diff headers.
    8.27 +
    8.28 +\optref{diff}{B}{ignore-blank-lines}
    8.29 +
    8.30 +Do not print changes that only insert or delete blank lines.  A line
    8.31 +that contains only whitespace is not considered blank.
    8.32 +
    8.33 +\optref{diff}{I}{include}
    8.34 +
    8.35 +Include files and directories whose names match the given patterns.
    8.36 +
    8.37 +\optref{diff}{X}{exclude}
    8.38 +
    8.39 +Exclude files and directories whose names match the given patterns.
    8.40 +
    8.41 +\optref{diff}{a}{text}
    8.42 +
    8.43 +If this option is not specified, \hgcmd{diff} will refuse to print
    8.44 +diffs for files that it detects as binary. Specifying \hgopt{diff}{-a}
    8.45 +forces \hgcmd{diff} to treat all files as text, and generate diffs for
    8.46 +all of them.
    8.47 +
    8.48 +This option is useful for files that are ``mostly text'' but have a
    8.49 +few embedded NUL characters.  If you use it on files that contain a
    8.50 +lot of binary data, its output will be incomprehensible.
    8.51 +
    8.52 +\optref{diff}{b}{ignore-space-change}
    8.53 +
    8.54 +Do not print a line if the only change to that line is in the amount
    8.55 +of white space it contains.
    8.56 +
    8.57 +\optref{diff}{g}{git}
    8.58 +
    8.59 +Print \command{git}-compatible diffs.  XXX reference a format
    8.60 +description.
    8.61 +
    8.62 +\optref{diff}{p}{show-function}
    8.63 +
    8.64 +Display the name of the enclosing function in a hunk header, using a
    8.65 +simple heuristic.  This functionality is enabled by default, so the
    8.66 +\hgopt{diff}{-p} option has no effect unless you change the value of
    8.67 +the \rcitem{diff}{showfunc} config item, as in the following example.
    8.68 +\interaction{cmdref.diff-p}
    8.69 +
    8.70 +\optref{diff}{r}{rev}
    8.71 +
    8.72 +Specify one or more revisions to compare.  The \hgcmd{diff} command
    8.73 +accepts up to two \hgopt{diff}{-r} options to specify the revisions to
    8.74 +compare.
    8.75 +
    8.76 +\begin{enumerate}
    8.77 +\setcounter{enumi}{0}
    8.78 +\item Display the differences between the parent revision of the
    8.79 +  working directory and the working directory.
    8.80 +\item Display the differences between the specified changeset and the
    8.81 +  working directory.
    8.82 +\item Display the differences between the two specified changesets.
    8.83 +\end{enumerate}
    8.84 +
    8.85 +You can specify two revisions using either two \hgopt{diff}{-r}
    8.86 +options or revision range notation.  For example, the two revision
    8.87 +specifications below are equivalent.
    8.88 +\begin{codesample2}
    8.89 +  hg diff -r 10 -r 20
    8.90 +  hg diff -r10:20
    8.91 +\end{codesample2}
    8.92 +
    8.93 +When you provide two revisions, Mercurial treats the order of those
    8.94 +revisions as significant.  Thus, \hgcmdargs{diff}{-r10:20} will
    8.95 +produce a diff that will transform files from their contents as of
    8.96 +revision~10 to their contents as of revision~20, while
    8.97 +\hgcmdargs{diff}{-r20:10} means the opposite: the diff that will
    8.98 +transform files from their revision~20 contents to their revision~10
    8.99 +contents.  You cannot reverse the ordering in this way if you are
   8.100 +diffing against the working directory.
   8.101 +
   8.102 +\optref{diff}{w}{ignore-all-space}
   8.103 +
   8.104 +\cmdref{version}{print version and copyright information}
   8.105 +
   8.106 +This command displays the version of Mercurial you are running, and
   8.107 +its copyright license.  There are four kinds of version string that
   8.108 +you may see.
   8.109 +\begin{itemize}
   8.110 +\item The string ``\texttt{unknown}''. This version of Mercurial was
   8.111 +  not built in a Mercurial repository, and cannot determine its own
   8.112 +  version.
   8.113 +\item A short numeric string, such as ``\texttt{1.1}''. This is a
   8.114 +  build of a revision of Mercurial that was identified by a specific
   8.115 +  tag in the repository where it was built.  (This doesn't necessarily
   8.116 +  mean that you're running an official release; someone else could
   8.117 +  have added that tag to any revision in the repository where they
   8.118 +  built Mercurial.)
   8.119 +\item A hexadecimal string, such as ``\texttt{875489e31abe}''.  This
   8.120 +  is a build of the given revision of Mercurial.
   8.121 +\item A hexadecimal string followed by a date, such as
   8.122 +  ``\texttt{875489e31abe+20070205}''.  This is a build of the given
   8.123 +  revision of Mercurial, where the build repository contained some
   8.124 +  local changes that had not been committed.
   8.125 +\end{itemize}
   8.126 +
   8.127 +\subsection{Tips and tricks}
   8.128 +
   8.129 +\subsubsection{Why do the results of \hgcmd{diff} and \hgcmd{status}
   8.130 +  differ?}
   8.131 +\label{cmdref:diff-vs-status}
   8.132 +
   8.133 +When you run the \hgcmd{status} command, you'll see a list of files
   8.134 +that Mercurial will record changes for the next time you perform a
   8.135 +commit.  If you run the \hgcmd{diff} command, you may notice that it
   8.136 +prints diffs for only a \emph{subset} of the files that \hgcmd{status}
   8.137 +listed.  There are two possible reasons for this.
   8.138 +
   8.139 +The first is that \hgcmd{status} prints some kinds of modifications
   8.140 +that \hgcmd{diff} doesn't normally display.  The \hgcmd{diff} command
   8.141 +normally outputs unified diffs, which don't have the ability to
   8.142 +represent some changes that Mercurial can track.  Most notably,
   8.143 +traditional diffs can't represent a change in whether or not a file is
   8.144 +executable, but Mercurial records this information.
   8.145 +
   8.146 +If you use the \hgopt{diff}{--git} option to \hgcmd{diff}, it will
   8.147 +display \command{git}-compatible diffs that \emph{can} display this
   8.148 +extra information.
   8.149 +
   8.150 +The second possible reason that \hgcmd{diff} might be printing diffs
   8.151 +for a subset of the files displayed by \hgcmd{status} is that if you
   8.152 +invoke it without any arguments, \hgcmd{diff} prints diffs against the
   8.153 +first parent of the working directory.  If you have run \hgcmd{merge}
   8.154 +to merge two changesets, but you haven't yet committed the results of
   8.155 +the merge, your working directory has two parents (use \hgcmd{parents}
   8.156 +to see them).  While \hgcmd{status} prints modifications relative to
   8.157 +\emph{both} parents after an uncommitted merge, \hgcmd{diff} still
   8.158 +operates relative only to the first parent.  You can get it to print
   8.159 +diffs relative to the second parent by specifying that parent with the
   8.160 +\hgopt{diff}{-r} option.  There is no way to print diffs relative to
   8.161 +both parents.
   8.162 +
   8.163 +\subsubsection{Generating safe binary diffs}
   8.164 +
   8.165 +If you use the \hgopt{diff}{-a} option to force Mercurial to print
   8.166 +diffs of files that are either ``mostly text'' or contain lots of
   8.167 +binary data, those diffs cannot subsequently be applied by either
   8.168 +Mercurial's \hgcmd{import} command or the system's \command{patch}
   8.169 +command.  
   8.170 +
   8.171 +If you want to generate a diff of a binary file that is safe to use as
   8.172 +input for \hgcmd{import}, use the \hgcmd{diff}{--git} option when you
   8.173 +generate the patch.  The system \command{patch} command cannot handle
   8.174 +binary patches at all.
   8.175 +
   8.176 +%%% Local Variables: 
   8.177 +%%% mode: latex
   8.178 +%%% TeX-master: "00book"
   8.179 +%%% End: 
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/fr/collab.tex	Thu Feb 05 12:37:03 2009 +0100
     9.3 @@ -0,0 +1,1118 @@
     9.4 +\chapter{Collaborating with other people}
     9.5 +\label{cha:collab}
     9.6 +
     9.7 +As a completely decentralised tool, Mercurial doesn't impose any
     9.8 +policy on how people ought to work with each other.  However, if
     9.9 +you're new to distributed revision control, it helps to have some
    9.10 +tools and examples in mind when you're thinking about possible
    9.11 +workflow models.
    9.12 +
    9.13 +\section{Mercurial's web interface}
    9.14 +
    9.15 +Mercurial has a powerful web interface that provides several 
    9.16 +useful capabilities.
    9.17 +
    9.18 +For interactive use, the web interface lets you browse a single
    9.19 +repository or a collection of repositories.  You can view the history
    9.20 +of a repository, examine each change (comments and diffs), and view
    9.21 +the contents of each directory and file.
    9.22 +
    9.23 +Also for human consumption, the web interface provides an RSS feed of
    9.24 +the changes in a repository.  This lets you ``subscribe'' to a
    9.25 +repository using your favourite feed reader, and be automatically
    9.26 +notified of activity in that repository as soon as it happens.  I find
    9.27 +this capability much more convenient than the model of subscribing to
    9.28 +a mailing list to which notifications are sent, as it requires no
    9.29 +additional configuration on the part of whoever is serving the
    9.30 +repository.
    9.31 +
    9.32 +The web interface also lets remote users clone a repository, pull
    9.33 +changes from it, and (when the server is configured to permit it) push
    9.34 +changes back to it.  Mercurial's HTTP tunneling protocol aggressively
    9.35 +compresses data, so that it works efficiently even over low-bandwidth
    9.36 +network connections.
    9.37 +
    9.38 +The easiest way to get started with the web interface is to use your
    9.39 +web browser to visit an existing repository, such as the master
    9.40 +Mercurial repository at
    9.41 +\url{http://www.selenic.com/repo/hg?style=gitweb}.
    9.42 +
    9.43 +If you're interested in providing a web interface to your own
    9.44 +repositories, Mercurial provides two ways to do this.  The first is
    9.45 +using the \hgcmd{serve} command, which is best suited to short-term
    9.46 +``lightweight'' serving.  See section~\ref{sec:collab:serve} below for
    9.47 +details of how to use this command.  If you have a long-lived
    9.48 +repository that you'd like to make permanently available, Mercurial
    9.49 +has built-in support for the CGI (Common Gateway Interface) standard,
    9.50 +which all common web servers support.  See
    9.51 +section~\ref{sec:collab:cgi} for details of CGI configuration.
    9.52 +
    9.53 +\section{Collaboration models}
    9.54 +
    9.55 +With a suitably flexible tool, making decisions about workflow is much
    9.56 +more of a social engineering challenge than a technical one.
    9.57 +Mercurial imposes few limitations on how you can structure the flow of
    9.58 +work in a project, so it's up to you and your group to set up and live
    9.59 +with a model that matches your own particular needs.
    9.60 +
    9.61 +\subsection{Factors to keep in mind}
    9.62 +
    9.63 +The most important aspect of any model that you must keep in mind is
    9.64 +how well it matches the needs and capabilities of the people who will
    9.65 +be using it.  This might seem self-evident; even so, you still can't
    9.66 +afford to forget it for a moment.
    9.67 +
    9.68 +I once put together a workflow model that seemed to make perfect sense
    9.69 +to me, but that caused a considerable amount of consternation and
    9.70 +strife within my development team.  In spite of my attempts to explain
    9.71 +why we needed a complex set of branches, and how changes ought to flow
    9.72 +between them, a few team members revolted.  Even though they were
    9.73 +smart people, they didn't want to pay attention to the constraints we
    9.74 +were operating under, or face the consequences of those constraints in
    9.75 +the details of the model that I was advocating.
    9.76 +
    9.77 +Don't sweep foreseeable social or technical problems under the rug.
    9.78 +Whatever scheme you put into effect, you should plan for mistakes and
    9.79 +problem scenarios.  Consider adding automated machinery to prevent, or
    9.80 +quickly recover from, trouble that you can anticipate.  As an example,
    9.81 +if you intend to have a branch with not-for-release changes in it,
    9.82 +you'd do well to think early about the possibility that someone might
    9.83 +accidentally merge those changes into a release branch.  You could
    9.84 +avoid this particular problem by writing a hook that prevents changes
    9.85 +from being merged from an inappropriate branch.
    9.86 +
    9.87 +\subsection{Informal anarchy}
    9.88 +
    9.89 +I wouldn't suggest an ``anything goes'' approach as something
    9.90 +sustainable, but it's a model that's easy to grasp, and it works
    9.91 +perfectly well in a few unusual situations.
    9.92 +
    9.93 +As one example, many projects have a loose-knit group of collaborators
    9.94 +who rarely physically meet each other.  Some groups like to overcome
    9.95 +the isolation of working at a distance by organising occasional
    9.96 +``sprints''.  In a sprint, a number of people get together in a single
    9.97 +location (a company's conference room, a hotel meeting room, that kind
    9.98 +of place) and spend several days more or less locked in there, hacking
    9.99 +intensely on a handful of projects.
   9.100 +
   9.101 +A sprint is the perfect place to use the \hgcmd{serve} command, since
   9.102 +\hgcmd{serve} does not requires any fancy server infrastructure.  You
   9.103 +can get started with \hgcmd{serve} in moments, by reading
   9.104 +section~\ref{sec:collab:serve} below.  Then simply tell the person
   9.105 +next to you that you're running a server, send the URL to them in an
   9.106 +instant message, and you immediately have a quick-turnaround way to
   9.107 +work together.  They can type your URL into their web browser and
   9.108 +quickly review your changes; or they can pull a bugfix from you and
   9.109 +verify it; or they can clone a branch containing a new feature and try
   9.110 +it out.
   9.111 +
   9.112 +The charm, and the problem, with doing things in an ad hoc fashion
   9.113 +like this is that only people who know about your changes, and where
   9.114 +they are, can see them.  Such an informal approach simply doesn't
   9.115 +scale beyond a handful people, because each individual needs to know
   9.116 +about $n$ different repositories to pull from.
   9.117 +
   9.118 +\subsection{A single central repository}
   9.119 +
   9.120 +For smaller projects migrating from a centralised revision control
   9.121 +tool, perhaps the easiest way to get started is to have changes flow
   9.122 +through a single shared central repository.  This is also the
   9.123 +most common ``building block'' for more ambitious workflow schemes.
   9.124 +
   9.125 +Contributors start by cloning a copy of this repository.  They can
   9.126 +pull changes from it whenever they need to, and some (perhaps all)
   9.127 +developers have permission to push a change back when they're ready
   9.128 +for other people to see it.
   9.129 +
   9.130 +Under this model, it can still often make sense for people to pull
   9.131 +changes directly from each other, without going through the central
   9.132 +repository.  Consider a case in which I have a tentative bug fix, but
   9.133 +I am worried that if I were to publish it to the central repository,
   9.134 +it might subsequently break everyone else's trees as they pull it.  To
   9.135 +reduce the potential for damage, I can ask you to clone my repository
   9.136 +into a temporary repository of your own and test it.  This lets us put
   9.137 +off publishing the potentially unsafe change until it has had a little
   9.138 +testing.
   9.139 +
   9.140 +In this kind of scenario, people usually use the \command{ssh}
   9.141 +protocol to securely push changes to the central repository, as
   9.142 +documented in section~\ref{sec:collab:ssh}.  It's also usual to
   9.143 +publish a read-only copy of the repository over HTTP using CGI, as in
   9.144 +section~\ref{sec:collab:cgi}.  Publishing over HTTP satisfies the
   9.145 +needs of people who don't have push access, and those who want to use
   9.146 +web browsers to browse the repository's history.
   9.147 +
   9.148 +\subsection{Working with multiple branches}
   9.149 +
   9.150 +Projects of any significant size naturally tend to make progress on
   9.151 +several fronts simultaneously.  In the case of software, it's common
   9.152 +for a project to go through periodic official releases.  A release
   9.153 +might then go into ``maintenance mode'' for a while after its first
   9.154 +publication; maintenance releases tend to contain only bug fixes, not
   9.155 +new features.  In parallel with these maintenance releases, one or
   9.156 +more future releases may be under development.  People normally use
   9.157 +the word ``branch'' to refer to one of these many slightly different
   9.158 +directions in which development is proceeding.
   9.159 +
   9.160 +Mercurial is particularly well suited to managing a number of
   9.161 +simultaneous, but not identical, branches.  Each ``development
   9.162 +direction'' can live in its own central repository, and you can merge
   9.163 +changes from one to another as the need arises.  Because repositories
   9.164 +are independent of each other, unstable changes in a development
   9.165 +branch will never affect a stable branch unless someone explicitly
   9.166 +merges those changes in.
   9.167 +
   9.168 +Here's an example of how this can work in practice.  Let's say you
   9.169 +have one ``main branch'' on a central server.
   9.170 +\interaction{branching.init}
   9.171 +People clone it, make changes locally, test them, and push them back.
   9.172 +
   9.173 +Once the main branch reaches a release milestone, you can use the
   9.174 +\hgcmd{tag} command to give a permanent name to the milestone
   9.175 +revision.
   9.176 +\interaction{branching.tag}
   9.177 +Let's say some ongoing development occurs on the main branch.
   9.178 +\interaction{branching.main}
   9.179 +Using the tag that was recorded at the milestone, people who clone
   9.180 +that repository at any time in the future can use \hgcmd{update} to
   9.181 +get a copy of the working directory exactly as it was when that tagged
   9.182 +revision was committed.  
   9.183 +\interaction{branching.update}
   9.184 +
   9.185 +In addition, immediately after the main branch is tagged, someone can
   9.186 +then clone the main branch on the server to a new ``stable'' branch,
   9.187 +also on the server.
   9.188 +\interaction{branching.clone}
   9.189 +
   9.190 +Someone who needs to make a change to the stable branch can then clone
   9.191 +\emph{that} repository, make their changes, commit, and push their
   9.192 +changes back there.
   9.193 +\interaction{branching.stable}
   9.194 +Because Mercurial repositories are independent, and Mercurial doesn't
   9.195 +move changes around automatically, the stable and main branches are
   9.196 +\emph{isolated} from each other.  The changes that you made on the
   9.197 +main branch don't ``leak'' to the stable branch, and vice versa.
   9.198 +
   9.199 +You'll often want all of your bugfixes on the stable branch to show up
   9.200 +on the main branch, too.  Rather than rewrite a bugfix on the main
   9.201 +branch, you can simply pull and merge changes from the stable to the
   9.202 +main branch, and Mercurial will bring those bugfixes in for you.
   9.203 +\interaction{branching.merge}
   9.204 +The main branch will still contain changes that are not on the stable
   9.205 +branch, but it will also contain all of the bugfixes from the stable
   9.206 +branch.  The stable branch remains unaffected by these changes.
   9.207 +
   9.208 +\subsection{Feature branches}
   9.209 +
   9.210 +For larger projects, an effective way to manage change is to break up
   9.211 +a team into smaller groups.  Each group has a shared branch of its
   9.212 +own, cloned from a single ``master'' branch used by the entire
   9.213 +project.  People working on an individual branch are typically quite
   9.214 +isolated from developments on other branches.
   9.215 +
   9.216 +\begin{figure}[ht]
   9.217 +  \centering
   9.218 +  \grafix{feature-branches}
   9.219 +  \caption{Feature branches}
   9.220 +  \label{fig:collab:feature-branches}
   9.221 +\end{figure}
   9.222 +
   9.223 +When a particular feature is deemed to be in suitable shape, someone
   9.224 +on that feature team pulls and merges from the master branch into the
   9.225 +feature branch, then pushes back up to the master branch.
   9.226 +
   9.227 +\subsection{The release train}
   9.228 +
   9.229 +Some projects are organised on a ``train'' basis: a release is
   9.230 +scheduled to happen every few months, and whatever features are ready
   9.231 +when the ``train'' is ready to leave are allowed in.
   9.232 +
   9.233 +This model resembles working with feature branches.  The difference is
   9.234 +that when a feature branch misses a train, someone on the feature team
   9.235 +pulls and merges the changes that went out on that train release into
   9.236 +the feature branch, and the team continues its work on top of that
   9.237 +release so that their feature can make the next release.
   9.238 +
   9.239 +\subsection{The Linux kernel model}
   9.240 +
   9.241 +The development of the Linux kernel has a shallow hierarchical
   9.242 +structure, surrounded by a cloud of apparent chaos.  Because most
   9.243 +Linux developers use \command{git}, a distributed revision control
   9.244 +tool with capabilities similar to Mercurial, it's useful to describe
   9.245 +the way work flows in that environment; if you like the ideas, the
   9.246 +approach translates well across tools.
   9.247 +
   9.248 +At the center of the community sits Linus Torvalds, the creator of
   9.249 +Linux.  He publishes a single source repository that is considered the
   9.250 +``authoritative'' current tree by the entire developer community.
   9.251 +Anyone can clone Linus's tree, but he is very choosy about whose trees
   9.252 +he pulls from.
   9.253 +
   9.254 +Linus has a number of ``trusted lieutenants''.  As a general rule, he
   9.255 +pulls whatever changes they publish, in most cases without even
   9.256 +reviewing those changes.  Some of those lieutenants are generally
   9.257 +agreed to be ``maintainers'', responsible for specific subsystems
   9.258 +within the kernel.  If a random kernel hacker wants to make a change
   9.259 +to a subsystem that they want to end up in Linus's tree, they must
   9.260 +find out who the subsystem's maintainer is, and ask that maintainer to
   9.261 +take their change.  If the maintainer reviews their changes and agrees
   9.262 +to take them, they'll pass them along to Linus in due course.
   9.263 +
   9.264 +Individual lieutenants have their own approaches to reviewing,
   9.265 +accepting, and publishing changes; and for deciding when to feed them
   9.266 +to Linus.  In addition, there are several well known branches that
   9.267 +people use for different purposes.  For example, a few people maintain
   9.268 +``stable'' repositories of older versions of the kernel, to which they
   9.269 +apply critical fixes as needed.  Some maintainers publish multiple
   9.270 +trees: one for experimental changes; one for changes that they are
   9.271 +about to feed upstream; and so on.  Others just publish a single
   9.272 +tree.
   9.273 +
   9.274 +This model has two notable features.  The first is that it's ``pull
   9.275 +only''.  You have to ask, convince, or beg another developer to take a
   9.276 +change from you, because there are almost no trees to which more than
   9.277 +one person can push, and there's no way to push changes into a tree
   9.278 +that someone else controls.
   9.279 +
   9.280 +The second is that it's based on reputation and acclaim.  If you're an
   9.281 +unknown, Linus will probably ignore changes from you without even
   9.282 +responding.  But a subsystem maintainer will probably review them, and
   9.283 +will likely take them if they pass their criteria for suitability.
   9.284 +The more ``good'' changes you contribute to a maintainer, the more
   9.285 +likely they are to trust your judgment and accept your changes.  If
   9.286 +you're well-known and maintain a long-lived branch for something Linus
   9.287 +hasn't yet accepted, people with similar interests may pull your
   9.288 +changes regularly to keep up with your work.
   9.289 +
   9.290 +Reputation and acclaim don't necessarily cross subsystem or ``people''
   9.291 +boundaries.  If you're a respected but specialised storage hacker, and
   9.292 +you try to fix a networking bug, that change will receive a level of
   9.293 +scrutiny from a network maintainer comparable to a change from a
   9.294 +complete stranger.
   9.295 +
   9.296 +To people who come from more orderly project backgrounds, the
   9.297 +comparatively chaotic Linux kernel development process often seems
   9.298 +completely insane.  It's subject to the whims of individuals; people
   9.299 +make sweeping changes whenever they deem it appropriate; and the pace
   9.300 +of development is astounding.  And yet Linux is a highly successful,
   9.301 +well-regarded piece of software.
   9.302 +
   9.303 +\subsection{Pull-only versus shared-push collaboration}
   9.304 +
   9.305 +A perpetual source of heat in the open source community is whether a
   9.306 +development model in which people only ever pull changes from others
   9.307 +is ``better than'' one in which multiple people can push changes to a
   9.308 +shared repository.
   9.309 +
   9.310 +Typically, the backers of the shared-push model use tools that
   9.311 +actively enforce this approach.  If you're using a centralised
   9.312 +revision control tool such as Subversion, there's no way to make a
   9.313 +choice over which model you'll use: the tool gives you shared-push,
   9.314 +and if you want to do anything else, you'll have to roll your own
   9.315 +approach on top (such as applying a patch by hand).
   9.316 +
   9.317 +A good distributed revision control tool, such as Mercurial, will
   9.318 +support both models.  You and your collaborators can then structure
   9.319 +how you work together based on your own needs and preferences, not on
   9.320 +what contortions your tools force you into.
   9.321 +
   9.322 +\subsection{Where collaboration meets branch management}
   9.323 +
   9.324 +Once you and your team set up some shared repositories and start
   9.325 +propagating changes back and forth between local and shared repos, you
   9.326 +begin to face a related, but slightly different challenge: that of
   9.327 +managing the multiple directions in which your team may be moving at
   9.328 +once.  Even though this subject is intimately related to how your team
   9.329 +collaborates, it's dense enough to merit treatment of its own, in
   9.330 +chapter~\ref{chap:branch}.
   9.331 +
   9.332 +\section{The technical side of sharing}
   9.333 +
   9.334 +The remainder of this chapter is devoted to the question of serving
   9.335 +data to your collaborators.
   9.336 +
   9.337 +\section{Informal sharing with \hgcmd{serve}}
   9.338 +\label{sec:collab:serve}
   9.339 +
   9.340 +Mercurial's \hgcmd{serve} command is wonderfully suited to small,
   9.341 +tight-knit, and fast-paced group environments.  It also provides a
   9.342 +great way to get a feel for using Mercurial commands over a network.
   9.343 +
   9.344 +Run \hgcmd{serve} inside a repository, and in under a second it will
   9.345 +bring up a specialised HTTP server; this will accept connections from
   9.346 +any client, and serve up data for that repository until you terminate
   9.347 +it.  Anyone who knows the URL of the server you just started, and can
   9.348 +talk to your computer over the network, can then use a web browser or
   9.349 +Mercurial to read data from that repository.  A URL for a
   9.350 +\hgcmd{serve} instance running on a laptop is likely to look something
   9.351 +like \Verb|http://my-laptop.local:8000/|.
   9.352 +
   9.353 +The \hgcmd{serve} command is \emph{not} a general-purpose web server.
   9.354 +It can do only two things:
   9.355 +\begin{itemize}
   9.356 +\item Allow people to browse the history of the repository it's
   9.357 +  serving, from their normal web browsers.
   9.358 +\item Speak Mercurial's wire protocol, so that people can
   9.359 +  \hgcmd{clone} or \hgcmd{pull} changes from that repository.
   9.360 +\end{itemize}
   9.361 +In particular, \hgcmd{serve} won't allow remote users to \emph{modify}
   9.362 +your repository.  It's intended for read-only use.
   9.363 +
   9.364 +If you're getting started with Mercurial, there's nothing to prevent
   9.365 +you from using \hgcmd{serve} to serve up a repository on your own
   9.366 +computer, then use commands like \hgcmd{clone}, \hgcmd{incoming}, and
   9.367 +so on to talk to that server as if the repository was hosted remotely.
   9.368 +This can help you to quickly get acquainted with using commands on
   9.369 +network-hosted repositories.
   9.370 +
   9.371 +\subsection{A few things to keep in mind}
   9.372 +
   9.373 +Because it provides unauthenticated read access to all clients, you
   9.374 +should only use \hgcmd{serve} in an environment where you either don't
   9.375 +care, or have complete control over, who can access your network and
   9.376 +pull data from your repository.
   9.377 +
   9.378 +The \hgcmd{serve} command knows nothing about any firewall software
   9.379 +you might have installed on your system or network.  It cannot detect
   9.380 +or control your firewall software.  If other people are unable to talk
   9.381 +to a running \hgcmd{serve} instance, the second thing you should do
   9.382 +(\emph{after} you make sure that they're using the correct URL) is
   9.383 +check your firewall configuration.
   9.384 +
   9.385 +By default, \hgcmd{serve} listens for incoming connections on
   9.386 +port~8000.  If another process is already listening on the port you
   9.387 +want to use, you can specify a different port to listen on using the
   9.388 +\hgopt{serve}{-p} option.
   9.389 +
   9.390 +Normally, when \hgcmd{serve} starts, it prints no output, which can be
   9.391 +a bit unnerving.  If you'd like to confirm that it is indeed running
   9.392 +correctly, and find out what URL you should send to your
   9.393 +collaborators, start it with the \hggopt{-v} option.
   9.394 +
   9.395 +\section{Using the Secure Shell (ssh) protocol}
   9.396 +\label{sec:collab:ssh}
   9.397 +
   9.398 +You can pull and push changes securely over a network connection using
   9.399 +the Secure Shell (\texttt{ssh}) protocol.  To use this successfully,
   9.400 +you may have to do a little bit of configuration on the client or
   9.401 +server sides.
   9.402 +
   9.403 +If you're not familiar with ssh, it's a network protocol that lets you
   9.404 +securely communicate with another computer.  To use it with Mercurial,
   9.405 +you'll be setting up one or more user accounts on a server so that
   9.406 +remote users can log in and execute commands.
   9.407 +
   9.408 +(If you \emph{are} familiar with ssh, you'll probably find some of the
   9.409 +material that follows to be elementary in nature.)
   9.410 +
   9.411 +\subsection{How to read and write ssh URLs}
   9.412 +
   9.413 +An ssh URL tends to look like this:
   9.414 +\begin{codesample2}
   9.415 +  ssh://bos@hg.serpentine.com:22/hg/hgbook
   9.416 +\end{codesample2}
   9.417 +\begin{enumerate}
   9.418 +\item The ``\texttt{ssh://}'' part tells Mercurial to use the ssh
   9.419 +  protocol.
   9.420 +\item The ``\texttt{bos@}'' component indicates what username to log
   9.421 +  into the server as.  You can leave this out if the remote username
   9.422 +  is the same as your local username.
   9.423 +\item The ``\texttt{hg.serpentine.com}'' gives the hostname of the
   9.424 +  server to log into.
   9.425 +\item The ``:22'' identifies the port number to connect to the server
   9.426 +  on.  The default port is~22, so you only need to specify this part
   9.427 +  if you're \emph{not} using port~22.
   9.428 +\item The remainder of the URL is the local path to the repository on
   9.429 +  the server.
   9.430 +\end{enumerate}
   9.431 +
   9.432 +There's plenty of scope for confusion with the path component of ssh
   9.433 +URLs, as there is no standard way for tools to interpret it.  Some
   9.434 +programs behave differently than others when dealing with these paths.
   9.435 +This isn't an ideal situation, but it's unlikely to change.  Please
   9.436 +read the following paragraphs carefully.
   9.437 +
   9.438 +Mercurial treats the path to a repository on the server as relative to
   9.439 +the remote user's home directory.  For example, if user \texttt{foo}
   9.440 +on the server has a home directory of \dirname{/home/foo}, then an ssh
   9.441 +URL that contains a path component of \dirname{bar}
   9.442 +\emph{really} refers to the directory \dirname{/home/foo/bar}.
   9.443 +
   9.444 +If you want to specify a path relative to another user's home
   9.445 +directory, you can use a path that starts with a tilde character
   9.446 +followed by the user's name (let's call them \texttt{otheruser}), like
   9.447 +this.
   9.448 +\begin{codesample2}
   9.449 +  ssh://server/~otheruser/hg/repo
   9.450 +\end{codesample2}
   9.451 +
   9.452 +And if you really want to specify an \emph{absolute} path on the
   9.453 +server, begin the path component with two slashes, as in this example.
   9.454 +\begin{codesample2}
   9.455 +  ssh://server//absolute/path
   9.456 +\end{codesample2}
   9.457 +
   9.458 +\subsection{Finding an ssh client for your system}
   9.459 +
   9.460 +Almost every Unix-like system comes with OpenSSH preinstalled.  If
   9.461 +you're using such a system, run \Verb|which ssh| to find out if
   9.462 +the \command{ssh} command is installed (it's usually in
   9.463 +\dirname{/usr/bin}).  In the unlikely event that it isn't present,
   9.464 +take a look at your system documentation to figure out how to install
   9.465 +it.
   9.466 +
   9.467 +On Windows, you'll first need to download a suitable ssh
   9.468 +client.  There are two alternatives.
   9.469 +\begin{itemize}
   9.470 +\item Simon Tatham's excellent PuTTY package~\cite{web:putty} provides
   9.471 +  a complete suite of ssh client commands.
   9.472 +\item If you have a high tolerance for pain, you can use the Cygwin
   9.473 +  port of OpenSSH.
   9.474 +\end{itemize}
   9.475 +In either case, you'll need to edit your \hgini\ file to tell
   9.476 +Mercurial where to find the actual client command.  For example, if
   9.477 +you're using PuTTY, you'll need to use the \command{plink} command as
   9.478 +a command-line ssh client.
   9.479 +\begin{codesample2}
   9.480 +  [ui]
   9.481 +  ssh = C:/path/to/plink.exe -ssh -i "C:/path/to/my/private/key"
   9.482 +\end{codesample2}
   9.483 +
   9.484 +\begin{note}
   9.485 +  The path to \command{plink} shouldn't contain any whitespace
   9.486 +  characters, or Mercurial may not be able to run it correctly (so
   9.487 +  putting it in \dirname{C:\\Program Files} is probably not a good
   9.488 +  idea).
   9.489 +\end{note}
   9.490 +
   9.491 +\subsection{Generating a key pair}
   9.492 +
   9.493 +To avoid the need to repetitively type a password every time you need
   9.494 +to use your ssh client, I recommend generating a key pair.  On a
   9.495 +Unix-like system, the \command{ssh-keygen} command will do the trick.
   9.496 +On Windows, if you're using PuTTY, the \command{puttygen} command is
   9.497 +what you'll need.
   9.498 +
   9.499 +When you generate a key pair, it's usually \emph{highly} advisable to
   9.500 +protect it with a passphrase.  (The only time that you might not want
   9.501 +to do this is when you're using the ssh protocol for automated tasks
   9.502 +on a secure network.)
   9.503 +
   9.504 +Simply generating a key pair isn't enough, however.  You'll need to
   9.505 +add the public key to the set of authorised keys for whatever user
   9.506 +you're logging in remotely as.  For servers using OpenSSH (the vast
   9.507 +majority), this will mean adding the public key to a list in a file
   9.508 +called \sfilename{authorized\_keys} in their \sdirname{.ssh}
   9.509 +directory.
   9.510 +
   9.511 +On a Unix-like system, your public key will have a \filename{.pub}
   9.512 +extension.  If you're using \command{puttygen} on Windows, you can
   9.513 +save the public key to a file of your choosing, or paste it from the
   9.514 +window it's displayed in straight into the
   9.515 +\sfilename{authorized\_keys} file.
   9.516 +
   9.517 +\subsection{Using an authentication agent}
   9.518 +
   9.519 +An authentication agent is a daemon that stores passphrases in memory
   9.520 +(so it will forget passphrases if you log out and log back in again).
   9.521 +An ssh client will notice if it's running, and query it for a
   9.522 +passphrase.  If there's no authentication agent running, or the agent
   9.523 +doesn't store the necessary passphrase, you'll have to type your
   9.524 +passphrase every time Mercurial tries to communicate with a server on
   9.525 +your behalf (e.g.~whenever you pull or push changes).
   9.526 +
   9.527 +The downside of storing passphrases in an agent is that it's possible
   9.528 +for a well-prepared attacker to recover the plain text of your
   9.529 +passphrases, in some cases even if your system has been power-cycled.
   9.530 +You should make your own judgment as to whether this is an acceptable
   9.531 +risk.  It certainly saves a lot of repeated typing.
   9.532 +
   9.533 +On Unix-like systems, the agent is called \command{ssh-agent}, and
   9.534 +it's often run automatically for you when you log in.  You'll need to
   9.535 +use the \command{ssh-add} command to add passphrases to the agent's
   9.536 +store.  On Windows, if you're using PuTTY, the \command{pageant}
   9.537 +command acts as the agent.  It adds an icon to your system tray that
   9.538 +will let you manage stored passphrases.
   9.539 +
   9.540 +\subsection{Configuring the server side properly}
   9.541 +
   9.542 +Because ssh can be fiddly to set up if you're new to it, there's a
   9.543 +variety of things that can go wrong.  Add Mercurial on top, and
   9.544 +there's plenty more scope for head-scratching.  Most of these
   9.545 +potential problems occur on the server side, not the client side.  The
   9.546 +good news is that once you've gotten a configuration working, it will
   9.547 +usually continue to work indefinitely.
   9.548 +
   9.549 +Before you try using Mercurial to talk to an ssh server, it's best to
   9.550 +make sure that you can use the normal \command{ssh} or \command{putty}
   9.551 +command to talk to the server first.  If you run into problems with
   9.552 +using these commands directly, Mercurial surely won't work.  Worse, it
   9.553 +will obscure the underlying problem.  Any time you want to debug
   9.554 +ssh-related Mercurial problems, you should drop back to making sure
   9.555 +that plain ssh client commands work first, \emph{before} you worry
   9.556 +about whether there's a problem with Mercurial.
   9.557 +
   9.558 +The first thing to be sure of on the server side is that you can
   9.559 +actually log in from another machine at all.  If you can't use
   9.560 +\command{ssh} or \command{putty} to log in, the error message you get
   9.561 +may give you a few hints as to what's wrong.  The most common problems
   9.562 +are as follows.
   9.563 +\begin{itemize}
   9.564 +\item If you get a ``connection refused'' error, either there isn't an
   9.565 +  SSH daemon running on the server at all, or it's inaccessible due to
   9.566 +  firewall configuration.
   9.567 +\item If you get a ``no route to host'' error, you either have an
   9.568 +  incorrect address for the server or a seriously locked down firewall
   9.569 +  that won't admit its existence at all.
   9.570 +\item If you get a ``permission denied'' error, you may have mistyped
   9.571 +  the username on the server, or you could have mistyped your key's
   9.572 +  passphrase or the remote user's password.
   9.573 +\end{itemize}
   9.574 +In summary, if you're having trouble talking to the server's ssh
   9.575 +daemon, first make sure that one is running at all.  On many systems
   9.576 +it will be installed, but disabled, by default.  Once you're done with
   9.577 +this step, you should then check that the server's firewall is
   9.578 +configured to allow incoming connections on the port the ssh daemon is
   9.579 +listening on (usually~22).  Don't worry about more exotic
   9.580 +possibilities for misconfiguration until you've checked these two
   9.581 +first.
   9.582 +
   9.583 +If you're using an authentication agent on the client side to store
   9.584 +passphrases for your keys, you ought to be able to log into the server
   9.585 +without being prompted for a passphrase or a password.  If you're
   9.586 +prompted for a passphrase, there are a few possible culprits.
   9.587 +\begin{itemize}
   9.588 +\item You might have forgotten to use \command{ssh-add} or
   9.589 +  \command{pageant} to store the passphrase.
   9.590 +\item You might have stored the passphrase for the wrong key.
   9.591 +\end{itemize}
   9.592 +If you're being prompted for the remote user's password, there are
   9.593 +another few possible problems to check.
   9.594 +\begin{itemize}
   9.595 +\item Either the user's home directory or their \sdirname{.ssh}
   9.596 +  directory might have excessively liberal permissions.  As a result,
   9.597 +  the ssh daemon will not trust or read their
   9.598 +  \sfilename{authorized\_keys} file.  For example, a group-writable
   9.599 +  home or \sdirname{.ssh} directory will often cause this symptom.
   9.600 +\item The user's \sfilename{authorized\_keys} file may have a problem.
   9.601 +  If anyone other than the user owns or can write to that file, the
   9.602 +  ssh daemon will not trust or read it.
   9.603 +\end{itemize}
   9.604 +
   9.605 +In the ideal world, you should be able to run the following command
   9.606 +successfully, and it should print exactly one line of output, the
   9.607 +current date and time.
   9.608 +\begin{codesample2}
   9.609 +  ssh myserver date
   9.610 +\end{codesample2}
   9.611 +
   9.612 +If, on your server, you have login scripts that print banners or other
   9.613 +junk even when running non-interactive commands like this, you should
   9.614 +fix them before you continue, so that they only print output if
   9.615 +they're run interactively.  Otherwise these banners will at least
   9.616 +clutter up Mercurial's output.  Worse, they could potentially cause
   9.617 +problems with running Mercurial commands remotely.  Mercurial makes
   9.618 +tries to detect and ignore banners in non-interactive \command{ssh}
   9.619 +sessions, but it is not foolproof.  (If you're editing your login
   9.620 +scripts on your server, the usual way to see if a login script is
   9.621 +running in an interactive shell is to check the return code from the
   9.622 +command \Verb|tty -s|.)
   9.623 +
   9.624 +Once you've verified that plain old ssh is working with your server,
   9.625 +the next step is to ensure that Mercurial runs on the server.  The
   9.626 +following command should run successfully:
   9.627 +\begin{codesample2}
   9.628 +  ssh myserver hg version
   9.629 +\end{codesample2}
   9.630 +If you see an error message instead of normal \hgcmd{version} output,
   9.631 +this is usually because you haven't installed Mercurial to
   9.632 +\dirname{/usr/bin}.  Don't worry if this is the case; you don't need
   9.633 +to do that.  But you should check for a few possible problems.
   9.634 +\begin{itemize}
   9.635 +\item Is Mercurial really installed on the server at all?  I know this
   9.636 +  sounds trivial, but it's worth checking!
   9.637 +\item Maybe your shell's search path (usually set via the \envar{PATH}
   9.638 +  environment variable) is simply misconfigured.
   9.639 +\item Perhaps your \envar{PATH} environment variable is only being set
   9.640 +  to point to the location of the \command{hg} executable if the login
   9.641 +  session is interactive.  This can happen if you're setting the path
   9.642 +  in the wrong shell login script.  See your shell's documentation for
   9.643 +  details.
   9.644 +\item The \envar{PYTHONPATH} environment variable may need to contain
   9.645 +  the path to the Mercurial Python modules.  It might not be set at
   9.646 +  all; it could be incorrect; or it may be set only if the login is
   9.647 +  interactive.
   9.648 +\end{itemize}
   9.649 +
   9.650 +If you can run \hgcmd{version} over an ssh connection, well done!
   9.651 +You've got the server and client sorted out.  You should now be able
   9.652 +to use Mercurial to access repositories hosted by that username on
   9.653 +that server.  If you run into problems with Mercurial and ssh at this
   9.654 +point, try using the \hggopt{--debug} option to get a clearer picture
   9.655 +of what's going on.
   9.656 +
   9.657 +\subsection{Using compression with ssh}
   9.658 +
   9.659 +Mercurial does not compress data when it uses the ssh protocol,
   9.660 +because the ssh protocol can transparently compress data.  However,
   9.661 +the default behaviour of ssh clients is \emph{not} to request
   9.662 +compression.
   9.663 +
   9.664 +Over any network other than a fast LAN (even a wireless network),
   9.665 +using compression is likely to significantly speed up Mercurial's
   9.666 +network operations.  For example, over a WAN, someone measured
   9.667 +compression as reducing the amount of time required to clone a
   9.668 +particularly large repository from~51 minutes to~17 minutes.
   9.669 +
   9.670 +Both \command{ssh} and \command{plink} accept a \cmdopt{ssh}{-C}
   9.671 +option which turns on compression.  You can easily edit your \hgrc\ to
   9.672 +enable compression for all of Mercurial's uses of the ssh protocol.
   9.673 +\begin{codesample2}
   9.674 +  [ui]
   9.675 +  ssh = ssh -C
   9.676 +\end{codesample2}
   9.677 +
   9.678 +If you use \command{ssh}, you can configure it to always use
   9.679 +compression when talking to your server.  To do this, edit your
   9.680 +\sfilename{.ssh/config} file (which may not yet exist), as follows.
   9.681 +\begin{codesample2}
   9.682 +  Host hg
   9.683 +    Compression yes
   9.684 +    HostName hg.example.com
   9.685 +\end{codesample2}
   9.686 +This defines an alias, \texttt{hg}.  When you use it on the
   9.687 +\command{ssh} command line or in a Mercurial \texttt{ssh}-protocol
   9.688 +URL, it will cause \command{ssh} to connect to \texttt{hg.example.com}
   9.689 +and use compression.  This gives you both a shorter name to type and
   9.690 +compression, each of which is a good thing in its own right.
   9.691 +
   9.692 +\section{Serving over HTTP using CGI}
   9.693 +\label{sec:collab:cgi}
   9.694 +
   9.695 +Depending on how ambitious you are, configuring Mercurial's CGI
   9.696 +interface can take anything from a few moments to several hours.
   9.697 +
   9.698 +We'll begin with the simplest of examples, and work our way towards a
   9.699 +more complex configuration.  Even for the most basic case, you're
   9.700 +almost certainly going to need to read and modify your web server's
   9.701 +configuration.
   9.702 +
   9.703 +\begin{note}
   9.704 +  Configuring a web server is a complex, fiddly, and highly
   9.705 +  system-dependent activity.  I can't possibly give you instructions
   9.706 +  that will cover anything like all of the cases you will encounter.
   9.707 +  Please use your discretion and judgment in following the sections
   9.708 +  below.  Be prepared to make plenty of mistakes, and to spend a lot
   9.709 +  of time reading your server's error logs.
   9.710 +\end{note}
   9.711 +
   9.712 +\subsection{Web server configuration checklist}
   9.713 +
   9.714 +Before you continue, do take a few moments to check a few aspects of
   9.715 +your system's setup.
   9.716 +
   9.717 +\begin{enumerate}
   9.718 +\item Do you have a web server installed at all?  Mac OS X ships with
   9.719 +  Apache, but many other systems may not have a web server installed.
   9.720 +\item If you have a web server installed, is it actually running?  On
   9.721 +  most systems, even if one is present, it will be disabled by
   9.722 +  default.
   9.723 +\item Is your server configured to allow you to run CGI programs in
   9.724 +  the directory where you plan to do so?  Most servers default to
   9.725 +  explicitly disabling the ability to run CGI programs.
   9.726 +\end{enumerate}
   9.727 +
   9.728 +If you don't have a web server installed, and don't have substantial
   9.729 +experience configuring Apache, you should consider using the
   9.730 +\texttt{lighttpd} web server instead of Apache.  Apache has a
   9.731 +well-deserved reputation for baroque and confusing configuration.
   9.732 +While \texttt{lighttpd} is less capable in some ways than Apache, most
   9.733 +of these capabilities are not relevant to serving Mercurial
   9.734 +repositories.  And \texttt{lighttpd} is undeniably \emph{much} easier
   9.735 +to get started with than Apache.
   9.736 +
   9.737 +\subsection{Basic CGI configuration}
   9.738 +
   9.739 +On Unix-like systems, it's common for users to have a subdirectory
   9.740 +named something like \dirname{public\_html} in their home directory,
   9.741 +from which they can serve up web pages.  A file named \filename{foo}
   9.742 +in this directory will be accessible at a URL of the form
   9.743 +\texttt{http://www.example.com/\~{}username/foo}.
   9.744 +
   9.745 +To get started, find the \sfilename{hgweb.cgi} script that should be
   9.746 +present in your Mercurial installation.  If you can't quickly find a
   9.747 +local copy on your system, simply download one from the master
   9.748 +Mercurial repository at
   9.749 +\url{http://www.selenic.com/repo/hg/raw-file/tip/hgweb.cgi}.
   9.750 +
   9.751 +You'll need to copy this script into your \dirname{public\_html}
   9.752 +directory, and ensure that it's executable.
   9.753 +\begin{codesample2}
   9.754 +  cp .../hgweb.cgi ~/public_html
   9.755 +  chmod 755 ~/public_html/hgweb.cgi
   9.756 +\end{codesample2}
   9.757 +The \texttt{755} argument to \command{chmod} is a little more general
   9.758 +than just making the script executable: it ensures that the script is
   9.759 +executable by anyone, and that ``group'' and ``other'' write
   9.760 +permissions are \emph{not} set.  If you were to leave those write
   9.761 +permissions enabled, Apache's \texttt{suexec} subsystem would likely
   9.762 +refuse to execute the script.  In fact, \texttt{suexec} also insists
   9.763 +that the \emph{directory} in which the script resides must not be
   9.764 +writable by others.
   9.765 +\begin{codesample2}
   9.766 +  chmod 755 ~/public_html
   9.767 +\end{codesample2}
   9.768 +
   9.769 +\subsubsection{What could \emph{possibly} go wrong?}
   9.770 +\label{sec:collab:wtf}
   9.771 +
   9.772 +Once you've copied the CGI script into place, go into a web browser,
   9.773 +and try to open the URL \url{http://myhostname/~myuser/hgweb.cgi},
   9.774 +\emph{but} brace yourself for instant failure.  There's a high
   9.775 +probability that trying to visit this URL will fail, and there are
   9.776 +many possible reasons for this.  In fact, you're likely to stumble
   9.777 +over almost every one of the possible errors below, so please read
   9.778 +carefully.  The following are all of the problems I ran into on a
   9.779 +system running Fedora~7, with a fresh installation of Apache, and a
   9.780 +user account that I created specially to perform this exercise.
   9.781 +
   9.782 +Your web server may have per-user directories disabled.  If you're
   9.783 +using Apache, search your config file for a \texttt{UserDir}
   9.784 +directive.  If there's none present, per-user directories will be
   9.785 +disabled.  If one exists, but its value is \texttt{disabled}, then
   9.786 +per-user directories will be disabled.  Otherwise, the string after
   9.787 +\texttt{UserDir} gives the name of the subdirectory that Apache will
   9.788 +look in under your home directory, for example \dirname{public\_html}.
   9.789 +
   9.790 +Your file access permissions may be too restrictive.  The web server
   9.791 +must be able to traverse your home directory and directories under
   9.792 +your \dirname{public\_html} directory, and read files under the latter
   9.793 +too.  Here's a quick recipe to help you to make your permissions more
   9.794 +appropriate.
   9.795 +\begin{codesample2}
   9.796 +  chmod 755 ~
   9.797 +  find ~/public_html -type d -print0 | xargs -0r chmod 755
   9.798 +  find ~/public_html -type f -print0 | xargs -0r chmod 644
   9.799 +\end{codesample2}
   9.800 +
   9.801 +The other possibility with permissions is that you might get a
   9.802 +completely empty window when you try to load the script.  In this
   9.803 +case, it's likely that your access permissions are \emph{too
   9.804 +  permissive}.  Apache's \texttt{suexec} subsystem won't execute a
   9.805 +script that's group-~or world-writable, for example.
   9.806 +
   9.807 +Your web server may be configured to disallow execution of CGI
   9.808 +programs in your per-user web directory.  Here's Apache's
   9.809 +default per-user configuration from my Fedora system.
   9.810 +\begin{codesample2}
   9.811 +  <Directory /home/*/public_html>
   9.812 +      AllowOverride FileInfo AuthConfig Limit
   9.813 +      Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
   9.814 +      <Limit GET POST OPTIONS>
   9.815 +          Order allow,deny
   9.816 +          Allow from all
   9.817 +      </Limit>
   9.818 +      <LimitExcept GET POST OPTIONS>
   9.819 +          Order deny,allow
   9.820 +          Deny from all
   9.821 +      </LimitExcept>
   9.822 +  </Directory>
   9.823 +\end{codesample2}
   9.824 +If you find a similar-looking \texttt{Directory} group in your Apache
   9.825 +configuration, the directive to look at inside it is \texttt{Options}.
   9.826 +Add \texttt{ExecCGI} to the end of this list if it's missing, and
   9.827 +restart the web server.
   9.828 +
   9.829 +If you find that Apache serves you the text of the CGI script instead
   9.830 +of executing it, you may need to either uncomment (if already present)
   9.831 +or add a directive like this.
   9.832 +\begin{codesample2}
   9.833 +  AddHandler cgi-script .cgi
   9.834 +\end{codesample2}
   9.835 +
   9.836 +The next possibility is that you might be served with a colourful
   9.837 +Python backtrace claiming that it can't import a
   9.838 +\texttt{mercurial}-related module.  This is actually progress!  The
   9.839 +server is now capable of executing your CGI script.  This error is
   9.840 +only likely to occur if you're running a private installation of
   9.841 +Mercurial, instead of a system-wide version.  Remember that the web
   9.842 +server runs the CGI program without any of the environment variables
   9.843 +that you take for granted in an interactive session.  If this error
   9.844 +happens to you, edit your copy of \sfilename{hgweb.cgi} and follow the
   9.845 +directions inside it to correctly set your \envar{PYTHONPATH}
   9.846 +environment variable.
   9.847 +
   9.848 +Finally, you are \emph{certain} to by served with another colourful
   9.849 +Python backtrace: this one will complain that it can't find
   9.850 +\dirname{/path/to/repository}.  Edit your \sfilename{hgweb.cgi} script
   9.851 +and replace the \dirname{/path/to/repository} string with the complete
   9.852 +path to the repository you want to serve up.
   9.853 +
   9.854 +At this point, when you try to reload the page, you should be
   9.855 +presented with a nice HTML view of your repository's history.  Whew!
   9.856 +
   9.857 +\subsubsection{Configuring lighttpd}
   9.858 +
   9.859 +To be exhaustive in my experiments, I tried configuring the
   9.860 +increasingly popular \texttt{lighttpd} web server to serve the same
   9.861 +repository as I described with Apache above.  I had already overcome
   9.862 +all of the problems I outlined with Apache, many of which are not
   9.863 +server-specific.  As a result, I was fairly sure that my file and
   9.864 +directory permissions were good, and that my \sfilename{hgweb.cgi}
   9.865 +script was properly edited.
   9.866 +
   9.867 +Once I had Apache running, getting \texttt{lighttpd} to serve the
   9.868 +repository was a snap (in other words, even if you're trying to use
   9.869 +\texttt{lighttpd}, you should read the Apache section).  I first had
   9.870 +to edit the \texttt{mod\_access} section of its config file to enable
   9.871 +\texttt{mod\_cgi} and \texttt{mod\_userdir}, both of which were
   9.872 +disabled by default on my system.  I then added a few lines to the end
   9.873 +of the config file, to configure these modules.
   9.874 +\begin{codesample2}
   9.875 +  userdir.path = "public_html"
   9.876 +  cgi.assign = ( ".cgi" => "" )
   9.877 +\end{codesample2}
   9.878 +With this done, \texttt{lighttpd} ran immediately for me.  If I had
   9.879 +configured \texttt{lighttpd} before Apache, I'd almost certainly have
   9.880 +run into many of the same system-level configuration problems as I did
   9.881 +with Apache.  However, I found \texttt{lighttpd} to be noticeably
   9.882 +easier to configure than Apache, even though I've used Apache for over
   9.883 +a decade, and this was my first exposure to \texttt{lighttpd}.
   9.884 +
   9.885 +\subsection{Sharing multiple repositories with one CGI script}
   9.886 +
   9.887 +The \sfilename{hgweb.cgi} script only lets you publish a single
   9.888 +repository, which is an annoying restriction.  If you want to publish
   9.889 +more than one without wracking yourself with multiple copies of the
   9.890 +same script, each with different names, a better choice is to use the
   9.891 +\sfilename{hgwebdir.cgi} script.
   9.892 +
   9.893 +The procedure to configure \sfilename{hgwebdir.cgi} is only a little
   9.894 +more involved than for \sfilename{hgweb.cgi}.  First, you must obtain
   9.895 +a copy of the script.  If you don't have one handy, you can download a
   9.896 +copy from the master Mercurial repository at
   9.897 +\url{http://www.selenic.com/repo/hg/raw-file/tip/hgwebdir.cgi}.
   9.898 +
   9.899 +You'll need to copy this script into your \dirname{public\_html}
   9.900 +directory, and ensure that it's executable.
   9.901 +\begin{codesample2}
   9.902 +  cp .../hgwebdir.cgi ~/public_html
   9.903 +  chmod 755 ~/public_html ~/public_html/hgwebdir.cgi
   9.904 +\end{codesample2}
   9.905 +With basic configuration out of the way, try to visit
   9.906 +\url{http://myhostname/~myuser/hgwebdir.cgi} in your browser.  It
   9.907 +should display an empty list of repositories.  If you get a blank
   9.908 +window or error message, try walking through the list of potential
   9.909 +problems in section~\ref{sec:collab:wtf}.
   9.910 +
   9.911 +The \sfilename{hgwebdir.cgi} script relies on an external
   9.912 +configuration file.  By default, it searches for a file named
   9.913 +\sfilename{hgweb.config} in the same directory as itself.  You'll need
   9.914 +to create this file, and make it world-readable.  The format of the
   9.915 +file is similar to a Windows ``ini'' file, as understood by Python's
   9.916 +\texttt{ConfigParser}~\cite{web:configparser} module.
   9.917 +
   9.918 +The easiest way to configure \sfilename{hgwebdir.cgi} is with a
   9.919 +section named \texttt{collections}.  This will automatically publish
   9.920 +\emph{every} repository under the directories you name.  The section
   9.921 +should look like this:
   9.922 +\begin{codesample2}
   9.923 +  [collections]
   9.924 +  /my/root = /my/root
   9.925 +\end{codesample2}
   9.926 +Mercurial interprets this by looking at the directory name on the
   9.927 +\emph{right} hand side of the ``\texttt{=}'' sign; finding
   9.928 +repositories in that directory hierarchy; and using the text on the
   9.929 +\emph{left} to strip off matching text from the names it will actually
   9.930 +list in the web interface.  The remaining component of a path after
   9.931 +this stripping has occurred is called a ``virtual path''.
   9.932 +
   9.933 +Given the example above, if we have a repository whose local path is
   9.934 +\dirname{/my/root/this/repo}, the CGI script will strip the leading
   9.935 +\dirname{/my/root} from the name, and publish the repository with a
   9.936 +virtual path of \dirname{this/repo}.  If the base URL for our CGI
   9.937 +script is \url{http://myhostname/~myuser/hgwebdir.cgi}, the complete
   9.938 +URL for that repository will be
   9.939 +\url{http://myhostname/~myuser/hgwebdir.cgi/this/repo}.
   9.940 +
   9.941 +If we replace \dirname{/my/root} on the left hand side of this example
   9.942 +with \dirname{/my}, then \sfilename{hgwebdir.cgi} will only strip off
   9.943 +\dirname{/my} from the repository name, and will give us a virtual
   9.944 +path of \dirname{root/this/repo} instead of \dirname{this/repo}.
   9.945 +
   9.946 +The \sfilename{hgwebdir.cgi} script will recursively search each
   9.947 +directory listed in the \texttt{collections} section of its
   9.948 +configuration file, but it will \texttt{not} recurse into the
   9.949 +repositories it finds.
   9.950 +
   9.951 +The \texttt{collections} mechanism makes it easy to publish many
   9.952 +repositories in a ``fire and forget'' manner.  You only need to set up
   9.953 +the CGI script and configuration file one time.  Afterwards, you can
   9.954 +publish or unpublish a repository at any time by simply moving it
   9.955 +into, or out of, the directory hierarchy in which you've configured
   9.956 +\sfilename{hgwebdir.cgi} to look.
   9.957 +
   9.958 +\subsubsection{Explicitly specifying which repositories to publish}
   9.959 +
   9.960 +In addition to the \texttt{collections} mechanism, the
   9.961 +\sfilename{hgwebdir.cgi} script allows you to publish a specific list
   9.962 +of repositories.  To do so, create a \texttt{paths} section, with
   9.963 +contents of the following form.
   9.964 +\begin{codesample2}
   9.965 +  [paths]
   9.966 +  repo1 = /my/path/to/some/repo
   9.967 +  repo2 = /some/path/to/another
   9.968 +\end{codesample2}
   9.969 +In this case, the virtual path (the component that will appear in a
   9.970 +URL) is on the left hand side of each definition, while the path to
   9.971 +the repository is on the right.  Notice that there does not need to be
   9.972 +any relationship between the virtual path you choose and the location
   9.973 +of a repository in your filesystem.
   9.974 +
   9.975 +If you wish, you can use both the \texttt{collections} and
   9.976 +\texttt{paths} mechanisms simultaneously in a single configuration
   9.977 +file.
   9.978 +
   9.979 +\begin{note}
   9.980 +  If multiple repositories have the same virtual path,
   9.981 +  \sfilename{hgwebdir.cgi} will not report an error.  Instead, it will
   9.982 +  behave unpredictably.
   9.983 +\end{note}
   9.984 +
   9.985 +\subsection{Downloading source archives}
   9.986 +
   9.987 +Mercurial's web interface lets users download an archive of any
   9.988 +revision.  This archive will contain a snapshot of the working
   9.989 +directory as of that revision, but it will not contain a copy of the
   9.990 +repository data.
   9.991 +
   9.992 +By default, this feature is not enabled.  To enable it, you'll need to
   9.993 +add an \rcitem{web}{allow\_archive} item to the \rcsection{web}
   9.994 +section of your \hgrc.
   9.995 +
   9.996 +\subsection{Web configuration options}
   9.997 +
   9.998 +Mercurial's web interfaces (the \hgcmd{serve} command, and the
   9.999 +\sfilename{hgweb.cgi} and \sfilename{hgwebdir.cgi} scripts) have a
  9.1000 +number of configuration options that you can set.  These belong in a
  9.1001 +section named \rcsection{web}.
  9.1002 +\begin{itemize}
  9.1003 +\item[\rcitem{web}{allow\_archive}] Determines which (if any) archive
  9.1004 +  download mechanisms Mercurial supports.  If you enable this
  9.1005 +  feature, users of the web interface will be able to download an
  9.1006 +  archive of whatever revision of a repository they are viewing.
  9.1007 +  To enable the archive feature, this item must take the form of a
  9.1008 +  sequence of words drawn from the list below.
  9.1009 +  \begin{itemize}
  9.1010 +  \item[\texttt{bz2}] A \command{tar} archive, compressed using
  9.1011 +    \texttt{bzip2} compression.  This has the best compression ratio,
  9.1012 +    but uses the most CPU time on the server.
  9.1013 +  \item[\texttt{gz}] A \command{tar} archive, compressed using
  9.1014 +    \texttt{gzip} compression.
  9.1015 +  \item[\texttt{zip}] A \command{zip} archive, compressed using LZW
  9.1016 +    compression.  This format has the worst compression ratio, but is
  9.1017 +    widely used in the Windows world.
  9.1018 +  \end{itemize}
  9.1019 +  If you provide an empty list, or don't have an
  9.1020 +  \rcitem{web}{allow\_archive} entry at all, this feature will be
  9.1021 +  disabled.  Here is an example of how to enable all three supported
  9.1022 +  formats.
  9.1023 +  \begin{codesample4}
  9.1024 +    [web]
  9.1025 +    allow_archive = bz2 gz zip
  9.1026 +  \end{codesample4}
  9.1027 +\item[\rcitem{web}{allowpull}] Boolean.  Determines whether the web
  9.1028 +  interface allows remote users to \hgcmd{pull} and \hgcmd{clone} this
  9.1029 +  repository over~HTTP.  If set to \texttt{no} or \texttt{false}, only
  9.1030 +  the ``human-oriented'' portion of the web interface is available.
  9.1031 +\item[\rcitem{web}{contact}] String.  A free-form (but preferably
  9.1032 +  brief) string identifying the person or group in charge of the
  9.1033 +  repository.  This often contains the name and email address of a
  9.1034 +  person or mailing list.  It often makes sense to place this entry in
  9.1035 +  a repository's own \sfilename{.hg/hgrc} file, but it can make sense
  9.1036 +  to use in a global \hgrc\ if every repository has a single
  9.1037 +  maintainer.
  9.1038 +\item[\rcitem{web}{maxchanges}] Integer.  The default maximum number
  9.1039 +  of changesets to display in a single page of output.
  9.1040 +\item[\rcitem{web}{maxfiles}] Integer.  The default maximum number
  9.1041 +  of modified files to display in a single page of output.
  9.1042 +\item[\rcitem{web}{stripes}] Integer.  If the web interface displays
  9.1043 +  alternating ``stripes'' to make it easier to visually align rows
  9.1044 +  when you are looking at a table, this number controls the number of
  9.1045 +  rows in each stripe.
  9.1046 +\item[\rcitem{web}{style}] Controls the template Mercurial uses to
  9.1047 +  display the web interface.  Mercurial ships with two web templates,
  9.1048 +  named \texttt{default} and \texttt{gitweb} (the latter is much more
  9.1049 +  visually attractive).  You can also specify a custom template of
  9.1050 +  your own; see chapter~\ref{chap:template} for details.  Here, you
  9.1051 +  can see how to enable the \texttt{gitweb} style.
  9.1052 +  \begin{codesample4}
  9.1053 +    [web]
  9.1054 +    style = gitweb
  9.1055 +  \end{codesample4}
  9.1056 +\item[\rcitem{web}{templates}] Path.  The directory in which to search
  9.1057 +  for template files.  By default, Mercurial searches in the directory
  9.1058 +  in which it was installed.
  9.1059 +\end{itemize}
  9.1060 +If you are using \sfilename{hgwebdir.cgi}, you can place a few
  9.1061 +configuration items in a \rcsection{web} section of the
  9.1062 +\sfilename{hgweb.config} file instead of a \hgrc\ file, for
  9.1063 +convenience.  These items are \rcitem{web}{motd} and
  9.1064 +\rcitem{web}{style}.
  9.1065 +
  9.1066 +\subsubsection{Options specific to an individual repository}
  9.1067 +
  9.1068 +A few \rcsection{web} configuration items ought to be placed in a
  9.1069 +repository's local \sfilename{.hg/hgrc}, rather than a user's or
  9.1070 +global \hgrc.
  9.1071 +\begin{itemize}
  9.1072 +\item[\rcitem{web}{description}] String.  A free-form (but preferably
  9.1073 +  brief) string that describes the contents or purpose of the
  9.1074 +  repository.
  9.1075 +\item[\rcitem{web}{name}] String.  The name to use for the repository
  9.1076 +  in the web interface.  This overrides the default name, which is the
  9.1077 +  last component of the repository's path.
  9.1078 +\end{itemize}
  9.1079 +
  9.1080 +\subsubsection{Options specific to the \hgcmd{serve} command}
  9.1081 +
  9.1082 +Some of the items in the \rcsection{web} section of a \hgrc\ file are
  9.1083 +only for use with the \hgcmd{serve} command.
  9.1084 +\begin{itemize}
  9.1085 +\item[\rcitem{web}{accesslog}] Path.  The name of a file into which to
  9.1086 +  write an access log.  By default, the \hgcmd{serve} command writes
  9.1087 +  this information to standard output, not to a file.  Log entries are
  9.1088 +  written in the standard ``combined'' file format used by almost all
  9.1089 +  web servers.
  9.1090 +\item[\rcitem{web}{address}] String.  The local address on which the
  9.1091 +  server should listen for incoming connections.  By default, the
  9.1092 +  server listens on all addresses.
  9.1093 +\item[\rcitem{web}{errorlog}] Path.  The name of a file into which to
  9.1094 +  write an error log.  By default, the \hgcmd{serve} command writes this
  9.1095 +  information to standard error, not to a file.
  9.1096 +\item[\rcitem{web}{ipv6}] Boolean.  Whether to use the IPv6 protocol.
  9.1097 +  By default, IPv6 is not used. 
  9.1098 +\item[\rcitem{web}{port}] Integer.  The TCP~port number on which the
  9.1099 +  server should listen.  The default port number used is~8000.
  9.1100 +\end{itemize}
  9.1101 +
  9.1102 +\subsubsection{Choosing the right \hgrc\ file to add \rcsection{web}
  9.1103 +  items to}
  9.1104 +
  9.1105 +It is important to remember that a web server like Apache or
  9.1106 +\texttt{lighttpd} will run under a user~ID that is different to yours.
  9.1107 +CGI scripts run by your server, such as \sfilename{hgweb.cgi}, will
  9.1108 +usually also run under that user~ID.
  9.1109 +
  9.1110 +If you add \rcsection{web} items to your own personal \hgrc\ file, CGI
  9.1111 +scripts won't read that \hgrc\ file.  Those settings will thus only
  9.1112 +affect the behaviour of the \hgcmd{serve} command when you run it.  To
  9.1113 +cause CGI scripts to see your settings, either create a \hgrc\ file in
  9.1114 +the home directory of the user ID that runs your web server, or add
  9.1115 +those settings to a system-wide \hgrc\ file.
  9.1116 +
  9.1117 +
  9.1118 +%%% Local Variables: 
  9.1119 +%%% mode: latex
  9.1120 +%%% TeX-master: "00book"
  9.1121 +%%% End: 
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/fr/concepts.tex	Thu Feb 05 12:37:03 2009 +0100
    10.3 @@ -0,0 +1,577 @@
    10.4 +\chapter{Behind the scenes}
    10.5 +\label{chap:concepts}
    10.6 +
    10.7 +Unlike many revision control systems, the concepts upon which
    10.8 +Mercurial is built are simple enough that it's easy to understand how
    10.9 +the software really works.  Knowing this certainly isn't necessary,
   10.10 +but I find it useful to have a ``mental model'' of what's going on.
   10.11 +
   10.12 +This understanding gives me confidence that Mercurial has been
   10.13 +carefully designed to be both \emph{safe} and \emph{efficient}.  And
   10.14 +just as importantly, if it's easy for me to retain a good idea of what
   10.15 +the software is doing when I perform a revision control task, I'm less
   10.16 +likely to be surprised by its behaviour.
   10.17 +
   10.18 +In this chapter, we'll initially cover the core concepts behind
   10.19 +Mercurial's design, then continue to discuss some of the interesting
   10.20 +details of its implementation.
   10.21 +
   10.22 +\section{Mercurial's historical record}
   10.23 +
   10.24 +\subsection{Tracking the history of a single file}
   10.25 +
   10.26 +When Mercurial tracks modifications to a file, it stores the history
   10.27 +of that file in a metadata object called a \emph{filelog}.  Each entry
   10.28 +in the filelog contains enough information to reconstruct one revision
   10.29 +of the file that is being tracked.  Filelogs are stored as files in
   10.30 +the \sdirname{.hg/store/data} directory.  A filelog contains two kinds
   10.31 +of information: revision data, and an index to help Mercurial to find
   10.32 +a revision efficiently.
   10.33 +
   10.34 +A file that is large, or has a lot of history, has its filelog stored
   10.35 +in separate data (``\texttt{.d}'' suffix) and index (``\texttt{.i}''
   10.36 +suffix) files.  For small files without much history, the revision
   10.37 +data and index are combined in a single ``\texttt{.i}'' file.  The
   10.38 +correspondence between a file in the working directory and the filelog
   10.39 +that tracks its history in the repository is illustrated in
   10.40 +figure~\ref{fig:concepts:filelog}.
   10.41 +
   10.42 +\begin{figure}[ht]
   10.43 +  \centering
   10.44 +  \grafix{filelog}
   10.45 +  \caption{Relationships between files in working directory and
   10.46 +    filelogs in repository}
   10.47 +  \label{fig:concepts:filelog}
   10.48 +\end{figure}
   10.49 +
   10.50 +\subsection{Managing tracked files}
   10.51 +
   10.52 +Mercurial uses a structure called a \emph{manifest} to collect
   10.53 +together information about the files that it tracks.  Each entry in
   10.54 +the manifest contains information about the files present in a single
   10.55 +changeset.  An entry records which files are present in the changeset,
   10.56 +the revision of each file, and a few other pieces of file metadata.
   10.57 +
   10.58 +\subsection{Recording changeset information}
   10.59 +
   10.60 +The \emph{changelog} contains information about each changeset.  Each
   10.61 +revision records who committed a change, the changeset comment, other
   10.62 +pieces of changeset-related information, and the revision of the
   10.63 +manifest to use.
   10.64 +
   10.65 +\subsection{Relationships between revisions}
   10.66 +
   10.67 +Within a changelog, a manifest, or a filelog, each revision stores a
   10.68 +pointer to its immediate parent (or to its two parents, if it's a
   10.69 +merge revision).  As I mentioned above, there are also relationships
   10.70 +between revisions \emph{across} these structures, and they are
   10.71 +hierarchical in nature.
   10.72 +
   10.73 +For every changeset in a repository, there is exactly one revision
   10.74 +stored in the changelog.  Each revision of the changelog contains a
   10.75 +pointer to a single revision of the manifest.  A revision of the
   10.76 +manifest stores a pointer to a single revision of each filelog tracked
   10.77 +when that changeset was created.  These relationships are illustrated
   10.78 +in figure~\ref{fig:concepts:metadata}.
   10.79 +
   10.80 +\begin{figure}[ht]
   10.81 +  \centering
   10.82 +  \grafix{metadata}
   10.83 +  \caption{Metadata relationships}
   10.84 +  \label{fig:concepts:metadata}
   10.85 +\end{figure}
   10.86 +
   10.87 +As the illustration shows, there is \emph{not} a ``one to one''
   10.88 +relationship between revisions in the changelog, manifest, or filelog.
   10.89 +If the manifest hasn't changed between two changesets, the changelog
   10.90 +entries for those changesets will point to the same revision of the
   10.91 +manifest.  If a file that Mercurial tracks hasn't changed between two
   10.92 +changesets, the entry for that file in the two revisions of the
   10.93 +manifest will point to the same revision of its filelog.
   10.94 +
   10.95 +\section{Safe, efficient storage}
   10.96 +
   10.97 +The underpinnings of changelogs, manifests, and filelogs are provided
   10.98 +by a single structure called the \emph{revlog}.
   10.99 +
  10.100 +\subsection{Efficient storage}
  10.101 +
  10.102 +The revlog provides efficient storage of revisions using a
  10.103 +\emph{delta} mechanism.  Instead of storing a complete copy of a file
  10.104 +for each revision, it stores the changes needed to transform an older
  10.105 +revision into the new revision.  For many kinds of file data, these
  10.106 +deltas are typically a fraction of a percent of the size of a full
  10.107 +copy of a file.
  10.108 +
  10.109 +Some obsolete revision control systems can only work with deltas of
  10.110 +text files.  They must either store binary files as complete snapshots
  10.111 +or encoded into a text representation, both of which are wasteful
  10.112 +approaches.  Mercurial can efficiently handle deltas of files with
  10.113 +arbitrary binary contents; it doesn't need to treat text as special.
  10.114 +
  10.115 +\subsection{Safe operation}
  10.116 +\label{sec:concepts:txn}
  10.117 +
  10.118 +Mercurial only ever \emph{appends} data to the end of a revlog file.
  10.119 +It never modifies a section of a file after it has written it.  This
  10.120 +is both more robust and efficient than schemes that need to modify or
  10.121 +rewrite data.
  10.122 +
  10.123 +In addition, Mercurial treats every write as part of a
  10.124 +\emph{transaction} that can span a number of files.  A transaction is
  10.125 +\emph{atomic}: either the entire transaction succeeds and its effects
  10.126 +are all visible to readers in one go, or the whole thing is undone.
  10.127 +This guarantee of atomicity means that if you're running two copies of
  10.128 +Mercurial, where one is reading data and one is writing it, the reader
  10.129 +will never see a partially written result that might confuse it.
  10.130 +
  10.131 +The fact that Mercurial only appends to files makes it easier to
  10.132 +provide this transactional guarantee.  The easier it is to do stuff
  10.133 +like this, the more confident you should be that it's done correctly.
  10.134 +
  10.135 +\subsection{Fast retrieval}
  10.136 +
  10.137 +Mercurial cleverly avoids a pitfall common to all earlier
  10.138 +revision control systems: the problem of \emph{inefficient retrieval}.
  10.139 +Most revision control systems store the contents of a revision as an
  10.140 +incremental series of modifications against a ``snapshot''.  To
  10.141 +reconstruct a specific revision, you must first read the snapshot, and
  10.142 +then every one of the revisions between the snapshot and your target
  10.143 +revision.  The more history that a file accumulates, the more
  10.144 +revisions you must read, hence the longer it takes to reconstruct a
  10.145 +particular revision.
  10.146 +
  10.147 +\begin{figure}[ht]
  10.148 +  \centering
  10.149 +  \grafix{snapshot}
  10.150 +  \caption{Snapshot of a revlog, with incremental deltas}
  10.151 +  \label{fig:concepts:snapshot}
  10.152 +\end{figure}
  10.153 +
  10.154 +The innovation that Mercurial applies to this problem is simple but
  10.155 +effective.  Once the cumulative amount of delta information stored
  10.156 +since the last snapshot exceeds a fixed threshold, it stores a new
  10.157 +snapshot (compressed, of course), instead of another delta.  This
  10.158 +makes it possible to reconstruct \emph{any} revision of a file
  10.159 +quickly.  This approach works so well that it has since been copied by
  10.160 +several other revision control systems.
  10.161 +
  10.162 +Figure~\ref{fig:concepts:snapshot} illustrates the idea.  In an entry
  10.163 +in a revlog's index file, Mercurial stores the range of entries from
  10.164 +the data file that it must read to reconstruct a particular revision.
  10.165 +
  10.166 +\subsubsection{Aside: the influence of video compression}
  10.167 +
  10.168 +If you're familiar with video compression or have ever watched a TV
  10.169 +feed through a digital cable or satellite service, you may know that
  10.170 +most video compression schemes store each frame of video as a delta
  10.171 +against its predecessor frame.  In addition, these schemes use
  10.172 +``lossy'' compression techniques to increase the compression ratio, so
  10.173 +visual errors accumulate over the course of a number of inter-frame
  10.174 +deltas.
  10.175 +
  10.176 +Because it's possible for a video stream to ``drop out'' occasionally
  10.177 +due to signal glitches, and to limit the accumulation of artefacts
  10.178 +introduced by the lossy compression process, video encoders
  10.179 +periodically insert a complete frame (called a ``key frame'') into the
  10.180 +video stream; the next delta is generated against that frame.  This
  10.181 +means that if the video signal gets interrupted, it will resume once
  10.182 +the next key frame is received.  Also, the accumulation of encoding
  10.183 +errors restarts anew with each key frame.
  10.184 +
  10.185 +\subsection{Identification and strong integrity}
  10.186 +
  10.187 +Along with delta or snapshot information, a revlog entry contains a
  10.188 +cryptographic hash of the data that it represents.  This makes it
  10.189 +difficult to forge the contents of a revision, and easy to detect
  10.190 +accidental corruption.  
  10.191 +
  10.192 +Hashes provide more than a mere check against corruption; they are
  10.193 +used as the identifiers for revisions.  The changeset identification
  10.194 +hashes that you see as an end user are from revisions of the
  10.195 +changelog.  Although filelogs and the manifest also use hashes,
  10.196 +Mercurial only uses these behind the scenes.
  10.197 +
  10.198 +Mercurial verifies that hashes are correct when it retrieves file
  10.199 +revisions and when it pulls changes from another repository.  If it
  10.200 +encounters an integrity problem, it will complain and stop whatever
  10.201 +it's doing.
  10.202 +
  10.203 +In addition to the effect it has on retrieval efficiency, Mercurial's
  10.204 +use of periodic snapshots makes it more robust against partial data
  10.205 +corruption.  If a revlog becomes partly corrupted due to a hardware
  10.206 +error or system bug, it's often possible to reconstruct some or most
  10.207 +revisions from the uncorrupted sections of the revlog, both before and
  10.208 +after the corrupted section.  This would not be possible with a
  10.209 +delta-only storage model.
  10.210 +
  10.211 +\section{Revision history, branching,
  10.212 +  and merging}
  10.213 +
  10.214 +Every entry in a Mercurial revlog knows the identity of its immediate
  10.215 +ancestor revision, usually referred to as its \emph{parent}.  In fact,
  10.216 +a revision contains room for not one parent, but two.  Mercurial uses
  10.217 +a special hash, called the ``null ID'', to represent the idea ``there
  10.218 +is no parent here''.  This hash is simply a string of zeroes.
  10.219 +
  10.220 +In figure~\ref{fig:concepts:revlog}, you can see an example of the
  10.221 +conceptual structure of a revlog.  Filelogs, manifests, and changelogs
  10.222 +all have this same structure; they differ only in the kind of data
  10.223 +stored in each delta or snapshot.
  10.224 +
  10.225 +The first revision in a revlog (at the bottom of the image) has the
  10.226 +null ID in both of its parent slots.  For a ``normal'' revision, its
  10.227 +first parent slot contains the ID of its parent revision, and its
  10.228 +second contains the null ID, indicating that the revision has only one
  10.229 +real parent.  Any two revisions that have the same parent ID are
  10.230 +branches.  A revision that represents a merge between branches has two
  10.231 +normal revision IDs in its parent slots.
  10.232 +
  10.233 +\begin{figure}[ht]
  10.234 +  \centering
  10.235 +  \grafix{revlog}
  10.236 +  \caption{}
  10.237 +  \label{fig:concepts:revlog}
  10.238 +\end{figure}
  10.239 +
  10.240 +\section{The working directory}
  10.241 +
  10.242 +In the working directory, Mercurial stores a snapshot of the files
  10.243 +from the repository as of a particular changeset.
  10.244 +
  10.245 +The working directory ``knows'' which changeset it contains.  When you
  10.246 +update the working directory to contain a particular changeset,
  10.247 +Mercurial looks up the appropriate revision of the manifest to find
  10.248 +out which files it was tracking at the time that changeset was
  10.249 +committed, and which revision of each file was then current.  It then
  10.250 +recreates a copy of each of those files, with the same contents it had
  10.251 +when the changeset was committed.
  10.252 +
  10.253 +The \emph{dirstate} contains Mercurial's knowledge of the working
  10.254 +directory.  This details which changeset the working directory is
  10.255 +updated to, and all of the files that Mercurial is tracking in the
  10.256 +working directory.
  10.257 +
  10.258 +Just as a revision of a revlog has room for two parents, so that it
  10.259 +can represent either a normal revision (with one parent) or a merge of
  10.260 +two earlier revisions, the dirstate has slots for two parents.  When
  10.261 +you use the \hgcmd{update} command, the changeset that you update to
  10.262 +is stored in the ``first parent'' slot, and the null ID in the second.
  10.263 +When you \hgcmd{merge} with another changeset, the first parent
  10.264 +remains unchanged, and the second parent is filled in with the
  10.265 +changeset you're merging with.  The \hgcmd{parents} command tells you
  10.266 +what the parents of the dirstate are.
  10.267 +
  10.268 +\subsection{What happens when you commit}
  10.269 +
  10.270 +The dirstate stores parent information for more than just book-keeping
  10.271 +purposes.  Mercurial uses the parents of the dirstate as \emph{the
  10.272 +  parents of a new changeset} when you perform a commit.
  10.273 +
  10.274 +\begin{figure}[ht]
  10.275 +  \centering
  10.276 +  \grafix{wdir}
  10.277 +  \caption{The working directory can have two parents}
  10.278 +  \label{fig:concepts:wdir}
  10.279 +\end{figure}
  10.280 +
  10.281 +Figure~\ref{fig:concepts:wdir} shows the normal state of the working
  10.282 +directory, where it has a single changeset as parent.  That changeset
  10.283 +is the \emph{tip}, the newest changeset in the repository that has no
  10.284 +children.
  10.285 +
  10.286 +\begin{figure}[ht]
  10.287 +  \centering
  10.288 +  \grafix{wdir-after-commit}
  10.289 +  \caption{The working directory gains new parents after a commit}
  10.290 +  \label{fig:concepts:wdir-after-commit}
  10.291 +\end{figure}
  10.292 +
  10.293 +It's useful to think of the working directory as ``the changeset I'm
  10.294 +about to commit''.  Any files that you tell Mercurial that you've
  10.295 +added, removed, renamed, or copied will be reflected in that
  10.296 +changeset, as will modifications to any files that Mercurial is
  10.297 +already tracking; the new changeset will have the parents of the
  10.298 +working directory as its parents.
  10.299 +
  10.300 +After a commit, Mercurial will update the parents of the working
  10.301 +directory, so that the first parent is the ID of the new changeset,
  10.302 +and the second is the null ID.  This is shown in
  10.303 +figure~\ref{fig:concepts:wdir-after-commit}.  Mercurial doesn't touch
  10.304 +any of the files in the working directory when you commit; it just
  10.305 +modifies the dirstate to note its new parents.
  10.306 +
  10.307 +\subsection{Creating a new head}
  10.308 +
  10.309 +It's perfectly normal to update the working directory to a changeset
  10.310 +other than the current tip.  For example, you might want to know what
  10.311 +your project looked like last Tuesday, or you could be looking through
  10.312 +changesets to see which one introduced a bug.  In cases like this, the
  10.313 +natural thing to do is update the working directory to the changeset
  10.314 +you're interested in, and then examine the files in the working
  10.315 +directory directly to see their contents as they were when you
  10.316 +committed that changeset.  The effect of this is shown in
  10.317 +figure~\ref{fig:concepts:wdir-pre-branch}.
  10.318 +
  10.319 +\begin{figure}[ht]
  10.320 +  \centering
  10.321 +  \grafix{wdir-pre-branch}
  10.322 +  \caption{The working directory, updated to an older changeset}
  10.323 +  \label{fig:concepts:wdir-pre-branch}
  10.324 +\end{figure}
  10.325 +
  10.326 +Having updated the working directory to an older changeset, what
  10.327 +happens if you make some changes, and then commit?  Mercurial behaves
  10.328 +in the same way as I outlined above.  The parents of the working
  10.329 +directory become the parents of the new changeset.  This new changeset
  10.330 +has no children, so it becomes the new tip.  And the repository now
  10.331 +contains two changesets that have no children; we call these
  10.332 +\emph{heads}.  You can see the structure that this creates in
  10.333 +figure~\ref{fig:concepts:wdir-branch}.
  10.334 +
  10.335 +\begin{figure}[ht]
  10.336 +  \centering
  10.337 +  \grafix{wdir-branch}
  10.338 +  \caption{After a commit made while synced to an older changeset}
  10.339 +  \label{fig:concepts:wdir-branch}
  10.340 +\end{figure}
  10.341 +
  10.342 +\begin{note}
  10.343 +  If you're new to Mercurial, you should keep in mind a common
  10.344 +  ``error'', which is to use the \hgcmd{pull} command without any
  10.345 +  options.  By default, the \hgcmd{pull} command \emph{does not}
  10.346 +  update the working directory, so you'll bring new changesets into
  10.347 +  your repository, but the working directory will stay synced at the
  10.348 +  same changeset as before the pull.  If you make some changes and
  10.349 +  commit afterwards, you'll thus create a new head, because your
  10.350 +  working directory isn't synced to whatever the current tip is.
  10.351 +
  10.352 +  I put the word ``error'' in quotes because all that you need to do
  10.353 +  to rectify this situation is \hgcmd{merge}, then \hgcmd{commit}.  In
  10.354 +  other words, this almost never has negative consequences; it just
  10.355 +  surprises people.  I'll discuss other ways to avoid this behaviour,
  10.356 +  and why Mercurial behaves in this initially surprising way, later
  10.357 +  on.
  10.358 +\end{note}
  10.359 +
  10.360 +\subsection{Merging heads}
  10.361 +
  10.362 +When you run the \hgcmd{merge} command, Mercurial leaves the first
  10.363 +parent of the working directory unchanged, and sets the second parent
  10.364 +to the changeset you're merging with, as shown in
  10.365 +figure~\ref{fig:concepts:wdir-merge}.
  10.366 +
  10.367 +\begin{figure}[ht]
  10.368 +  \centering
  10.369 +  \grafix{wdir-merge}
  10.370 +  \caption{Merging two heads}
  10.371 +  \label{fig:concepts:wdir-merge}
  10.372 +\end{figure}
  10.373 +
  10.374 +Mercurial also has to modify the working directory, to merge the files
  10.375 +managed in the two changesets.  Simplified a little, the merging
  10.376 +process goes like this, for every file in the manifests of both
  10.377 +changesets.
  10.378 +\begin{itemize}
  10.379 +\item If neither changeset has modified a file, do nothing with that
  10.380 +  file.
  10.381 +\item If one changeset has modified a file, and the other hasn't,
  10.382 +  create the modified copy of the file in the working directory.
  10.383 +\item If one changeset has removed a file, and the other hasn't (or
  10.384 +  has also deleted it), delete the file from the working directory.
  10.385 +\item If one changeset has removed a file, but the other has modified
  10.386 +  the file, ask the user what to do: keep the modified file, or remove
  10.387 +  it?
  10.388 +\item If both changesets have modified a file, invoke an external
  10.389 +  merge program to choose the new contents for the merged file.  This
  10.390 +  may require input from the user.
  10.391 +\item If one changeset has modified a file, and the other has renamed
  10.392 +  or copied the file, make sure that the changes follow the new name
  10.393 +  of the file.
  10.394 +\end{itemize}
  10.395 +There are more details---merging has plenty of corner cases---but
  10.396 +these are the most common choices that are involved in a merge.  As
  10.397 +you can see, most cases are completely automatic, and indeed most
  10.398 +merges finish automatically, without requiring your input to resolve
  10.399 +any conflicts.
  10.400 +
  10.401 +When you're thinking about what happens when you commit after a merge,
  10.402 +once again the working directory is ``the changeset I'm about to
  10.403 +commit''.  After the \hgcmd{merge} command completes, the working
  10.404 +directory has two parents; these will become the parents of the new
  10.405 +changeset.
  10.406 +
  10.407 +Mercurial lets you perform multiple merges, but you must commit the
  10.408 +results of each individual merge as you go.  This is necessary because
  10.409 +Mercurial only tracks two parents for both revisions and the working
  10.410 +directory.  While it would be technically possible to merge multiple
  10.411 +changesets at once, the prospect of user confusion and making a
  10.412 +terrible mess of a merge immediately becomes overwhelming.
  10.413 +
  10.414 +\section{Other interesting design features}
  10.415 +
  10.416 +In the sections above, I've tried to highlight some of the most
  10.417 +important aspects of Mercurial's design, to illustrate that it pays
  10.418 +careful attention to reliability and performance.  However, the
  10.419 +attention to detail doesn't stop there.  There are a number of other
  10.420 +aspects of Mercurial's construction that I personally find
  10.421 +interesting.  I'll detail a few of them here, separate from the ``big
  10.422 +ticket'' items above, so that if you're interested, you can gain a
  10.423 +better idea of the amount of thinking that goes into a well-designed
  10.424 +system.
  10.425 +
  10.426 +\subsection{Clever compression}
  10.427 +
  10.428 +When appropriate, Mercurial will store both snapshots and deltas in
  10.429 +compressed form.  It does this by always \emph{trying to} compress a
  10.430 +snapshot or delta, but only storing the compressed version if it's
  10.431 +smaller than the uncompressed version.
  10.432 +
  10.433 +This means that Mercurial does ``the right thing'' when storing a file
  10.434 +whose native form is compressed, such as a \texttt{zip} archive or a
  10.435 +JPEG image.  When these types of files are compressed a second time,
  10.436 +the resulting file is usually bigger than the once-compressed form,
  10.437 +and so Mercurial will store the plain \texttt{zip} or JPEG.
  10.438 +
  10.439 +Deltas between revisions of a compressed file are usually larger than
  10.440 +snapshots of the file, and Mercurial again does ``the right thing'' in
  10.441 +these cases.  It finds that such a delta exceeds the threshold at
  10.442 +which it should store a complete snapshot of the file, so it stores
  10.443 +the snapshot, again saving space compared to a naive delta-only
  10.444 +approach.
  10.445 +
  10.446 +\subsubsection{Network recompression}
  10.447 +
  10.448 +When storing revisions on disk, Mercurial uses the ``deflate''
  10.449 +compression algorithm (the same one used by the popular \texttt{zip}
  10.450 +archive format), which balances good speed with a respectable
  10.451 +compression ratio.  However, when transmitting revision data over a
  10.452 +network connection, Mercurial uncompresses the compressed revision
  10.453 +data.
  10.454 +
  10.455 +If the connection is over HTTP, Mercurial recompresses the entire
  10.456 +stream of data using a compression algorithm that gives a better
  10.457 +compression ratio (the Burrows-Wheeler algorithm from the widely used
  10.458 +\texttt{bzip2} compression package).  This combination of algorithm
  10.459 +and compression of the entire stream (instead of a revision at a time)
  10.460 +substantially reduces the number of bytes to be transferred, yielding
  10.461 +better network performance over almost all kinds of network.
  10.462 +
  10.463 +(If the connection is over \command{ssh}, Mercurial \emph{doesn't}
  10.464 +recompress the stream, because \command{ssh} can already do this
  10.465 +itself.)
  10.466 +
  10.467 +\subsection{Read/write ordering and atomicity}
  10.468 +
  10.469 +Appending to files isn't the whole story when it comes to guaranteeing
  10.470 +that a reader won't see a partial write.  If you recall
  10.471 +figure~\ref{fig:concepts:metadata}, revisions in the changelog point to
  10.472 +revisions in the manifest, and revisions in the manifest point to
  10.473 +revisions in filelogs.  This hierarchy is deliberate.
  10.474 +
  10.475 +A writer starts a transaction by writing filelog and manifest data,
  10.476 +and doesn't write any changelog data until those are finished.  A
  10.477 +reader starts by reading changelog data, then manifest data, followed
  10.478 +by filelog data.
  10.479 +
  10.480 +Since the writer has always finished writing filelog and manifest data
  10.481 +before it writes to the changelog, a reader will never read a pointer
  10.482 +to a partially written manifest revision from the changelog, and it will
  10.483 +never read a pointer to a partially written filelog revision from the
  10.484 +manifest.
  10.485 +
  10.486 +\subsection{Concurrent access}
  10.487 +
  10.488 +The read/write ordering and atomicity guarantees mean that Mercurial
  10.489 +never needs to \emph{lock} a repository when it's reading data, even
  10.490 +if the repository is being written to while the read is occurring.
  10.491 +This has a big effect on scalability; you can have an arbitrary number
  10.492 +of Mercurial processes safely reading data from a repository safely
  10.493 +all at once, no matter whether it's being written to or not.
  10.494 +
  10.495 +The lockless nature of reading means that if you're sharing a
  10.496 +repository on a multi-user system, you don't need to grant other local
  10.497 +users permission to \emph{write} to your repository in order for them
  10.498 +to be able to clone it or pull changes from it; they only need
  10.499 +\emph{read} permission.  (This is \emph{not} a common feature among
  10.500 +revision control systems, so don't take it for granted!  Most require
  10.501 +readers to be able to lock a repository to access it safely, and this
  10.502 +requires write permission on at least one directory, which of course
  10.503 +makes for all kinds of nasty and annoying security and administrative
  10.504 +problems.)
  10.505 +
  10.506 +Mercurial uses locks to ensure that only one process can write to a
  10.507 +repository at a time (the locking mechanism is safe even over
  10.508 +filesystems that are notoriously hostile to locking, such as NFS).  If
  10.509 +a repository is locked, a writer will wait for a while to retry if the
  10.510 +repository becomes unlocked, but if the repository remains locked for
  10.511 +too long, the process attempting to write will time out after a while.
  10.512 +This means that your daily automated scripts won't get stuck forever
  10.513 +and pile up if a system crashes unnoticed, for example.  (Yes, the
  10.514 +timeout is configurable, from zero to infinity.)
  10.515 +
  10.516 +\subsubsection{Safe dirstate access}
  10.517 +
  10.518 +As with revision data, Mercurial doesn't take a lock to read the
  10.519 +dirstate file; it does acquire a lock to write it.  To avoid the
  10.520 +possibility of reading a partially written copy of the dirstate file,
  10.521 +Mercurial writes to a file with a unique name in the same directory as
  10.522 +the dirstate file, then renames the temporary file atomically to
  10.523 +\filename{dirstate}.  The file named \filename{dirstate} is thus
  10.524 +guaranteed to be complete, not partially written.
  10.525 +
  10.526 +\subsection{Avoiding seeks}
  10.527 +
  10.528 +Critical to Mercurial's performance is the avoidance of seeks of the
  10.529 +disk head, since any seek is far more expensive than even a
  10.530 +comparatively large read operation.
  10.531 +
  10.532 +This is why, for example, the dirstate is stored in a single file.  If
  10.533 +there were a dirstate file per directory that Mercurial tracked, the
  10.534 +disk would seek once per directory.  Instead, Mercurial reads the
  10.535 +entire single dirstate file in one step.
  10.536 +
  10.537 +Mercurial also uses a ``copy on write'' scheme when cloning a
  10.538 +repository on local storage.  Instead of copying every revlog file
  10.539 +from the old repository into the new repository, it makes a ``hard
  10.540 +link'', which is a shorthand way to say ``these two names point to the
  10.541 +same file''.  When Mercurial is about to write to one of a revlog's
  10.542 +files, it checks to see if the number of names pointing at the file is
  10.543 +greater than one.  If it is, more than one repository is using the
  10.544 +file, so Mercurial makes a new copy of the file that is private to
  10.545 +this repository.
  10.546 +
  10.547 +A few revision control developers have pointed out that this idea of
  10.548 +making a complete private copy of a file is not very efficient in its
  10.549 +use of storage.  While this is true, storage is cheap, and this method
  10.550 +gives the highest performance while deferring most book-keeping to the
  10.551 +operating system.  An alternative scheme would most likely reduce
  10.552 +performance and increase the complexity of the software, each of which
  10.553 +is much more important to the ``feel'' of day-to-day use.
  10.554 +
  10.555 +\subsection{Other contents of the dirstate}
  10.556 +
  10.557 +Because Mercurial doesn't force you to tell it when you're modifying a
  10.558 +file, it uses the dirstate to store some extra information so it can
  10.559 +determine efficiently whether you have modified a file.  For each file
  10.560 +in the working directory, it stores the time that it last modified the
  10.561 +file itself, and the size of the file at that time.  
  10.562 +
  10.563 +When you explicitly \hgcmd{add}, \hgcmd{remove}, \hgcmd{rename} or
  10.564 +\hgcmd{copy} files, Mercurial updates the dirstate so that it knows
  10.565 +what to do with those files when you commit.
  10.566 +
  10.567 +When Mercurial is checking the states of files in the working
  10.568 +directory, it first checks a file's modification time.  If that has
  10.569 +not changed, the file must not have been modified.  If the file's size
  10.570 +has changed, the file must have been modified.  If the modification
  10.571 +time has changed, but the size has not, only then does Mercurial need
  10.572 +to read the actual contents of the file to see if they've changed.
  10.573 +Storing these few extra pieces of information dramatically reduces the
  10.574 +amount of data that Mercurial needs to read, which yields large
  10.575 +performance improvements compared to other revision control systems.
  10.576 +
  10.577 +%%% Local Variables: 
  10.578 +%%% mode: latex
  10.579 +%%% TeX-master: "00book"
  10.580 +%%% End:
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/fr/daily.tex	Thu Feb 05 12:37:03 2009 +0100
    11.3 @@ -0,0 +1,381 @@
    11.4 +\chapter{Mercurial in daily use}
    11.5 +\label{chap:daily}
    11.6 +
    11.7 +\section{Telling Mercurial which files to track}
    11.8 +
    11.9 +Mercurial does not work with files in your repository unless you tell
   11.10 +it to manage them.  The \hgcmd{status} command will tell you which
   11.11 +files Mercurial doesn't know about; it uses a ``\texttt{?}'' to
   11.12 +display such files.
   11.13 +
   11.14 +To tell Mercurial to track a file, use the \hgcmd{add} command.  Once
   11.15 +you have added a file, the entry in the output of \hgcmd{status} for
   11.16 +that file changes from ``\texttt{?}'' to ``\texttt{A}''.
   11.17 +\interaction{daily.files.add}
   11.18 +
   11.19 +After you run a \hgcmd{commit}, the files that you added before the
   11.20 +commit will no longer be listed in the output of \hgcmd{status}.  The
   11.21 +reason for this is that \hgcmd{status} only tells you about
   11.22 +``interesting'' files---those that you have modified or told Mercurial
   11.23 +to do something with---by default.  If you have a repository that
   11.24 +contains thousands of files, you will rarely want to know about files
   11.25 +that Mercurial is tracking, but that have not changed.  (You can still
   11.26 +get this information; we'll return to this later.)
   11.27 +
   11.28 +Once you add a file, Mercurial doesn't do anything with it
   11.29 +immediately.  Instead, it will take a snapshot of the file's state the
   11.30 +next time you perform a commit.  It will then continue to track the
   11.31 +changes you make to the file every time you commit, until you remove
   11.32 +the file.
   11.33 +
   11.34 +\subsection{Explicit versus implicit file naming}
   11.35 +
   11.36 +A useful behaviour that Mercurial has is that if you pass the name of
   11.37 +a directory to a command, every Mercurial command will treat this as
   11.38 +``I want to operate on every file in this directory and its
   11.39 +subdirectories''.
   11.40 +\interaction{daily.files.add-dir}
   11.41 +Notice in this example that Mercurial printed the names of the files
   11.42 +it added, whereas it didn't do so when we added the file named
   11.43 +\filename{a} in the earlier example.
   11.44 +
   11.45 +What's going on is that in the former case, we explicitly named the
   11.46 +file to add on the command line, so the assumption that Mercurial
   11.47 +makes in such cases is that you know what you were doing, and it
   11.48 +doesn't print any output.
   11.49 +
   11.50 +However, when we \emph{imply} the names of files by giving the name of
   11.51 +a directory, Mercurial takes the extra step of printing the name of
   11.52 +each file that it does something with.  This makes it more clear what
   11.53 +is happening, and reduces the likelihood of a silent and nasty
   11.54 +surprise.  This behaviour is common to most Mercurial commands.
   11.55 +
   11.56 +\subsection{Aside: Mercurial tracks files, not directories}
   11.57 +
   11.58 +Mercurial does not track directory information.  Instead, it tracks
   11.59 +the path to a file.  Before creating a file, it first creates any
   11.60 +missing directory components of the path.  After it deletes a file, it
   11.61 +then deletes any empty directories that were in the deleted file's
   11.62 +path.  This sounds like a trivial distinction, but it has one minor
   11.63 +practical consequence: it is not possible to represent a completely
   11.64 +empty directory in Mercurial.
   11.65 +
   11.66 +Empty directories are rarely useful, and there are unintrusive
   11.67 +workarounds that you can use to achieve an appropriate effect.  The
   11.68 +developers of Mercurial thus felt that the complexity that would be
   11.69 +required to manage empty directories was not worth the limited benefit
   11.70 +this feature would bring.
   11.71 +
   11.72 +If you need an empty directory in your repository, there are a few
   11.73 +ways to achieve this. One is to create a directory, then \hgcmd{add} a
   11.74 +``hidden'' file to that directory.  On Unix-like systems, any file
   11.75 +name that begins with a period (``\texttt{.}'') is treated as hidden
   11.76 +by most commands and GUI tools.  This approach is illustrated in
   11.77 +figure~\ref{ex:daily:hidden}.
   11.78 +
   11.79 +\begin{figure}[ht]
   11.80 +  \interaction{daily.files.hidden}
   11.81 +  \caption{Simulating an empty directory using a hidden file}
   11.82 +  \label{ex:daily:hidden}
   11.83 +\end{figure}
   11.84 +
   11.85 +Another way to tackle a need for an empty directory is to simply
   11.86 +create one in your automated build scripts before they will need it.
   11.87 +
   11.88 +\section{How to stop tracking a file}
   11.89 +
   11.90 +Once you decide that a file no longer belongs in your repository, use
   11.91 +the \hgcmd{remove} command; this deletes the file, and tells Mercurial
   11.92 +to stop tracking it.  A removed file is represented in the output of
   11.93 +\hgcmd{status} with a ``\texttt{R}''.
   11.94 +\interaction{daily.files.remove}
   11.95 +
   11.96 +After you \hgcmd{remove} a file, Mercurial will no longer track
   11.97 +changes to that file, even if you recreate a file with the same name
   11.98 +in your working directory.  If you do recreate a file with the same
   11.99 +name and want Mercurial to track the new file, simply \hgcmd{add} it.
  11.100 +Mercurial will know that the newly added file is not related to the
  11.101 +old file of the same name.
  11.102 +
  11.103 +\subsection{Removing a file does not affect its history}
  11.104 +
  11.105 +It is important to understand that removing a file has only two
  11.106 +effects.
  11.107 +\begin{itemize}
  11.108 +\item It removes the current version of the file from the working
  11.109 +  directory.
  11.110 +\item It stops Mercurial from tracking changes to the file, from the
  11.111 +  time of the next commit.
  11.112 +\end{itemize}
  11.113 +Removing a file \emph{does not} in any way alter the \emph{history} of
  11.114 +the file.
  11.115 +
  11.116 +If you update the working directory to a changeset in which a file
  11.117 +that you have removed was still tracked, it will reappear in the
  11.118 +working directory, with the contents it had when you committed that
  11.119 +changeset.  If you then update the working directory to a later
  11.120 +changeset, in which the file had been removed, Mercurial will once
  11.121 +again remove the file from the working directory.
  11.122 +
  11.123 +\subsection{Missing files}
  11.124 +
  11.125 +Mercurial considers a file that you have deleted, but not used
  11.126 +\hgcmd{remove} to delete, to be \emph{missing}.  A missing file is
  11.127 +represented with ``\texttt{!}'' in the output of \hgcmd{status}.
  11.128 +Mercurial commands will not generally do anything with missing files.
  11.129 +\interaction{daily.files.missing}
  11.130 +
  11.131 +If your repository contains a file that \hgcmd{status} reports as
  11.132 +missing, and you want the file to stay gone, you can run
  11.133 +\hgcmdargs{remove}{\hgopt{remove}{--after}} at any time later on, to
  11.134 +tell Mercurial that you really did mean to remove the file.
  11.135 +\interaction{daily.files.remove-after}
  11.136 +
  11.137 +On the other hand, if you deleted the missing file by accident, use
  11.138 +\hgcmdargs{revert}{\emph{filename}} to recover the file.  It will
  11.139 +reappear, in unmodified form.
  11.140 +\interaction{daily.files.recover-missing}
  11.141 +
  11.142 +\subsection{Aside: why tell Mercurial explicitly to 
  11.143 +  remove a file?}
  11.144 +
  11.145 +You might wonder why Mercurial requires you to explicitly tell it that
  11.146 +you are deleting a file.  Early during the development of Mercurial,
  11.147 +it let you delete a file however you pleased; Mercurial would notice
  11.148 +the absence of the file automatically when you next ran a
  11.149 +\hgcmd{commit}, and stop tracking the file.  In practice, this made it
  11.150 +too easy to accidentally remove a file without noticing.
  11.151 +
  11.152 +\subsection{Useful shorthand---adding and removing files
  11.153 +  in one step}
  11.154 +
  11.155 +Mercurial offers a combination command, \hgcmd{addremove}, that adds
  11.156 +untracked files and marks missing files as removed.  
  11.157 +\interaction{daily.files.addremove}
  11.158 +The \hgcmd{commit} command also provides a \hgopt{commit}{-A} option
  11.159 +that performs this same add-and-remove, immediately followed by a
  11.160 +commit.
  11.161 +\interaction{daily.files.commit-addremove}
  11.162 +
  11.163 +\section{Copying files}
  11.164 +
  11.165 +Mercurial provides a \hgcmd{copy} command that lets you make a new
  11.166 +copy of a file.  When you copy a file using this command, Mercurial
  11.167 +makes a record of the fact that the new file is a copy of the original
  11.168 +file.  It treats these copied files specially when you merge your work
  11.169 +with someone else's.
  11.170 +
  11.171 +\subsection{The results of copying during a merge}
  11.172 +
  11.173 +What happens during a merge is that changes ``follow'' a copy.  To
  11.174 +best illustrate what this means, let's create an example.  We'll start
  11.175 +with the usual tiny repository that contains a single file.
  11.176 +\interaction{daily.copy.init}
  11.177 +We need to do some work in parallel, so that we'll have something to
  11.178 +merge.  So let's clone our repository.
  11.179 +\interaction{daily.copy.clone}
  11.180 +Back in our initial repository, let's use the \hgcmd{copy} command to
  11.181 +make a copy of the first file we created.
  11.182 +\interaction{daily.copy.copy}
  11.183 +
  11.184 +If we look at the output of the \hgcmd{status} command afterwards, the
  11.185 +copied file looks just like a normal added file.
  11.186 +\interaction{daily.copy.status}
  11.187 +But if we pass the \hgopt{status}{-C} option to \hgcmd{status}, it
  11.188 +prints another line of output: this is the file that our newly-added
  11.189 +file was copied \emph{from}.
  11.190 +\interaction{daily.copy.status-copy}
  11.191 +
  11.192 +Now, back in the repository we cloned, let's make a change in
  11.193 +parallel.  We'll add a line of content to the original file that we
  11.194 +created.
  11.195 +\interaction{daily.copy.other}
  11.196 +Now we have a modified \filename{file} in this repository.  When we
  11.197 +pull the changes from the first repository, and merge the two heads,
  11.198 +Mercurial will propagate the changes that we made locally to
  11.199 +\filename{file} into its copy, \filename{new-file}.
  11.200 +\interaction{daily.copy.merge}
  11.201 +
  11.202 +\subsection{Why should changes follow copies?}
  11.203 +\label{sec:daily:why-copy}
  11.204 +
  11.205 +This behaviour, of changes to a file propagating out to copies of the
  11.206 +file, might seem esoteric, but in most cases it's highly desirable.
  11.207 +
  11.208 +First of all, remember that this propagation \emph{only} happens when
  11.209 +you merge.  So if you \hgcmd{copy} a file, and subsequently modify the
  11.210 +original file during the normal course of your work, nothing will
  11.211 +happen.
  11.212 +
  11.213 +The second thing to know is that modifications will only propagate
  11.214 +across a copy as long as the repository that you're pulling changes
  11.215 +from \emph{doesn't know} about the copy.
  11.216 +
  11.217 +The reason that Mercurial does this is as follows.  Let's say I make
  11.218 +an important bug fix in a source file, and commit my changes.
  11.219 +Meanwhile, you've decided to \hgcmd{copy} the file in your repository,
  11.220 +without knowing about the bug or having seen the fix, and you have
  11.221 +started hacking on your copy of the file.
  11.222 +
  11.223 +If you pulled and merged my changes, and Mercurial \emph{didn't}
  11.224 +propagate changes across copies, your source file would now contain
  11.225 +the bug, and unless you remembered to propagate the bug fix by hand,
  11.226 +the bug would \emph{remain} in your copy of the file.
  11.227 +
  11.228 +By automatically propagating the change that fixed the bug from the
  11.229 +original file to the copy, Mercurial prevents this class of problem.
  11.230 +To my knowledge, Mercurial is the \emph{only} revision control system
  11.231 +that propagates changes across copies like this.
  11.232 +
  11.233 +Once your change history has a record that the copy and subsequent
  11.234 +merge occurred, there's usually no further need to propagate changes
  11.235 +from the original file to the copied file, and that's why Mercurial
  11.236 +only propagates changes across copies until this point, and no
  11.237 +further.
  11.238 +
  11.239 +\subsection{How to make changes \emph{not} follow a copy}
  11.240 +
  11.241 +If, for some reason, you decide that this business of automatically
  11.242 +propagating changes across copies is not for you, simply use your
  11.243 +system's normal file copy command (on Unix-like systems, that's
  11.244 +\command{cp}) to make a copy of a file, then \hgcmd{add} the new copy
  11.245 +by hand.  Before you do so, though, please do reread
  11.246 +section~\ref{sec:daily:why-copy}, and make an informed decision that
  11.247 +this behaviour is not appropriate to your specific case.
  11.248 +
  11.249 +\subsection{Behaviour of the \hgcmd{copy} command}
  11.250 +
  11.251 +When you use the \hgcmd{copy} command, Mercurial makes a copy of each
  11.252 +source file as it currently stands in the working directory.  This
  11.253 +means that if you make some modifications to a file, then \hgcmd{copy}
  11.254 +it without first having committed those changes, the new copy will
  11.255 +also contain the modifications you have made up until that point.  (I
  11.256 +find this behaviour a little counterintuitive, which is why I mention
  11.257 +it here.)
  11.258 +
  11.259 +The \hgcmd{copy} command acts similarly to the Unix \command{cp}
  11.260 +command (you can use the \hgcmd{cp} alias if you prefer).  The last
  11.261 +argument is the \emph{destination}, and all prior arguments are
  11.262 +\emph{sources}.  If you pass it a single file as the source, and the
  11.263 +destination does not exist, it creates a new file with that name.
  11.264 +\interaction{daily.copy.simple}
  11.265 +If the destination is a directory, Mercurial copies its sources into
  11.266 +that directory.
  11.267 +\interaction{daily.copy.dir-dest}
  11.268 +Copying a directory is recursive, and preserves the directory
  11.269 +structure of the source.
  11.270 +\interaction{daily.copy.dir-src}
  11.271 +If the source and destination are both directories, the source tree is
  11.272 +recreated in the destination directory.
  11.273 +\interaction{daily.copy.dir-src-dest}
  11.274 +
  11.275 +As with the \hgcmd{rename} command, if you copy a file manually and
  11.276 +then want Mercurial to know that you've copied the file, simply use
  11.277 +the \hgopt{copy}{--after} option to \hgcmd{copy}.
  11.278 +\interaction{daily.copy.after}
  11.279 +
  11.280 +\section{Renaming files}
  11.281 +
  11.282 +It's rather more common to need to rename a file than to make a copy
  11.283 +of it.  The reason I discussed the \hgcmd{copy} command before talking
  11.284 +about renaming files is that Mercurial treats a rename in essentially
  11.285 +the same way as a copy.  Therefore, knowing what Mercurial does when
  11.286 +you copy a file tells you what to expect when you rename a file.
  11.287 +
  11.288 +When you use the \hgcmd{rename} command, Mercurial makes a copy of
  11.289 +each source file, then deletes it and marks the file as removed.
  11.290 +\interaction{daily.rename.rename}
  11.291 +The \hgcmd{status} command shows the newly copied file as added, and
  11.292 +the copied-from file as removed.
  11.293 +\interaction{daily.rename.status}
  11.294 +As with the results of a \hgcmd{copy}, we must use the
  11.295 +\hgopt{status}{-C} option to \hgcmd{status} to see that the added file
  11.296 +is really being tracked by Mercurial as a copy of the original, now
  11.297 +removed, file.
  11.298 +\interaction{daily.rename.status-copy}
  11.299 +
  11.300 +As with \hgcmd{remove} and \hgcmd{copy}, you can tell Mercurial about
  11.301 +a rename after the fact using the \hgopt{rename}{--after} option.  In
  11.302 +most other respects, the behaviour of the \hgcmd{rename} command, and
  11.303 +the options it accepts, are similar to the \hgcmd{copy} command.
  11.304 +
  11.305 +\subsection{Renaming files and merging changes}
  11.306 +
  11.307 +Since Mercurial's rename is implemented as copy-and-remove, the same
  11.308 +propagation of changes happens when you merge after a rename as after
  11.309 +a copy.
  11.310 +
  11.311 +If I modify a file, and you rename it to a new name, and then we merge
  11.312 +our respective changes, my modifications to the file under its
  11.313 +original name will be propagated into the file under its new name.
  11.314 +(This is something you might expect to ``simply work,'' but not all
  11.315 +revision control systems actually do this.)
  11.316 +
  11.317 +Whereas having changes follow a copy is a feature where you can
  11.318 +perhaps nod and say ``yes, that might be useful,'' it should be clear
  11.319 +that having them follow a rename is definitely important.  Without
  11.320 +this facility, it would simply be too easy for changes to become
  11.321 +orphaned when files are renamed.
  11.322 +
  11.323 +\subsection{Divergent renames and merging}
  11.324 +
  11.325 +The case of diverging names occurs when two developers start with a
  11.326 +file---let's call it \filename{foo}---in their respective
  11.327 +repositories.
  11.328 +
  11.329 +\interaction{rename.divergent.clone}
  11.330 +Anne renames the file to \filename{bar}.
  11.331 +\interaction{rename.divergent.rename.anne}
  11.332 +Meanwhile, Bob renames it to \filename{quux}.
  11.333 +\interaction{rename.divergent.rename.bob}
  11.334 +
  11.335 +I like to think of this as a conflict because each developer has
  11.336 +expressed different intentions about what the file ought to be named.
  11.337 +
  11.338 +What do you think should happen when they merge their work?
  11.339 +Mercurial's actual behaviour is that it always preserves \emph{both}
  11.340 +names when it merges changesets that contain divergent renames.
  11.341 +\interaction{rename.divergent.merge}
  11.342 +
  11.343 +Notice that Mercurial does warn about the divergent renames, but it
  11.344 +leaves it up to you to do something about the divergence after the merge.
  11.345 +
  11.346 +\subsection{Convergent renames and merging}
  11.347 +
  11.348 +Another kind of rename conflict occurs when two people choose to
  11.349 +rename different \emph{source} files to the same \emph{destination}.
  11.350 +In this case, Mercurial runs its normal merge machinery, and lets you
  11.351 +guide it to a suitable resolution.
  11.352 +
  11.353 +\subsection{Other name-related corner cases}
  11.354 +
  11.355 +Mercurial has a longstanding bug in which it fails to handle a merge
  11.356 +where one side has a file with a given name, while another has a
  11.357 +directory with the same name.  This is documented as~\bug{29}.
  11.358 +\interaction{issue29.go}
  11.359 +
  11.360 +\section{Recovering from mistakes}
  11.361 +
  11.362 +Mercurial has some useful commands that will help you to recover from
  11.363 +some common mistakes.
  11.364 +
  11.365 +The \hgcmd{revert} command lets you undo changes that you have made to
  11.366 +your working directory.  For example, if you \hgcmd{add} a file by
  11.367 +accident, just run \hgcmd{revert} with the name of the file you added,
  11.368 +and while the file won't be touched in any way, it won't be tracked
  11.369 +for adding by Mercurial any longer, either.  You can also use
  11.370 +\hgcmd{revert} to get rid of erroneous changes to a file.
  11.371 +
  11.372 +It's useful to remember that the \hgcmd{revert} command is useful for
  11.373 +changes that you have not yet committed.  Once you've committed a
  11.374 +change, if you decide it was a mistake, you can still do something
  11.375 +about it, though your options may be more limited.
  11.376 +
  11.377 +For more information about the \hgcmd{revert} command, and details
  11.378 +about how to deal with changes you have already committed, see
  11.379 +chapter~\ref{chap:undo}.
  11.380 +
  11.381 +%%% Local Variables: 
  11.382 +%%% mode: latex
  11.383 +%%% TeX-master: "00book"
  11.384 +%%% End: 
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/fr/examples/backout	Thu Feb 05 12:37:03 2009 +0100
    12.3 @@ -0,0 +1,83 @@
    12.4 +#!/bin/bash
    12.5 +
    12.6 +# We have to fake the merges here, because they cause conflicts with
    12.7 +# three-way command-line merge, and kdiff3 may not be available.
    12.8 +
    12.9 +export HGMERGE=$(mktemp)
   12.10 +echo '#!/bin/sh' >> $HGMERGE
   12.11 +echo 'echo first change > "$1"' >> $HGMERGE
   12.12 +echo 'echo third change >> "$1"' >> $HGMERGE
   12.13 +chmod 700 $HGMERGE
   12.14 +
   12.15 +#$ name: init
   12.16 +
   12.17 +hg init myrepo
   12.18 +cd myrepo
   12.19 +echo first change >> myfile
   12.20 +hg add myfile
   12.21 +hg commit -m 'first change'
   12.22 +echo second change >> myfile
   12.23 +hg commit -m 'second change'
   12.24 +
   12.25 +#$ name: simple
   12.26 +
   12.27 +hg backout -m 'back out second change' tip
   12.28 +cat myfile
   12.29 +
   12.30 +#$ name: simple.log
   12.31 +#$ ignore: \s+200[78]-.*
   12.32 +
   12.33 +hg log --style compact
   12.34 +
   12.35 +#$ name: non-tip.clone
   12.36 +
   12.37 +cd ..
   12.38 +hg clone -r1 myrepo non-tip-repo
   12.39 +cd non-tip-repo
   12.40 +
   12.41 +#$ name: non-tip.backout
   12.42 +
   12.43 +echo third change >> myfile
   12.44 +hg commit -m 'third change'
   12.45 +hg backout --merge -m 'back out second change' 1
   12.46 +
   12.47 +#$ name: non-tip.cat
   12.48 +cat myfile
   12.49 +
   12.50 +#$ name: manual.clone
   12.51 +
   12.52 +cd ..
   12.53 +hg clone -r1 myrepo newrepo
   12.54 +cd newrepo
   12.55 +
   12.56 +#$ name: manual.backout
   12.57 +
   12.58 +echo third change >> myfile
   12.59 +hg commit -m 'third change'
   12.60 +hg backout -m 'back out second change' 1
   12.61 +
   12.62 +#$ name: manual.log
   12.63 +
   12.64 +hg log --style compact
   12.65 +
   12.66 +#$ name: manual.parents
   12.67 +
   12.68 +hg parents
   12.69 +
   12.70 +#$ name: manual.heads
   12.71 +
   12.72 +hg heads
   12.73 +
   12.74 +#$ name: manual.cat
   12.75 +
   12.76 +cat myfile
   12.77 +
   12.78 +#$ name: manual.merge
   12.79 +
   12.80 +hg merge
   12.81 +hg commit -m 'merged backout with previous tip'
   12.82 +cat myfile
   12.83 +
   12.84 +#$ name:
   12.85 +
   12.86 +rm $HGMERGE
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/fr/examples/bisect	Thu Feb 05 12:37:03 2009 +0100
    13.3 @@ -0,0 +1,92 @@
    13.4 +#!/bin/bash
    13.5 +
    13.6 +if  hg -v | head -1 | grep -e "version 0.*"
    13.7 +then
    13.8 +#On mercurial 1.0 and later bisect is a builtin
    13.9 +echo '[extensions]' >> $HGRC
   13.10 +echo 'hbisect =' >> $HGRC
   13.11 +fi
   13.12 +
   13.13 +# XXX There's some kind of horrible nondeterminism in the execution of
   13.14 +# bisect at the moment.  Ugh.
   13.15 +
   13.16 +#$ ignore: .*
   13.17 +
   13.18 +#$ name: init
   13.19 +
   13.20 +hg init mybug
   13.21 +cd mybug
   13.22 +
   13.23 +#$ name: commits
   13.24 +
   13.25 +buggy_change=22
   13.26 +
   13.27 +for (( i = 0; i < 35; i++ )); do
   13.28 +  if [[ $i = $buggy_change ]]; then
   13.29 +    echo 'i have a gub' > myfile$i
   13.30 +    hg commit -q -A -m 'buggy changeset'
   13.31 +  else
   13.32 +    echo 'nothing to see here, move along' > myfile$i
   13.33 +    hg commit -q -A -m 'normal changeset'
   13.34 +  fi
   13.35 +done
   13.36 +
   13.37 +#$ name: help
   13.38 +
   13.39 +hg help bisect
   13.40 +
   13.41 +#$ name: search.init
   13.42 +
   13.43 +hg bisect init
   13.44 +
   13.45 +#$ name: search.bad-init
   13.46 +
   13.47 +hg bisect bad
   13.48 +
   13.49 +#$ name: search.good-init
   13.50 +
   13.51 +hg bisect good 10
   13.52 +
   13.53 +#$ name: search.step1
   13.54 +
   13.55 +if grep -q 'i have a gub' *
   13.56 +then
   13.57 +  result=bad
   13.58 +else
   13.59 +  result=good
   13.60 +fi
   13.61 +
   13.62 +echo this revision is $result
   13.63 +hg bisect --$result
   13.64 +
   13.65 +#$ name: search.mytest
   13.66 +
   13.67 +mytest() {
   13.68 +  if grep -q 'i have a gub' *
   13.69 +  then
   13.70 +    result=bad
   13.71 +  else
   13.72 +    result=good
   13.73 +  fi
   13.74 +
   13.75 +  echo this revision is $result
   13.76 +  hg bisect $result
   13.77 +}
   13.78 +  
   13.79 +#$ name: search.step2
   13.80 +
   13.81 +mytest
   13.82 +
   13.83 +#$ name: search.rest
   13.84 +
   13.85 +mytest
   13.86 +mytest
   13.87 +mytest
   13.88 +
   13.89 +#$ name: search.reset
   13.90 +
   13.91 +hg bisect reset
   13.92 +
   13.93 +#$ name:
   13.94 +
   13.95 +exit 0
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/fr/examples/branch-named	Thu Feb 05 12:37:03 2009 +0100
    14.3 @@ -0,0 +1,73 @@
    14.4 +#!/bin/bash
    14.5 +
    14.6 +hg init a
    14.7 +cd a
    14.8 +echo hello > myfile
    14.9 +hg commit -A -m 'Initial commit'
   14.10 +
   14.11 +#$ name: branches
   14.12 +
   14.13 +hg tip
   14.14 +hg branches
   14.15 +
   14.16 +#$ name: branch
   14.17 +
   14.18 +hg branch
   14.19 +
   14.20 +#$ name: create
   14.21 +
   14.22 +hg branch foo
   14.23 +hg branch
   14.24 +
   14.25 +#$ name: status
   14.26 +
   14.27 +hg status
   14.28 +hg tip
   14.29 +
   14.30 +#$ name: commit
   14.31 +
   14.32 +echo 'hello again' >> myfile
   14.33 +hg commit -m 'Second commit'
   14.34 +hg tip
   14.35 +
   14.36 +#$ name: rebranch
   14.37 +
   14.38 +hg branch
   14.39 +hg branch bar
   14.40 +echo new file > newfile
   14.41 +hg commit -A -m 'Third commit'
   14.42 +hg tip
   14.43 +
   14.44 +#$ name: parents
   14.45 +
   14.46 +hg parents
   14.47 +hg branches
   14.48 +
   14.49 +#$ name: update-switchy
   14.50 +
   14.51 +hg update foo
   14.52 +hg parents
   14.53 +hg update bar
   14.54 +hg parents
   14.55 +
   14.56 +#$ name: update-nothing
   14.57 +
   14.58 +hg update foo
   14.59 +hg update
   14.60 +
   14.61 +#$ name: foo-commit
   14.62 +
   14.63 +echo something > somefile
   14.64 +hg commit -A -m 'New file'
   14.65 +hg heads
   14.66 +
   14.67 +#$ name: update-bar
   14.68 +
   14.69 +hg update bar
   14.70 +
   14.71 +#$ name: merge
   14.72 +
   14.73 +hg branch
   14.74 +hg merge foo
   14.75 +hg commit -m 'Merge'
   14.76 +hg tip
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/fr/examples/branch-repo	Thu Feb 05 12:37:03 2009 +0100
    15.3 @@ -0,0 +1,48 @@
    15.4 +#!/bin/bash
    15.5 +
    15.6 +hg init myproject
    15.7 +cd myproject
    15.8 +echo hello > myfile
    15.9 +hg commit -A -m 'Initial commit'
   15.10 +cd ..
   15.11 +
   15.12 +#$ name: tag
   15.13 +
   15.14 +cd myproject
   15.15 +hg tag v1.0
   15.16 +
   15.17 +#$ name: clone
   15.18 +
   15.19 +cd ..
   15.20 +hg clone myproject myproject-1.0.1
   15.21 +
   15.22 +#$ name: bugfix
   15.23 +
   15.24 +hg clone myproject-1.0.1 my-1.0.1-bugfix
   15.25 +cd my-1.0.1-bugfix
   15.26 +echo 'I fixed a bug using only echo!' >> myfile
   15.27 +hg commit -m 'Important fix for 1.0.1'
   15.28 +#$ ignore: /tmp/branch-repo.*
   15.29 +hg push
   15.30 +
   15.31 +#$ name: new
   15.32 +
   15.33 +cd ..
   15.34 +hg clone myproject my-feature
   15.35 +cd my-feature
   15.36 +echo 'This sure is an exciting new feature!' > mynewfile
   15.37 +hg commit -A -m 'New feature'
   15.38 +hg push
   15.39 +
   15.40 +#$ name: pull
   15.41 +
   15.42 +cd ..
   15.43 +hg clone myproject myproject-merge
   15.44 +cd myproject-merge
   15.45 +hg pull ../myproject-1.0.1
   15.46 +
   15.47 +#$ name: merge
   15.48 +
   15.49 +hg merge
   15.50 +hg commit -m 'Merge bugfix from 1.0.1 branch'
   15.51 +hg push
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/fr/examples/branching	Thu Feb 05 12:37:03 2009 +0100
    16.3 @@ -0,0 +1,63 @@
    16.4 +#!/bin/bash
    16.5 +
    16.6 +#$ name: init
    16.7 +
    16.8 +hg init main
    16.9 +cd main
   16.10 +echo 'This is a boring feature.' > myfile
   16.11 +hg commit -A -m 'We have reached an important milestone!'
   16.12 +
   16.13 +#$ name: tag
   16.14 +
   16.15 +hg tag v1.0
   16.16 +hg tip
   16.17 +hg tags
   16.18 +
   16.19 +#$ name: main
   16.20 +
   16.21 +cd ../main
   16.22 +echo 'This is exciting and new!' >> myfile
   16.23 +hg commit -m 'Add a new feature'
   16.24 +cat myfile
   16.25 +
   16.26 +#$ name: update
   16.27 +
   16.28 +cd ..
   16.29 +hg clone -U main main-old
   16.30 +cd main-old
   16.31 +hg update v1.0
   16.32 +cat myfile
   16.33 +
   16.34 +#$ name: clone
   16.35 +
   16.36 +cd ..
   16.37 +hg clone -rv1.0 main stable
   16.38 +
   16.39 +#$ name: stable
   16.40 +
   16.41 +hg clone stable stable-fix
   16.42 +cd stable-fix
   16.43 +echo 'This is a fix to a boring feature.' > myfile
   16.44 +hg commit -m 'Fix a bug'
   16.45 +#$ ignore: /tmp/branching.*
   16.46 +hg push
   16.47 +
   16.48 +#$ name:
   16.49 +
   16.50 +export HGMERGE=$(mktemp)
   16.51 +echo '#!/bin/sh' > $HGMERGE
   16.52 +echo 'echo "This is a fix to a boring feature." > "$1"' >> $HGMERGE
   16.53 +echo 'echo "This is exciting and new!" >> "$1"' >> $HGMERGE
   16.54 +chmod 700 $HGMERGE
   16.55 +
   16.56 +#$ name: merge
   16.57 +
   16.58 +cd ../main
   16.59 +hg pull ../stable
   16.60 +hg merge
   16.61 +hg commit -m 'Bring in bugfix from stable branch'
   16.62 +cat myfile
   16.63 +
   16.64 +#$ name:
   16.65 +
   16.66 +rm $HGMERGE
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/fr/examples/cmdref	Thu Feb 05 12:37:03 2009 +0100
    17.3 @@ -0,0 +1,22 @@
    17.4 +#!/bin/bash
    17.5 +
    17.6 +hg init diff
    17.7 +cd diff
    17.8 +cat > myfile.c <<EOF
    17.9 +int myfunc()
   17.10 +{
   17.11 +    return 1;
   17.12 +}
   17.13 +EOF
   17.14 +hg ci -Ama
   17.15 +
   17.16 +sed -ie 's/return 1/return 10/' myfile.c
   17.17 +
   17.18 +#$ name: diff-p
   17.19 +
   17.20 +echo '[diff]' >> $HGRC
   17.21 +echo 'showfunc = False' >> $HGRC
   17.22 +
   17.23 +hg diff
   17.24 +
   17.25 +hg diff -p
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/fr/examples/daily.copy	Thu Feb 05 12:37:03 2009 +0100
    18.3 @@ -0,0 +1,82 @@
    18.4 +#!/bin/bash
    18.5 +
    18.6 +#$ name: init
    18.7 +
    18.8 +hg init my-copy
    18.9 +cd my-copy
   18.10 +echo line > file
   18.11 +hg add file
   18.12 +hg commit -m 'Added a file'
   18.13 +
   18.14 +#$ name: clone
   18.15 +
   18.16 +cd ..
   18.17 +hg clone my-copy your-copy
   18.18 +
   18.19 +#$ name: copy
   18.20 +
   18.21 +cd my-copy
   18.22 +hg copy file new-file
   18.23 +
   18.24 +#$ name: status
   18.25 +
   18.26 +hg status
   18.27 +
   18.28 +#$ name: status-copy
   18.29 +
   18.30 +hg status -C
   18.31 +hg commit -m 'Copied file'
   18.32 +
   18.33 +#$ name: other
   18.34 +
   18.35 +cd ../your-copy
   18.36 +echo 'new contents' >> file
   18.37 +hg commit -m 'Changed file'
   18.38 +
   18.39 +#$ name: cat
   18.40 +
   18.41 +cat file
   18.42 +cat ../my-copy/new-file
   18.43 +
   18.44 +#$ name: merge
   18.45 +
   18.46 +hg pull ../my-copy
   18.47 +hg merge
   18.48 +cat new-file
   18.49 +
   18.50 +#$ name:
   18.51 +
   18.52 +cd ..
   18.53 +hg init copy-example
   18.54 +cd copy-example
   18.55 +echo a > a
   18.56 +echo b > b
   18.57 +mkdir c
   18.58 +mkdir c/a
   18.59 +echo c > c/a/c
   18.60 +hg ci -Ama
   18.61 +
   18.62 +#$ name: simple
   18.63 +
   18.64 +mkdir k
   18.65 +hg copy a k
   18.66 +ls k
   18.67 +
   18.68 +#$ name: dir-dest
   18.69 +
   18.70 +mkdir d
   18.71 +hg copy a b d
   18.72 +ls d
   18.73 +
   18.74 +#$ name: dir-src
   18.75 +
   18.76 +hg copy c e
   18.77 +
   18.78 +#$ name: dir-src-dest
   18.79 +
   18.80 +hg copy c d
   18.81 +
   18.82 +#$ name: after
   18.83 +
   18.84 +cp a z
   18.85 +hg copy --after a z
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/fr/examples/daily.files	Thu Feb 05 12:37:03 2009 +0100
    19.3 @@ -0,0 +1,93 @@
    19.4 +#!/bin/bash
    19.5 +
    19.6 +#$ name: add
    19.7 +
    19.8 +hg init add-example
    19.9 +cd add-example
   19.10 +echo a > a
   19.11 +hg status
   19.12 +hg add a
   19.13 +hg status
   19.14 +hg commit -m 'Added one file'
   19.15 +hg status
   19.16 +
   19.17 +#$ name: add-dir
   19.18 +
   19.19 +mkdir b
   19.20 +echo b > b/b
   19.21 +echo c > b/c
   19.22 +mkdir b/d
   19.23 +echo d > b/d/d
   19.24 +hg add b
   19.25 +hg commit -m 'Added all files in subdirectory'
   19.26 +
   19.27 +#$ name:
   19.28 +
   19.29 +cd ..
   19.30 +
   19.31 +#$ name: hidden
   19.32 +
   19.33 +hg init hidden-example
   19.34 +cd hidden-example
   19.35 +mkdir empty
   19.36 +touch empty/.hidden
   19.37 +hg add empty/.hidden
   19.38 +hg commit -m 'Manage an empty-looking directory'
   19.39 +ls empty
   19.40 +cd ..
   19.41 +hg clone hidden-example tmp
   19.42 +ls tmp
   19.43 +ls tmp/empty
   19.44 +
   19.45 +#$ name: remove
   19.46 +
   19.47 +hg init remove-example
   19.48 +cd remove-example
   19.49 +echo a > a
   19.50 +mkdir b
   19.51 +echo b > b/b
   19.52 +hg add a b
   19.53 +hg commit -m 'Small example for file removal'
   19.54 +hg remove a
   19.55 +hg status
   19.56 +hg remove b
   19.57 +
   19.58 +#$ name:
   19.59 +
   19.60 +cd ..
   19.61 +
   19.62 +#$ name: missing
   19.63 +hg init missing-example
   19.64 +cd missing-example
   19.65 +echo a > a
   19.66 +hg add a
   19.67 +hg commit -m 'File about to be missing'
   19.68 +rm a
   19.69 +hg status
   19.70 +
   19.71 +#$ name: remove-after
   19.72 +
   19.73 +hg remove --after a
   19.74 +hg status
   19.75 +
   19.76 +#$ name: recover-missing
   19.77 +hg revert a
   19.78 +cat a
   19.79 +hg status
   19.80 +
   19.81 +#$ name:
   19.82 +
   19.83 +cd ..
   19.84 +
   19.85 +#$ name: addremove
   19.86 +
   19.87 +hg init addremove-example
   19.88 +cd addremove-example
   19.89 +echo a > a
   19.90 +echo b > b
   19.91 +hg addremove
   19.92 +
   19.93 +#$ name: commit-addremove
   19.94 +
   19.95 +echo c > c
   19.96 +hg commit -A -m 'Commit with addremove'
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/fr/examples/daily.rename	Thu Feb 05 12:37:03 2009 +0100
    20.3 @@ -0,0 +1,18 @@
    20.4 +#!/bin/bash
    20.5 +
    20.6 +hg init a
    20.7 +cd a
    20.8 +echo a > a
    20.9 +hg ci -Ama
   20.10 +
   20.11 +#$ name: rename
   20.12 +
   20.13 +hg rename a b
   20.14 +
   20.15 +#$ name: status
   20.16 +
   20.17 +hg status
   20.18 +
   20.19 +#$ name: status-copy
   20.20 +
   20.21 +hg status -C
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/fr/examples/daily.revert	Thu Feb 05 12:37:03 2009 +0100
    21.3 @@ -0,0 +1,74 @@
    21.4 +#!/bin/bash
    21.5 +
    21.6 +hg init a
    21.7 +cd a
    21.8 +echo 'original content' > file
    21.9 +hg ci -Ama
   21.10 +
   21.11 +#$ name: modify
   21.12 +
   21.13 +cat file
   21.14 +echo unwanted change >> file
   21.15 +hg diff file
   21.16 +
   21.17 +#$ name: unmodify
   21.18 +
   21.19 +hg status
   21.20 +hg revert file
   21.21 +cat file
   21.22 +
   21.23 +#$ name: status
   21.24 +
   21.25 +hg status
   21.26 +cat file.orig
   21.27 +
   21.28 +#$ name:
   21.29 +
   21.30 +rm file.orig
   21.31 +
   21.32 +#$ name: add
   21.33 +
   21.34 +echo oops > oops
   21.35 +hg add oops
   21.36 +hg status oops
   21.37 +hg revert oops
   21.38 +hg status
   21.39 +
   21.40 +#$ name:
   21.41 +
   21.42 +rm oops
   21.43 +
   21.44 +#$ name: remove
   21.45 +
   21.46 +hg remove file
   21.47 +hg status
   21.48 +hg revert file
   21.49 +hg status
   21.50 +ls file
   21.51 +
   21.52 +#$ name: missing
   21.53 +
   21.54 +rm file
   21.55 +hg status
   21.56 +hg revert file
   21.57 +ls file
   21.58 +
   21.59 +#$ name: copy
   21.60 +
   21.61 +hg copy file new-file
   21.62 +hg revert new-file
   21.63 +hg status
   21.64 +
   21.65 +#$ name:
   21.66 +
   21.67 +rm new-file
   21.68 +
   21.69 +#$ name: rename
   21.70 +
   21.71 +hg rename file new-file
   21.72 +hg revert new-file
   21.73 +hg status
   21.74 +
   21.75 +#$ name: rename-orig
   21.76 +hg revert file
   21.77 +hg status
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/fr/examples/data/check_whitespace.py	Thu Feb 05 12:37:03 2009 +0100
    22.3 @@ -0,0 +1,44 @@
    22.4 +#!/usr/bin/python
    22.5 +
    22.6 +import re
    22.7 +
    22.8 +def trailing_whitespace(difflines):
    22.9 +    added, linenum, header = [], 0, False
   22.10 +
   22.11 +    for line in difflines:
   22.12 +        if header:
   22.13 +            # remember the name of the file that this diff affects
   22.14 +            m = re.match(r'(?:---|\+\+\+) ([^\t]+)', line)
   22.15 +            if m and m.group(1) != '/dev/null':
   22.16 +                filename = m.group(1).split('/', 1)[-1]
   22.17 +            if line.startswith('+++ '):
   22.18 +                header = False
   22.19 +            continue
   22.20 +        if line.startswith('diff '):
   22.21 +            header = True
   22.22 +            continue
   22.23 +        # hunk header - save the line number
   22.24 +        m = re.match(r'@@ -\d+,\d+ \+(\d+),', line)
   22.25 +        if m:
   22.26 +            linenum = int(m.group(1))
   22.27 +            continue
   22.28 +        # hunk body - check for an added line with trailing whitespace
   22.29 +        m = re.match(r'\+.*\s$', line)
   22.30 +        if m:
   22.31 +            added.append((filename, linenum))
   22.32 +        if line and line[0] in ' +':
   22.33 +            linenum += 1
   22.34 +    return added
   22.35 +
   22.36 +if __name__ == '__main__':
   22.37 +    import os, sys
   22.38 +    
   22.39 +    added = trailing_whitespace(os.popen('hg export tip'))
   22.40 +    if added:
   22.41 +        for filename, linenum in added:
   22.42 +            print >> sys.stderr, ('%s, line %d: trailing whitespace added' %
   22.43 +                                  (filename, linenum))
   22.44 +        # save the commit message so we don't need to retype it
   22.45 +        os.system('hg tip --template "{desc}" > .hg/commit.save')
   22.46 +        print >> sys.stderr, 'commit message saved to .hg/commit.save'
   22.47 +        sys.exit(1)
    23.1 Binary file fr/examples/data/netplug-1.2.5.tar.bz2 has changed
    24.1 Binary file fr/examples/data/netplug-1.2.8.tar.bz2 has changed
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/fr/examples/data/remove-redundant-null-checks.patch	Thu Feb 05 12:37:03 2009 +0100
    25.3 @@ -0,0 +1,190 @@
    25.4 +
    25.5 +From: Jesper Juhl <jesper.juhl@gmail.com>
    25.6 +
    25.7 +Remove redundant NULL chck before kfree + tiny CodingStyle cleanup for
    25.8 +drivers/
    25.9 +
   25.10 +Signed-off-by: Jesper Juhl <jesper.juhl@gmail.com>
   25.11 +Signed-off-by: Andrew Morton <akpm@osdl.org>
   25.12 +---
   25.13 +
   25.14 + drivers/char/agp/sgi-agp.c        |    5 ++---
   25.15 + drivers/char/hvcs.c               |   11 +++++------
   25.16 + drivers/message/fusion/mptfc.c    |    6 ++----
   25.17 + drivers/message/fusion/mptsas.c   |    3 +--
   25.18 + drivers/net/fs_enet/fs_enet-mii.c |    3 +--
   25.19 + drivers/net/wireless/ipw2200.c    |   22 ++++++----------------
   25.20 + drivers/scsi/libata-scsi.c        |    4 +---
   25.21 + drivers/video/au1100fb.c          |    3 +--
   25.22 + 8 files changed, 19 insertions(+), 38 deletions(-)
   25.23 +
   25.24 +diff -puN drivers/char/agp/sgi-agp.c~remove-redundant-null-checks-before-free-in-drivers drivers/char/agp/sgi-agp.c
   25.25 +--- a/drivers/char/agp/sgi-agp.c~remove-redundant-null-checks-before-free-in-drivers
   25.26 ++++ a/drivers/char/agp/sgi-agp.c
   25.27 +@@ -329,9 +329,8 @@ static int __devinit agp_sgi_init(void)
   25.28 + 
   25.29 + static void __devexit agp_sgi_cleanup(void)
   25.30 + {
   25.31 +-	if (sgi_tioca_agp_bridges)
   25.32 +-		kfree(sgi_tioca_agp_bridges);
   25.33 +-	sgi_tioca_agp_bridges=NULL;
   25.34 ++	kfree(sgi_tioca_agp_bridges);
   25.35 ++	sgi_tioca_agp_bridges = NULL;
   25.36 + }
   25.37 + 
   25.38 + module_init(agp_sgi_init);
   25.39 +diff -puN drivers/char/hvcs.c~remove-redundant-null-checks-before-free-in-drivers drivers/char/hvcs.c
   25.40 +--- a/drivers/char/hvcs.c~remove-redundant-null-checks-before-free-in-drivers
   25.41 ++++ a/drivers/char/hvcs.c
   25.42 +@@ -1320,11 +1320,12 @@ static struct tty_operations hvcs_ops = 
   25.43 + static int hvcs_alloc_index_list(int n)
   25.44 + {
   25.45 + 	int i;
   25.46 ++
   25.47 + 	hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
   25.48 + 	if (!hvcs_index_list)
   25.49 + 		return -ENOMEM;
   25.50 + 	hvcs_index_count = n;
   25.51 +-	for(i = 0; i < hvcs_index_count; i++)
   25.52 ++	for (i = 0; i < hvcs_index_count; i++)
   25.53 + 		hvcs_index_list[i] = -1;
   25.54 + 	return 0;
   25.55 + }
   25.56 +@@ -1332,11 +1333,9 @@ static int hvcs_alloc_index_list(int n)
   25.57 + static void hvcs_free_index_list(void)
   25.58 + {
   25.59 + 	/* Paranoia check to be thorough. */
   25.60 +-	if (hvcs_index_list) {
   25.61 +-		kfree(hvcs_index_list);
   25.62 +-		hvcs_index_list = NULL;
   25.63 +-		hvcs_index_count = 0;
   25.64 +-	}
   25.65 ++	kfree(hvcs_index_list);
   25.66 ++	hvcs_index_list = NULL;
   25.67 ++	hvcs_index_count = 0;
   25.68 + }
   25.69 + 
   25.70 + static int __init hvcs_module_init(void)
   25.71 +diff -puN drivers/message/fusion/mptfc.c~remove-redundant-null-checks-before-free-in-drivers drivers/message/fusion/mptfc.c
   25.72 +--- a/drivers/message/fusion/mptfc.c~remove-redundant-null-checks-before-free-in-drivers
   25.73 ++++ a/drivers/message/fusion/mptfc.c
   25.74 +@@ -305,10 +305,8 @@ mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, in
   25.75 + 	}
   25.76 + 
   25.77 +  out:
   25.78 +-	if (pp0_array)
   25.79 +-		kfree(pp0_array);
   25.80 +-	if (p0_array)
   25.81 +-		kfree(p0_array);
   25.82 ++	kfree(pp0_array);
   25.83 ++	kfree(p0_array);
   25.84 + 	return rc;
   25.85 + }
   25.86 + 
   25.87 +diff -puN drivers/message/fusion/mptsas.c~remove-redundant-null-checks-before-free-in-drivers drivers/message/fusion/mptsas.c
   25.88 +--- a/drivers/message/fusion/mptsas.c~remove-redundant-null-checks-before-free-in-drivers
   25.89 ++++ a/drivers/message/fusion/mptsas.c
   25.90 +@@ -1378,8 +1378,7 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
   25.91 + 	return 0;
   25.92 + 
   25.93 +  out_free_port_info:
   25.94 +-	if (hba)
   25.95 +-		kfree(hba);
   25.96 ++	kfree(hba);
   25.97 +  out:
   25.98 + 	return error;
   25.99 + }
  25.100 +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
  25.101 +--- a/drivers/net/fs_enet/fs_enet-mii.c~remove-redundant-null-checks-before-free-in-drivers
  25.102 ++++ a/drivers/net/fs_enet/fs_enet-mii.c
  25.103 +@@ -431,8 +431,7 @@ static struct fs_enet_mii_bus *create_bu
  25.104 + 	return bus;
  25.105 + 
  25.106 + err:
  25.107 +-	if (bus)
  25.108 +-		kfree(bus);
  25.109 ++	kfree(bus);
  25.110 + 	return ERR_PTR(ret);
  25.111 + }
  25.112 + 
  25.113 +diff -puN drivers/net/wireless/ipw2200.c~remove-redundant-null-checks-before-free-in-drivers drivers/net/wireless/ipw2200.c
  25.114 +--- a/drivers/net/wireless/ipw2200.c~remove-redundant-null-checks-before-free-in-drivers
  25.115 ++++ a/drivers/net/wireless/ipw2200.c
  25.116 +@@ -1229,12 +1229,6 @@ static struct ipw_fw_error *ipw_alloc_er
  25.117 + 	return error;
  25.118 + }
  25.119 + 
  25.120 +-static void ipw_free_error_log(struct ipw_fw_error *error)
  25.121 +-{
  25.122 +-	if (error)
  25.123 +-		kfree(error);
  25.124 +-}
  25.125 +-
  25.126 + static ssize_t show_event_log(struct device *d,
  25.127 + 			      struct device_attribute *attr, char *buf)
  25.128 + {
  25.129 +@@ -1296,10 +1290,9 @@ static ssize_t clear_error(struct device
  25.130 + 			   const char *buf, size_t count)
  25.131 + {
  25.132 + 	struct ipw_priv *priv = dev_get_drvdata(d);
  25.133 +-	if (priv->error) {
  25.134 +-		ipw_free_error_log(priv->error);
  25.135 +-		priv->error = NULL;
  25.136 +-	}
  25.137 ++
  25.138 ++	kfree(priv->error);
  25.139 ++	priv->error = NULL;
  25.140 + 	return count;
  25.141 + }
  25.142 + 
  25.143 +@@ -1970,8 +1963,7 @@ static void ipw_irq_tasklet(struct ipw_p
  25.144 + 				struct ipw_fw_error *error =
  25.145 + 				    ipw_alloc_error_log(priv);
  25.146 + 				ipw_dump_error_log(priv, error);
  25.147 +-				if (error)
  25.148 +-					ipw_free_error_log(error);
  25.149 ++				kfree(error);
  25.150 + 			}
  25.151 + #endif
  25.152 + 		} else {
  25.153 +@@ -11693,10 +11685,8 @@ static void ipw_pci_remove(struct pci_de
  25.154 + 		}
  25.155 + 	}
  25.156 + 
  25.157 +-	if (priv->error) {
  25.158 +-		ipw_free_error_log(priv->error);
  25.159 +-		priv->error = NULL;
  25.160 +-	}
  25.161 ++	kfree(priv->error);
  25.162 ++	priv->error = NULL;
  25.163 + 
  25.164 + #ifdef CONFIG_IPW2200_PROMISCUOUS
  25.165 + 	ipw_prom_free(priv);
  25.166 +diff -puN drivers/scsi/libata-scsi.c~remove-redundant-null-checks-before-free-in-drivers drivers/scsi/libata-scsi.c
  25.167 +--- a/drivers/scsi/libata-scsi.c~remove-redundant-null-checks-before-free-in-drivers
  25.168 ++++ a/drivers/scsi/libata-scsi.c
  25.169 +@@ -222,9 +222,7 @@ int ata_cmd_ioctl(struct scsi_device *sc
  25.170 + 	 && copy_to_user(arg + sizeof(args), argbuf, argsize))
  25.171 + 		rc = -EFAULT;
  25.172 + error:
  25.173 +-	if (argbuf)
  25.174 +-		kfree(argbuf);
  25.175 +-
  25.176 ++	kfree(argbuf);
  25.177 + 	return rc;
  25.178 + }
  25.179 + 
  25.180 +diff -puN drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers drivers/video/au1100fb.c
  25.181 +--- a/drivers/video/au1100fb.c~remove-redundant-null-checks-before-free-in-drivers
  25.182 ++++ a/drivers/video/au1100fb.c
  25.183 +@@ -743,8 +743,7 @@ void __exit au1100fb_cleanup(void)
  25.184 + {
  25.185 + 	driver_unregister(&au1100fb_driver);
  25.186 + 
  25.187 +-	if (drv_info.opt_mode)
  25.188 +-		kfree(drv_info.opt_mode);
  25.189 ++	kfree(drv_info.opt_mode);
  25.190 + }
  25.191 + 
  25.192 + module_init(au1100fb_init);
  25.193 +_
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/fr/examples/extdiff	Thu Feb 05 12:37:03 2009 +0100
    26.3 @@ -0,0 +1,28 @@
    26.4 +#!/bin/bash
    26.5 +
    26.6 +echo '[extensions]' >> $HGRC
    26.7 +echo 'extdiff =' >> $HGRC
    26.8 +
    26.9 +hg init a
   26.10 +cd a
   26.11 +echo 'The first line.' > myfile
   26.12 +hg ci -Ama
   26.13 +echo 'The second line.' >> myfile
   26.14 +
   26.15 +#$ name: diff
   26.16 +
   26.17 +hg diff
   26.18 +
   26.19 +#$ name: extdiff
   26.20 +
   26.21 +hg extdiff
   26.22 +
   26.23 +#$ name: extdiff-ctx
   26.24 +
   26.25 +#$ ignore: ^\*\*\* a.*
   26.26 +
   26.27 +hg extdiff -o -NprcC5
   26.28 +
   26.29 +#$ name:
   26.30 +
   26.31 +exit 0
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/fr/examples/filenames	Thu Feb 05 12:37:03 2009 +0100
    27.3 @@ -0,0 +1,61 @@
    27.4 +#!/bin/bash
    27.5 +
    27.6 +hg init a
    27.7 +cd a
    27.8 +mkdir -p examples src/watcher
    27.9 +touch COPYING MANIFEST.in README setup.py
   27.10 +touch examples/performant.py examples/simple.py
   27.11 +touch src/main.py src/watcher/_watcher.c src/watcher/watcher.py src/xyzzy.txt
   27.12 +
   27.13 +#$ name: files
   27.14 +
   27.15 +hg add COPYING README examples/simple.py
   27.16 +
   27.17 +#$ name: dirs
   27.18 +
   27.19 +hg status src
   27.20 +
   27.21 +#$ name: wdir-subdir
   27.22 +
   27.23 +cd src
   27.24 +hg add -n
   27.25 +hg add -n .
   27.26 +
   27.27 +#$ name: wdir-relname
   27.28 +
   27.29 +hg status
   27.30 +hg status `hg root`
   27.31 +
   27.32 +#$ name: glob.star
   27.33 +
   27.34 +hg add 'glob:*.py'
   27.35 +
   27.36 +#$ name: glob.starstar
   27.37 +
   27.38 +cd ..
   27.39 +hg status 'glob:**.py'
   27.40 +
   27.41 +#$ name: glob.star-starstar
   27.42 +
   27.43 +hg status 'glob:*.py'
   27.44 +hg status 'glob:**.py'
   27.45 +
   27.46 +#$ name: glob.question
   27.47 +
   27.48 +hg status 'glob:**.?'
   27.49 +
   27.50 +#$ name: glob.range
   27.51 +
   27.52 +hg status 'glob:**[nr-t]'
   27.53 +
   27.54 +#$ name: glob.group
   27.55 +
   27.56 +hg status 'glob:*.{in,py}'
   27.57 +
   27.58 +#$ name: filter.include
   27.59 +
   27.60 +hg status -I '*.in'
   27.61 +
   27.62 +#$ name: filter.exclude
   27.63 +
   27.64 +hg status -X '**.py' src
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/fr/examples/hook.msglen	Thu Feb 05 12:37:03 2009 +0100
    28.3 @@ -0,0 +1,14 @@
    28.4 +#!/bin/sh
    28.5 +
    28.6 +hg init a
    28.7 +cd a
    28.8 +echo '[hooks]' > .hg/hgrc
    28.9 +echo 'pretxncommit.msglen = test `hg tip --template {desc} | wc -c` -ge 10' >> .hg/hgrc
   28.10 +
   28.11 +#$ name: go
   28.12 +
   28.13 +cat .hg/hgrc
   28.14 +echo a > a
   28.15 +hg add a
   28.16 +hg commit -A -m 'too short'
   28.17 +hg commit -A -m 'long enough'
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/fr/examples/hook.simple	Thu Feb 05 12:37:03 2009 +0100
    29.3 @@ -0,0 +1,37 @@
    29.4 +#!/bin/bash
    29.5 +
    29.6 +#$ name: init
    29.7 +
    29.8 +hg init hook-test
    29.9 +cd hook-test
   29.10 +echo '[hooks]' >> .hg/hgrc
   29.11 +echo 'commit = echo committed $HG_NODE' >> .hg/hgrc
   29.12 +cat .hg/hgrc
   29.13 +echo a > a
   29.14 +hg add a
   29.15 +hg commit -m 'testing commit hook'
   29.16 +
   29.17 +#$ name: ext
   29.18 +#$ ignore: ^date of commit.*
   29.19 +
   29.20 +echo 'commit.when = echo -n "date of commit: "; date' >> .hg/hgrc
   29.21 +echo a >> a
   29.22 +hg commit -m 'i have two hooks'
   29.23 +
   29.24 +#$ name:
   29.25 +
   29.26 +echo '#!/bin/sh' >> check_bug_id
   29.27 +echo '# check that a commit comment mentions a numeric bug id' >> check_bug_id
   29.28 +echo 'hg log -r $1 --template {desc} | grep -q "\<bug *[0-9]"' >> check_bug_id
   29.29 +chmod +x check_bug_id
   29.30 +
   29.31 +#$ name: pretxncommit
   29.32 +
   29.33 +cat check_bug_id
   29.34 +
   29.35 +echo 'pretxncommit.bug_id_required = ./check_bug_id $HG_NODE' >> .hg/hgrc
   29.36 +
   29.37 +echo a >> a
   29.38 +hg commit -m 'i am not mentioning a bug id'
   29.39 +
   29.40 +hg commit -m 'i refer you to bug 666'
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/fr/examples/hook.ws	Thu Feb 05 12:37:03 2009 +0100
    30.3 @@ -0,0 +1,31 @@
    30.4 +#!/bin/bash
    30.5 +
    30.6 +hg init a
    30.7 +cd a
    30.8 +echo '[hooks]' > .hg/hgrc
    30.9 +echo "pretxncommit.whitespace = hg export tip | (! egrep -q '^\\+.*[ \\t]$')" >> .hg/hgrc
   30.10 +
   30.11 +#$ name: simple
   30.12 +
   30.13 +cat .hg/hgrc
   30.14 +echo 'a ' > a
   30.15 +hg commit -A -m 'test with trailing whitespace'
   30.16 +echo 'a' > a
   30.17 +hg commit -A -m 'drop trailing whitespace and try again'
   30.18 +
   30.19 +#$ name:
   30.20 +
   30.21 +echo '[hooks]' > .hg/hgrc
   30.22 +echo "pretxncommit.whitespace = .hg/check_whitespace.py" >> .hg/hgrc
   30.23 +cp $EXAMPLE_DIR/data/check_whitespace.py .hg
   30.24 +
   30.25 +#$ name: better
   30.26 +
   30.27 +cat .hg/hgrc
   30.28 +echo 'a ' >> a
   30.29 +hg commit -A -m 'add new line with trailing whitespace'
   30.30 +sed -i 's, *$,,' a
   30.31 +hg commit -A -m 'trimmed trailing whitespace'
   30.32 +
   30.33 +#$ name:
   30.34 +exit 0
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/fr/examples/issue29	Thu Feb 05 12:37:03 2009 +0100
    31.3 @@ -0,0 +1,22 @@
    31.4 +#!/bin/bash
    31.5 +
    31.6 +#$ name: go
    31.7 +
    31.8 +hg init issue29
    31.9 +cd issue29
   31.10 +echo a > a
   31.11 +hg ci -Ama
   31.12 +echo b > b
   31.13 +hg ci -Amb
   31.14 +hg up 0
   31.15 +mkdir b
   31.16 +echo b > b/b
   31.17 +hg ci -Amc
   31.18 +
   31.19 +#$ ignore: abort: Is a directory: .*
   31.20 +hg merge
   31.21 +
   31.22 +#$ name:
   31.23 +# This error is expected from the failed merge.
   31.24 +
   31.25 +exit 0
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/fr/examples/mq.dodiff	Thu Feb 05 12:37:03 2009 +0100
    32.3 @@ -0,0 +1,14 @@
    32.4 +#!/bin/bash
    32.5 +
    32.6 +#$ name: diff
    32.7 +
    32.8 +echo 'this is my original thought' > oldfile
    32.9 +echo 'i have changed my mind' > newfile
   32.10 +
   32.11 +diff -u oldfile newfile > tiny.patch
   32.12 +
   32.13 +cat tiny.patch
   32.14 +
   32.15 +patch < tiny.patch
   32.16 +
   32.17 +cat oldfile
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/fr/examples/mq.guards	Thu Feb 05 12:37:03 2009 +0100
    33.3 @@ -0,0 +1,67 @@
    33.4 +#!/bin/bash
    33.5 +
    33.6 +echo '[extensions]' >> $HGRC
    33.7 +echo 'hgext.mq =' >> $HGRC
    33.8 +
    33.9 +hg init a
   33.10 +cd a
   33.11 +
   33.12 +#$ name: init
   33.13 +
   33.14 +hg qinit
   33.15 +hg qnew hello.patch
   33.16 +echo hello > hello
   33.17 +hg add hello
   33.18 +hg qrefresh
   33.19 +hg qnew goodbye.patch
   33.20 +echo goodbye > goodbye
   33.21 +hg add goodbye
   33.22 +hg qrefresh
   33.23 +
   33.24 +#$ name: qguard
   33.25 +
   33.26 +hg qguard
   33.27 +
   33.28 +#$ name: qguard.pos
   33.29 +
   33.30 +hg qguard +foo
   33.31 +hg qguard
   33.32 +
   33.33 +#$ name: qguard.neg
   33.34 +
   33.35 +hg qguard hello.patch -quux
   33.36 +hg qguard hello.patch
   33.37 +
   33.38 +#$ name: series
   33.39 +
   33.40 +cat .hg/patches/series
   33.41 +
   33.42 +#$ name: qselect.foo
   33.43 +
   33.44 +hg qpop -a
   33.45 +hg qselect
   33.46 +hg qselect foo
   33.47 +hg qselect
   33.48 +
   33.49 +#$ name: qselect.cat
   33.50 +
   33.51 +cat .hg/patches/guards
   33.52 +
   33.53 +#$ name: qselect.qpush
   33.54 +hg qpush -a
   33.55 +
   33.56 +#$ name: qselect.error
   33.57 +
   33.58 +hg qselect +foo
   33.59 +
   33.60 +#$ name: qselect.quux
   33.61 +
   33.62 +hg qselect quux
   33.63 +hg qpop -a
   33.64 +hg qpush -a
   33.65 +
   33.66 +#$ name: qselect.foobar
   33.67 +
   33.68 +hg qselect foo bar
   33.69 +hg qpop -a
   33.70 +hg qpush -a
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/fr/examples/mq.id	Thu Feb 05 12:37:03 2009 +0100
    34.3 @@ -0,0 +1,28 @@
    34.4 +#!/bin/sh
    34.5 +
    34.6 +echo '[extensions]' >> $HGRC
    34.7 +echo 'hgext.mq =' >> $HGRC
    34.8 +
    34.9 +hg init a
   34.10 +cd a
   34.11 +hg qinit
   34.12 +echo 'int x;' > test.c
   34.13 +hg ci -Ama
   34.14 +
   34.15 +hg qnew first.patch
   34.16 +echo 'float c;' >> test.c
   34.17 +hg qrefresh
   34.18 +
   34.19 +hg qnew second.patch
   34.20 +echo 'double u;' > other.c
   34.21 +hg add other.c
   34.22 +hg qrefresh
   34.23 +
   34.24 +#$ name: output
   34.25 +
   34.26 +hg qapplied
   34.27 +hg log -r qbase:qtip
   34.28 +hg export second.patch
   34.29 +
   34.30 +#$ name:
   34.31 +exit 0
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/fr/examples/mq.qinit-help	Thu Feb 05 12:37:03 2009 +0100
    35.3 @@ -0,0 +1,7 @@
    35.4 +#!/bin/bash
    35.5 +
    35.6 +echo '[extensions]' >> $HGRC
    35.7 +echo 'hgext.mq =' >> $HGRC
    35.8 +
    35.9 +#$ name: help
   35.10 +hg help qinit
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/fr/examples/mq.tarball	Thu Feb 05 12:37:03 2009 +0100
    36.3 @@ -0,0 +1,51 @@
    36.4 +#!/bin/bash
    36.5 +
    36.6 +cp $EXAMPLE_DIR/data/netplug-*.tar.bz2 .
    36.7 +ln -s /bin/true download
    36.8 +export PATH=`pwd`:$PATH
    36.9 +
   36.10 +#$ name: download
   36.11 +
   36.12 +download netplug-1.2.5.tar.bz2
   36.13 +tar jxf netplug-1.2.5.tar.bz2
   36.14 +cd netplug-1.2.5
   36.15 +hg init
   36.16 +hg commit -q --addremove --message netplug-1.2.5
   36.17 +cd ..
   36.18 +hg clone netplug-1.2.5 netplug
   36.19 +
   36.20 +#$ name:
   36.21 +
   36.22 +cd netplug
   36.23 +echo '[extensions]' >> $HGRC
   36.24 +echo 'hgext.mq =' >> $HGRC
   36.25 +cd ..
   36.26 +
   36.27 +#$ name: qinit
   36.28 +
   36.29 +cd netplug
   36.30 +hg qinit
   36.31 +hg qnew -m 'fix build problem with gcc 4' build-fix.patch
   36.32 +perl -pi -e 's/int addr_len/socklen_t addr_len/' netlink.c
   36.33 +hg qrefresh
   36.34 +hg tip -p
   36.35 +
   36.36 +#$ name: newsource
   36.37 +
   36.38 +hg qpop -a
   36.39 +cd ..
   36.40 +download netplug-1.2.8.tar.bz2
   36.41 +hg clone netplug-1.2.5 netplug-1.2.8
   36.42 +cd netplug-1.2.8
   36.43 +hg locate -0 | xargs -0 rm
   36.44 +cd ..
   36.45 +tar jxf netplug-1.2.8.tar.bz2
   36.46 +cd netplug-1.2.8
   36.47 +hg commit --addremove --message netplug-1.2.8
   36.48 +
   36.49 +#$ name: repush
   36.50 +
   36.51 +cd ../netplug
   36.52 +hg pull ../netplug-1.2.8
   36.53 +hg qpush -a
   36.54 +
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/fr/examples/mq.tools	Thu Feb 05 12:37:03 2009 +0100
    37.3 @@ -0,0 +1,11 @@
    37.4 +#!/bin/bash
    37.5 +
    37.6 +cp $EXAMPLE_DIR/data/remove-redundant-null-checks.patch .
    37.7 +
    37.8 +#$ name: tools
    37.9 +diffstat -p1 remove-redundant-null-checks.patch
   37.10 +
   37.11 +filterdiff -i '*/video/*' remove-redundant-null-checks.patch
   37.12 +
   37.13 +#$ name: lsdiff
   37.14 +lsdiff -nvv remove-redundant-null-checks.patch
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/fr/examples/mq.tutorial	Thu Feb 05 12:37:03 2009 +0100
    38.3 @@ -0,0 +1,74 @@
    38.4 +#!/bin/bash
    38.5 +
    38.6 +echo '[extensions]' >> $HGRC
    38.7 +echo 'hgext.mq =' >> $HGRC
    38.8 +
    38.9 +#$ name: qinit
   38.10 +
   38.11 +hg init mq-sandbox
   38.12 +cd mq-sandbox
   38.13 +echo 'line 1' > file1
   38.14 +echo 'another line 1' > file2
   38.15 +hg add file1 file2
   38.16 +hg commit -m'first change'
   38.17 +
   38.18 +hg qinit
   38.19 +
   38.20 +#$ name: qnew
   38.21 +
   38.22 +hg tip
   38.23 +hg qnew first.patch
   38.24 +hg tip
   38.25 +ls .hg/patches
   38.26 +
   38.27 +#$ name: qrefresh
   38.28 +#$ ignore: \s+200[78]-.*
   38.29 +
   38.30 +echo 'line 2' >> file1
   38.31 +hg diff
   38.32 +hg qrefresh
   38.33 +hg diff
   38.34 +hg tip --style=compact --patch
   38.35 +
   38.36 +#$ name: qrefresh2
   38.37 +
   38.38 +echo 'line 3' >> file1
   38.39 +hg status
   38.40 +hg qrefresh
   38.41 +hg tip --style=compact --patch
   38.42 +
   38.43 +#$ name: qnew2
   38.44 +
   38.45 +hg qnew second.patch
   38.46 +hg log --style=compact --limit=2
   38.47 +echo 'line 4' >> file1
   38.48 +hg qrefresh
   38.49 +hg tip --style=compact --patch
   38.50 +hg annotate file1
   38.51 +
   38.52 +#$ name: qseries
   38.53 +
   38.54 +hg qseries
   38.55 +hg qapplied
   38.56 +
   38.57 +#$ name: qpop
   38.58 +
   38.59 +hg qapplied
   38.60 +hg qpop
   38.61 +hg qseries
   38.62 +hg qapplied
   38.63 +cat file1
   38.64 +
   38.65 +#$ name: qpush-a
   38.66 +
   38.67 +hg qpush -a
   38.68 +cat file1
   38.69 +
   38.70 +#$ name: add
   38.71 +
   38.72 +echo 'file 3, line 1' >> file3
   38.73 +hg qnew add-file3.patch
   38.74 +hg qnew -f add-file3.patch
   38.75 +
   38.76 +#$ name:
   38.77 +exit 0
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/fr/examples/rename.divergent	Thu Feb 05 12:37:03 2009 +0100
    39.3 @@ -0,0 +1,33 @@
    39.4 +#!/bin/bash
    39.5 +
    39.6 +hg init orig
    39.7 +cd orig
    39.8 +echo foo > foo
    39.9 +hg ci -A -m 'First commit'
   39.10 +cd ..
   39.11 +
   39.12 +#$ name: clone
   39.13 +
   39.14 +hg clone orig anne
   39.15 +hg clone orig bob
   39.16 +
   39.17 +#$ name: rename.anne
   39.18 +
   39.19 +cd anne
   39.20 +hg mv foo bar
   39.21 +hg ci -m 'Rename foo to bar'
   39.22 +
   39.23 +#$ name: rename.bob
   39.24 +
   39.25 +cd ../bob
   39.26 +hg mv foo quux
   39.27 +hg ci -m 'Rename foo to quux'
   39.28 +
   39.29 +#$ name: merge
   39.30 +# See http://www.selenic.com/mercurial/bts/issue455
   39.31 +
   39.32 +cd ../orig
   39.33 +hg pull -u ../anne
   39.34 +hg pull ../bob
   39.35 +hg merge
   39.36 +ls
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/fr/examples/rollback	Thu Feb 05 12:37:03 2009 +0100
    40.3 @@ -0,0 +1,37 @@
    40.4 +#!/bin/bash
    40.5 +
    40.6 +hg init a
    40.7 +cd a
    40.8 +echo a > a
    40.9 +hg ci -A -m 'First commit'
   40.10 +
   40.11 +echo a >> a
   40.12 +
   40.13 +#$ name: tip
   40.14 +
   40.15 +#$ name: commit
   40.16 +
   40.17 +hg status
   40.18 +echo b > b
   40.19 +hg commit -m 'Add file b'
   40.20 +
   40.21 +#$ name: status
   40.22 +
   40.23 +hg status
   40.24 +hg tip
   40.25 +
   40.26 +#$ name: rollback
   40.27 +
   40.28 +hg rollback
   40.29 +hg tip
   40.30 +hg status
   40.31 +
   40.32 +#$ name: add
   40.33 +
   40.34 +hg add b
   40.35 +hg commit -m 'Add file b, this time for real'
   40.36 +
   40.37 +#$ name: twice
   40.38 +
   40.39 +hg rollback
   40.40 +hg rollback
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/fr/examples/run-example	Thu Feb 05 12:37:03 2009 +0100
    41.3 @@ -0,0 +1,391 @@
    41.4 +#!/usr/bin/env python
    41.5 +#
    41.6 +# This program takes something that resembles a shell script and runs
    41.7 +# it, spitting input (commands from the script) and output into text
    41.8 +# files, for use in examples.
    41.9 +
   41.10 +import cStringIO
   41.11 +import errno
   41.12 +import getopt
   41.13 +import os
   41.14 +import pty
   41.15 +import re
   41.16 +import select
   41.17 +import shutil
   41.18 +import signal
   41.19 +import stat
   41.20 +import sys
   41.21 +import tempfile
   41.22 +import time
   41.23 +
   41.24 +tex_subs = {
   41.25 +    '\\': '\\textbackslash{}',
   41.26 +    '{': '\\{',
   41.27 +    '}': '\\}',
   41.28 +    }
   41.29 +
   41.30 +def gensubs(s):
   41.31 +    start = 0
   41.32 +    for i, c in enumerate(s):
   41.33 +        sub = tex_subs.get(c)
   41.34 +        if sub:
   41.35 +            yield s[start:i]
   41.36 +            start = i + 1
   41.37 +            yield sub
   41.38 +    yield s[start:]
   41.39 +
   41.40 +def tex_escape(s):
   41.41 +    return ''.join(gensubs(s))
   41.42 +        
   41.43 +def maybe_unlink(name):
   41.44 +    try:
   41.45 +        os.unlink(name)
   41.46 +        return True
   41.47 +    except OSError, err:
   41.48 +        if err.errno != errno.ENOENT:
   41.49 +            raise
   41.50 +    return False
   41.51 +
   41.52 +def find_path_to(program):
   41.53 +    for p in os.environ.get('PATH', os.defpath).split(os.pathsep):
   41.54 +        name = os.path.join(p, program)
   41.55 +        if os.access(name, os.X_OK):
   41.56 +            return p
   41.57 +    return None
   41.58 +        
   41.59 +class example:
   41.60 +    shell = '/usr/bin/env bash'
   41.61 +    ps1 = '__run_example_ps1__ '
   41.62 +    ps2 = '__run_example_ps2__ '
   41.63 +    pi_re = re.compile(r'#\$\s*(name|ignore):\s*(.*)$')
   41.64 +    
   41.65 +    timeout = 10
   41.66 +
   41.67 +    def __init__(self, name, verbose):
   41.68 +        self.name = name
   41.69 +        self.verbose = verbose
   41.70 +        self.poll = select.poll()
   41.71 +
   41.72 +    def parse(self):
   41.73 +        '''yield each hunk of input from the file.'''
   41.74 +        fp = open(self.name)
   41.75 +        cfp = cStringIO.StringIO()
   41.76 +        for line in fp:
   41.77 +            cfp.write(line)
   41.78 +            if not line.rstrip().endswith('\\'):
   41.79 +                yield cfp.getvalue()
   41.80 +                cfp.seek(0)
   41.81 +                cfp.truncate()
   41.82 +        
   41.83 +    def status(self, s):
   41.84 +        sys.stdout.write(s)
   41.85 +        if not s.endswith('\n'):
   41.86 +            sys.stdout.flush()
   41.87 +
   41.88 +    def send(self, s):
   41.89 +        if self.verbose:
   41.90 +            print >> sys.stderr, '>', self.debugrepr(s)
   41.91 +        while s:
   41.92 +            count = os.write(self.cfd, s)
   41.93 +            s = s[count:]
   41.94 +
   41.95 +    def debugrepr(self, s):
   41.96 +        rs = repr(s)
   41.97 +        limit = 60
   41.98 +        if len(rs) > limit:
   41.99 +            return ('%s%s ... [%d bytes]' % (rs[:limit], rs[0], len(s)))
  41.100 +        else:
  41.101 +            return rs
  41.102 +            
  41.103 +    timeout = 5
  41.104 +
  41.105 +    def read(self, hint):
  41.106 +        events = self.poll.poll(self.timeout * 1000)
  41.107 +        if not events:
  41.108 +            print >> sys.stderr, ('[%stimed out after %d seconds]' %
  41.109 +                                  (hint, self.timeout))
  41.110 +            os.kill(self.pid, signal.SIGHUP)
  41.111 +            return ''
  41.112 +        return os.read(self.cfd, 1024)
  41.113 +        
  41.114 +    def receive(self, hint):
  41.115 +        out = cStringIO.StringIO()
  41.116 +        while True:
  41.117 +            try:
  41.118 +                if self.verbose:
  41.119 +                    sys.stderr.write('< ')
  41.120 +                s = self.read(hint)
  41.121 +            except OSError, err:
  41.122 +                if err.errno == errno.EIO:
  41.123 +                    return '', ''
  41.124 +                raise
  41.125 +            if self.verbose:
  41.126 +                print >> sys.stderr, self.debugrepr(s)
  41.127 +            out.write(s)
  41.128 +            s = out.getvalue()
  41.129 +            if s.endswith(self.ps1):
  41.130 +                return self.ps1, s.replace('\r\n', '\n')[:-len(self.ps1)]
  41.131 +            if s.endswith(self.ps2):
  41.132 +                return self.ps2, s.replace('\r\n', '\n')[:-len(self.ps2)]
  41.133 +        
  41.134 +    def sendreceive(self, s, hint):
  41.135 +        self.send(s)
  41.136 +        ps, r = self.receive(hint)
  41.137 +        if r.startswith(s):
  41.138 +            r = r[len(s):]
  41.139 +        return ps, r
  41.140 +    
  41.141 +    def run(self):
  41.142 +        ofp = None
  41.143 +        basename = os.path.basename(self.name)
  41.144 +        self.status('running %s ' % basename)
  41.145 +        tmpdir = tempfile.mkdtemp(prefix=basename)
  41.146 +
  41.147 +        # remove the marker file that we tell make to use to see if
  41.148 +        # this run succeeded
  41.149 +        maybe_unlink(self.name + '.run')
  41.150 +
  41.151 +        rcfile = os.path.join(tmpdir, '.hgrc')
  41.152 +        rcfp = open(rcfile, 'w')
  41.153 +        print >> rcfp, '[ui]'
  41.154 +        print >> rcfp, "username = Bryan O'Sullivan <bos@serpentine.com>"
  41.155 +        
  41.156 +        rcfile = os.path.join(tmpdir, '.bashrc')
  41.157 +        rcfp = open(rcfile, 'w')
  41.158 +        print >> rcfp, 'PS1="%s"' % self.ps1
  41.159 +        print >> rcfp, 'PS2="%s"' % self.ps2
  41.160 +        print >> rcfp, 'unset HISTFILE'
  41.161 +        path = ['/usr/bin', '/bin']
  41.162 +        hg = find_path_to('hg')
  41.163 +        if hg and hg not in path:
  41.164 +            path.append(hg)
  41.165 +        def re_export(envar):
  41.166 +            v = os.getenv(envar)
  41.167 +            if v is not None:
  41.168 +                print >> rcfp, 'export ' + envar + '=' + v
  41.169 +        print >> rcfp, 'export PATH=' + ':'.join(path)
  41.170 +        re_export('PYTHONPATH')
  41.171 +        print >> rcfp, 'export EXAMPLE_DIR="%s"' % os.getcwd()
  41.172 +        print >> rcfp, 'export HGMERGE=merge'
  41.173 +        print >> rcfp, 'export LANG=C'
  41.174 +        print >> rcfp, 'export LC_ALL=C'
  41.175 +        print >> rcfp, 'export TZ=GMT'
  41.176 +        print >> rcfp, 'export HGRC="%s/.hgrc"' % tmpdir
  41.177 +        print >> rcfp, 'export HGRCPATH=$HGRC'
  41.178 +        print >> rcfp, 'cd %s' % tmpdir
  41.179 +        rcfp.close()
  41.180 +        sys.stdout.flush()
  41.181 +        sys.stderr.flush()
  41.182 +        self.pid, self.cfd = pty.fork()
  41.183 +        if self.pid == 0:
  41.184 +            cmdline = ['/usr/bin/env', '-i', 'bash', '--noediting',
  41.185 +                       '--noprofile', '--norc']
  41.186 +            try:
  41.187 +                os.execv(cmdline[0], cmdline)
  41.188 +            except OSError, err:
  41.189 +                print >> sys.stderr, '%s: %s' % (cmdline[0], err.strerror)
  41.190 +                sys.stderr.flush()
  41.191 +                os._exit(0)
  41.192 +        self.poll.register(self.cfd, select.POLLIN | select.POLLERR |
  41.193 +                           select.POLLHUP)
  41.194 +
  41.195 +        prompts = {
  41.196 +            '': '',
  41.197 +            self.ps1: '$',
  41.198 +            self.ps2: '>',
  41.199 +            }
  41.200 +
  41.201 +        ignore = [
  41.202 +            r'\d+:[0-9a-f]{12}', # changeset number:hash
  41.203 +            r'[0-9a-f]{40}', # long changeset hash
  41.204 +            r'[0-9a-f]{12}', # short changeset hash
  41.205 +            r'^(?:---|\+\+\+) .*', # diff header with dates
  41.206 +            r'^date:.*', # date
  41.207 +            #r'^diff -r.*', # "diff -r" is followed by hash
  41.208 +            r'^# Date \d+ \d+', # hg patch header
  41.209 +            ]
  41.210 +
  41.211 +        err = False
  41.212 +        read_hint = ''
  41.213 +
  41.214 +        try:
  41.215 +            try:
  41.216 +                # eat first prompt string from shell
  41.217 +                self.read(read_hint)
  41.218 +                # setup env and prompt
  41.219 +                ps, output = self.sendreceive('source %s\n' % rcfile,
  41.220 +                                              read_hint)
  41.221 +                for hunk in self.parse():
  41.222 +                    # is this line a processing instruction?
  41.223 +                    m = self.pi_re.match(hunk)
  41.224 +                    if m:
  41.225 +                        pi, rest = m.groups()
  41.226 +                        if pi == 'name':
  41.227 +                            self.status('.')
  41.228 +                            out = rest
  41.229 +                            if out in ('err', 'lxo', 'out', 'run', 'tmp'):
  41.230 +                                print >> sys.stderr, ('%s: illegal section '
  41.231 +                                                      'name %r' %
  41.232 +                                                      (self.name, out))
  41.233 +                                return 1
  41.234 +                            assert os.sep not in out
  41.235 +                            if ofp is not None:
  41.236 +                                ofp.close()
  41.237 +                                err |= self.rename_output(ofp_basename, ignore)
  41.238 +                            if out:
  41.239 +                                ofp_basename = '%s.%s' % (self.name, out)
  41.240 +                                read_hint = ofp_basename + ' '
  41.241 +                                ofp = open(ofp_basename + '.tmp', 'w')
  41.242 +                            else:
  41.243 +                                ofp = None
  41.244 +                        elif pi == 'ignore':
  41.245 +                            ignore.append(rest)
  41.246 +                    elif hunk.strip():
  41.247 +                        # it's something we should execute
  41.248 +                        newps, output = self.sendreceive(hunk, read_hint)
  41.249 +                        if not ofp:
  41.250 +                            continue
  41.251 +                        # first, print the command we ran
  41.252 +                        if not hunk.startswith('#'):
  41.253 +                            nl = hunk.endswith('\n')
  41.254 +                            hunk = ('%s \\textbf{%s}' %
  41.255 +                                    (prompts[ps],
  41.256 +                                     tex_escape(hunk.rstrip('\n'))))
  41.257 +                            if nl: hunk += '\n'
  41.258 +                        ofp.write(hunk)
  41.259 +                        # then its output
  41.260 +                        ofp.write(tex_escape(output))
  41.261 +                    ps = newps
  41.262 +                self.status('\n')
  41.263 +            except:
  41.264 +                print >> sys.stderr, '(killed)'
  41.265 +                os.kill(self.pid, signal.SIGKILL)
  41.266 +                pid, rc = os.wait()
  41.267 +                raise
  41.268 +            else:
  41.269 +                try:
  41.270 +                    ps, output = self.sendreceive('exit\n', read_hint)
  41.271 +                    if ofp is not None:
  41.272 +                        ofp.write(output)
  41.273 +                        ofp.close()
  41.274 +                        err |= self.rename_output(ofp_basename, ignore)
  41.275 +                    os.close(self.cfd)
  41.276 +                except IOError:
  41.277 +                    pass
  41.278 +                os.kill(self.pid, signal.SIGTERM)
  41.279 +                pid, rc = os.wait()
  41.280 +                err = err or rc
  41.281 +                if err:
  41.282 +                    if os.WIFEXITED(rc):
  41.283 +                        print >> sys.stderr, '(exit %s)' % os.WEXITSTATUS(rc)
  41.284 +                    elif os.WIFSIGNALED(rc):
  41.285 +                        print >> sys.stderr, '(signal %s)' % os.WTERMSIG(rc)
  41.286 +                else:
  41.287 +                    open(self.name + '.run', 'w')
  41.288 +                return err
  41.289 +        finally:
  41.290 +            shutil.rmtree(tmpdir)
  41.291 +
  41.292 +    def rename_output(self, base, ignore):
  41.293 +        mangle_re = re.compile('(?:' + '|'.join(ignore) + ')')
  41.294 +        def mangle(s):
  41.295 +            return mangle_re.sub('', s)
  41.296 +        def matchfp(fp1, fp2):
  41.297 +            while True:
  41.298 +                s1 = mangle(fp1.readline())
  41.299 +                s2 = mangle(fp2.readline())
  41.300 +                if cmp(s1, s2):
  41.301 +                    break
  41.302 +                if not s1:
  41.303 +                    return True
  41.304 +            return False
  41.305 +
  41.306 +        oldname = base + '.out'
  41.307 +        tmpname = base + '.tmp'
  41.308 +        errname = base + '.err'
  41.309 +        errfp = open(errname, 'w+')
  41.310 +        for line in open(tmpname):
  41.311 +            errfp.write(mangle_re.sub('', line))
  41.312 +        os.rename(tmpname, base + '.lxo')
  41.313 +        errfp.seek(0)
  41.314 +        try:
  41.315 +            oldfp = open(oldname)
  41.316 +        except IOError, err:
  41.317 +            if err.errno != errno.ENOENT:
  41.318 +                raise
  41.319 +            os.rename(errname, oldname)
  41.320 +            return False
  41.321 +        if matchfp(oldfp, errfp):
  41.322 +            os.unlink(errname)
  41.323 +            return False
  41.324 +        else:
  41.325 +            print >> sys.stderr, '\nOutput of %s has changed!' % base
  41.326 +            os.system('diff -u %s %s 1>&2' % (oldname, errname))
  41.327 +            return True
  41.328 +
  41.329 +def print_help(exit, msg=None):
  41.330 +    if msg:
  41.331 +        print >> sys.stderr, 'Error:', msg
  41.332 +    print >> sys.stderr, 'Usage: run-example [options] [test...]'
  41.333 +    print >> sys.stderr, 'Options:'
  41.334 +    print >> sys.stderr, '  -a --all       run all tests in this directory'
  41.335 +    print >> sys.stderr, '  -h --help      print this help message'
  41.336 +    print >> sys.stderr, '  -v --verbose   display extra debug output'
  41.337 +    sys.exit(exit)
  41.338 +
  41.339 +def main(path='.'):
  41.340 +    opts, args = getopt.getopt(sys.argv[1:], '?ahv',
  41.341 +                               ['all', 'help', 'verbose'])
  41.342 +    verbose = False
  41.343 +    run_all = False
  41.344 +    for o, a in opts:
  41.345 +        if o in ('-h', '-?', '--help'):
  41.346 +            print_help(0)
  41.347 +        if o in ('-a', '--all'):
  41.348 +            run_all = True
  41.349 +        if o in ('-v', '--verbose'):
  41.350 +            verbose = True
  41.351 +    errs = 0
  41.352 +    if args:
  41.353 +        for a in args:
  41.354 +            try:
  41.355 +                st = os.lstat(a)
  41.356 +            except OSError, err:
  41.357 +                print >> sys.stderr, '%s: %s' % (a, err.strerror)
  41.358 +                errs += 1
  41.359 +                continue
  41.360 +            if stat.S_ISREG(st.st_mode) and st.st_mode & 0111:
  41.361 +                if example(a, verbose).run():
  41.362 +                    errs += 1
  41.363 +            else:
  41.364 +                print >> sys.stderr, '%s: not a file, or not executable' % a
  41.365 +                errs += 1
  41.366 +    elif run_all:
  41.367 +        names = os.listdir(path)
  41.368 +        names.sort()
  41.369 +        for name in names:
  41.370 +            if name == 'run-example' or name.startswith('.'): continue
  41.371 +            if name.endswith('.out') or name.endswith('~'): continue
  41.372 +            if name.endswith('.run'): continue
  41.373 +            pathname = os.path.join(path, name)
  41.374 +            try:
  41.375 +                st = os.lstat(pathname)
  41.376 +            except OSError, err:
  41.377 +                # could be an output file that was removed while we ran
  41.378 +                if err.errno != errno.ENOENT:
  41.379 +                    raise
  41.380 +                continue
  41.381 +            if stat.S_ISREG(st.st_mode) and st.st_mode & 0111:
  41.382 +                if example(pathname, verbose).run():
  41.383 +                    errs += 1
  41.384 +        print >> open(os.path.join(path, '.run'), 'w'), time.asctime()
  41.385 +    else:
  41.386 +        print_help(1, msg='no test names given, and --all not provided')
  41.387 +    return errs
  41.388 +
  41.389 +if __name__ == '__main__':
  41.390 +    try:
  41.391 +        sys.exit(main())
  41.392 +    except KeyboardInterrupt:
  41.393 +        print >> sys.stderr, 'interrupted!'
  41.394 +        sys.exit(1)
    42.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    42.2 +++ b/fr/examples/svn-long.txt	Thu Feb 05 12:37:03 2009 +0100
    42.3 @@ -0,0 +1,11 @@
    42.4 +------------------------------------------------------------------------
    42.5 +r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
    42.6 +Changed paths:
    42.7 +   M /gen2/trunk/src/linux-kernel/infiniband/core/cma.c
    42.8 +
    42.9 +On reporting a route error, also include the status for the error,
   42.10 +rather than indicating a status of 0 when an error has occurred.
   42.11 +
   42.12 +Signed-off-by: Sean Hefty <sean.hefty@intel.com>
   42.13 +
   42.14 +------------------------------------------------------------------------
    43.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    43.2 +++ b/fr/examples/svn-short.txt	Thu Feb 05 12:37:03 2009 +0100
    43.3 @@ -0,0 +1,9 @@
    43.4 +------------------------------------------------------------------------
    43.5 +r9653 | sean.hefty | 2006-09-27 14:39:55 -0700 (Wed, 27 Sep 2006) | 5 lines
    43.6 +
    43.7 +On reporting a route error, also include the status for the error,
    43.8 +rather than indicating a status of 0 when an error has occurred.
    43.9 +
   43.10 +Signed-off-by: Sean Hefty <sean.hefty@intel.com>
   43.11 +
   43.12 +------------------------------------------------------------------------
    44.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    44.2 +++ b/fr/examples/svn.style	Thu Feb 05 12:37:03 2009 +0100
    44.3 @@ -0,0 +1,2 @@
    44.4 +header = '------------------------------------------------------------------------\n\n'
    44.5 +changeset = svn.template
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/fr/examples/svn.template	Thu Feb 05 12:37:03 2009 +0100
    45.3 @@ -0,0 +1,5 @@
    45.4 +r{rev} | {author|user} | {date|isodate} ({date|rfc822date})
    45.5 +
    45.6 +{desc|strip|fill76}
    45.7 +
    45.8 +------------------------------------------------------------------------
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/fr/examples/tag	Thu Feb 05 12:37:03 2009 +0100
    46.3 @@ -0,0 +1,44 @@
    46.4 +#!/bin/bash
    46.5 +
    46.6 +#$ name: init
    46.7 +
    46.8 +hg init mytag
    46.9 +cd mytag
   46.10 +
   46.11 +echo hello > myfile
   46.12 +hg commit -A -m 'Initial commit'
   46.13 +
   46.14 +#$ name: tag
   46.15 +
   46.16 +hg tag v1.0
   46.17 +
   46.18 +#$ name: tags
   46.19 +
   46.20 +hg tags
   46.21 +
   46.22 +#$ name: log
   46.23 +
   46.24 +hg log
   46.25 +
   46.26 +#$ name: log.v1.0
   46.27 +
   46.28 +echo goodbye > myfile2
   46.29 +hg commit -A -m 'Second commit'
   46.30 +hg log -r v1.0
   46.31 +
   46.32 +#$ name: remove
   46.33 +
   46.34 +hg tag --remove v1.0
   46.35 +hg tags
   46.36 +
   46.37 +#$ name: replace
   46.38 +
   46.39 +hg tag -r 1 v1.1
   46.40 +hg tags
   46.41 +hg tag -r 2 v1.1
   46.42 +hg tag -f -r 2 v1.1
   46.43 +hg tags
   46.44 +
   46.45 +#$ name: tip
   46.46 +
   46.47 +hg tip
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/fr/examples/template.simple	Thu Feb 05 12:37:03 2009 +0100
    47.3 @@ -0,0 +1,96 @@
    47.4 +#!/bin/bash
    47.5 +
    47.6 +# So many different bits of random output, it would be a nightmare to
    47.7 +# ignore each individually.
    47.8 +#$ ignore: .*
    47.9 +
   47.10 +hg init myrepo
   47.11 +cd myrepo
   47.12 +echo hello > hello
   47.13 +hg commit -Am'added hello'
   47.14 +
   47.15 +echo hello >> hello
   47.16 +echo goodbye > goodbye
   47.17 +echo '   added line to end of <<hello>> file.' > ../msg
   47.18 +echo '' >> ../msg
   47.19 +echo 'in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.' >> ../msg
   47.20 +
   47.21 +hg commit -Al../msg
   47.22 +
   47.23 +hg tag mytag
   47.24 +hg tag v0.1
   47.25 +
   47.26 +#$ name: normal
   47.27 +
   47.28 +hg log -r1
   47.29 +
   47.30 +#$ name: compact
   47.31 +
   47.32 +hg log --style compact
   47.33 +
   47.34 +#$ name: changelog
   47.35 +
   47.36 +hg log --style changelog
   47.37 +
   47.38 +#$ name: simplest
   47.39 +
   47.40 +hg log -r1 --template 'i saw a changeset\n'
   47.41 +
   47.42 +#$ name: simplesub
   47.43 +
   47.44 +hg log --template 'i saw a changeset: {desc}\n'
   47.45 +
   47.46 +#$ name: keywords
   47.47 +
   47.48 +hg log -r1 --template 'author: {author}\n'
   47.49 +hg log -r1 --template 'desc:\n{desc}\n'
   47.50 +hg log -r1 --template 'files: {files}\n'
   47.51 +hg log -r1 --template 'file_adds: {file_adds}\n'
   47.52 +hg log -r1 --template 'file_dels: {file_dels}\n'
   47.53 +hg log -r1 --template 'node: {node}\n'
   47.54 +hg log -r1 --template 'parents: {parents}\n'
   47.55 +hg log -r1 --template 'rev: {rev}\n'
   47.56 +hg log -r1 --template 'tags: {tags}\n'
   47.57 +
   47.58 +#$ name: datekeyword
   47.59 +
   47.60 +hg log -r1 --template 'date: {date}\n'
   47.61 +hg log -r1 --template 'date: {date|isodate}\n'
   47.62 +
   47.63 +#$ name: manyfilters
   47.64 +
   47.65 +hg log -r1 --template '{author}\n'
   47.66 +hg log -r1 --template '{author|domain}\n'
   47.67 +hg log -r1 --template '{author|email}\n'
   47.68 +hg log -r1 --template '{author|obfuscate}\n' | cut -c-76
   47.69 +hg log -r1 --template '{author|person}\n'
   47.70 +hg log -r1 --template '{author|user}\n'
   47.71 +
   47.72 +hg log -r1 --template 'looks almost right, but actually garbage: {date}\n'
   47.73 +hg log -r1 --template '{date|age}\n'
   47.74 +hg log -r1 --template '{date|date}\n'
   47.75 +hg log -r1 --template '{date|hgdate}\n'
   47.76 +hg log -r1 --template '{date|isodate}\n'
   47.77 +hg log -r1 --template '{date|rfc822date}\n'
   47.78 +hg log -r1 --template '{date|shortdate}\n'
   47.79 +
   47.80 +hg log -r1 --template '{desc}\n' | cut -c-76
   47.81 +hg log -r1 --template '{desc|addbreaks}\n' | cut -c-76
   47.82 +hg log -r1 --template '{desc|escape}\n' | cut -c-76
   47.83 +hg log -r1 --template '{desc|fill68}\n'
   47.84 +hg log -r1 --template '{desc|fill76}\n'
   47.85 +hg log -r1 --template '{desc|firstline}\n'
   47.86 +hg log -r1 --template '{desc|strip}\n' | cut -c-76
   47.87 +hg log -r1 --template '{desc|tabindent}\n' | expand | cut -c-76
   47.88 +
   47.89 +hg log -r1 --template '{node}\n'
   47.90 +hg log -r1 --template '{node|short}\n'
   47.91 +
   47.92 +#$ name: combine
   47.93 +
   47.94 +hg log -r1 --template 'description:\n\t{desc|strip|fill68|tabindent}\n'
   47.95 +
   47.96 +#$ name: rev
   47.97 +
   47.98 +echo 'changeset = "rev: {rev}\n"' > rev
   47.99 +hg log -l1 --style ./rev
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/fr/examples/template.svnstyle	Thu Feb 05 12:37:03 2009 +0100
    48.3 @@ -0,0 +1,70 @@
    48.4 +#!/bin/bash
    48.5 +
    48.6 +svn() {
    48.7 +  cat $EXAMPLE_DIR/svn-short.txt
    48.8 +}
    48.9 +
   48.10 +#$ name: short
   48.11 +
   48.12 +svn log -r9653
   48.13 +
   48.14 +#$ name:
   48.15 +
   48.16 +hg init myrepo
   48.17 +cd myrepo
   48.18 +
   48.19 +echo hello > hello
   48.20 +hg commit -Am'added hello'
   48.21 +
   48.22 +echo hello >> hello
   48.23 +echo goodbye > goodbye
   48.24 +echo '   added line to end of <<hello>> file.' > ../msg
   48.25 +echo '' >> ../msg
   48.26 +echo 'in addition, added a file with the helpful name (at least i hope that some might consider it so) of goodbye.' >> ../msg
   48.27 +
   48.28 +hg commit -Al../msg
   48.29 +
   48.30 +hg tag mytag
   48.31 +hg tag v0.1
   48.32 +
   48.33 +echo 'changeset = "{node|short}\n"' > svn.style
   48.34 +
   48.35 +#$ name: id
   48.36 +
   48.37 +hg log -r0 --template '{node}'
   48.38 +
   48.39 +#$ name: simplest
   48.40 +
   48.41 +cat svn.style
   48.42 +hg log -r1 --style svn.style
   48.43 +
   48.44 +#$ name:
   48.45 +
   48.46 +echo 'changeset =' > broken.style
   48.47 +
   48.48 +#$ name: syntax.input
   48.49 +
   48.50 +cat broken.style
   48.51 +
   48.52 +#$ name: syntax.error
   48.53 +
   48.54 +hg log -r1 --style broken.style
   48.55 +
   48.56 +#$ name:
   48.57 +
   48.58 +cp $EXAMPLE_DIR/svn.style .
   48.59 +cp $EXAMPLE_DIR/svn.template .
   48.60 +
   48.61 +#$ name: template
   48.62 +
   48.63 +cat svn.template
   48.64 +
   48.65 +#$ name: style
   48.66 +
   48.67 +cat svn.style
   48.68 +
   48.69 +#$ name: result
   48.70 +#$ ignore: \| 200[78].*
   48.71 +
   48.72 +hg log -r1 --style svn.style
   48.73 +
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/fr/examples/tour	Thu Feb 05 12:37:03 2009 +0100
    49.3 @@ -0,0 +1,194 @@
    49.4 +#!/bin/bash
    49.5 +
    49.6 +#$ name: version
    49.7 +
    49.8 +hg version
    49.9 +
   49.10 +#$ name: help
   49.11 +
   49.12 +hg help init
   49.13 +
   49.14 +#$ name: clone
   49.15 +
   49.16 +hg clone http://hg.serpentine.com/tutorial/hello
   49.17 +
   49.18 +#$ name: ls
   49.19 +#$ ignore: ^drwx.*
   49.20 +#$ ignore: ^total \d+
   49.21 +
   49.22 +ls -l
   49.23 +ls hello
   49.24 +
   49.25 +#$ name: ls-a
   49.26 +
   49.27 +cd hello
   49.28 +ls -a
   49.29 +
   49.30 +#$ name: log
   49.31 +
   49.32 +hg log
   49.33 +
   49.34 +#$ name: log-r
   49.35 +
   49.36 +hg log -r 3
   49.37 +hg log -r 0272e0d5a517
   49.38 +hg log -r 1 -r 4
   49.39 +
   49.40 +#$ name: log.range
   49.41 +
   49.42 +hg log -r 2:4
   49.43 +
   49.44 +#$ name: log-v
   49.45 +
   49.46 +hg log -v -r 3
   49.47 +
   49.48 +#$ name: log-vp
   49.49 +
   49.50 +hg log -v -p -r 2
   49.51 +
   49.52 +#$ name: reclone
   49.53 +
   49.54 +cd ..
   49.55 +hg clone hello my-hello
   49.56 +cd my-hello
   49.57 +
   49.58 +#$ name: sed
   49.59 +
   49.60 +sed -i '/printf/a\\tprintf("hello again!\\n");' hello.c
   49.61 +
   49.62 +#$ name: status
   49.63 +
   49.64 +ls
   49.65 +hg status
   49.66 +
   49.67 +#$ name: diff
   49.68 +
   49.69 +hg diff
   49.70 +
   49.71 +#$ name:
   49.72 +
   49.73 +export HGEDITOR='echo Added an extra line of output >'
   49.74 +
   49.75 +#$ name: commit
   49.76 +
   49.77 +hg commit
   49.78 +
   49.79 +#$ name: merge.dummy1
   49.80 +
   49.81 +hg log -r 5 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV5.my-hello
   49.82 +
   49.83 +#$ name: tip
   49.84 +
   49.85 +hg tip -vp
   49.86 +
   49.87 +#$ name: clone-pull
   49.88 +
   49.89 +cd ..
   49.90 +hg clone hello hello-pull
   49.91 +
   49.92 +#$ name: incoming
   49.93 +
   49.94 +cd hello-pull
   49.95 +hg incoming ../my-hello
   49.96 +
   49.97 +#$ name: pull
   49.98 +
   49.99 +hg tip
  49.100 +hg pull ../my-hello
  49.101 +hg tip
  49.102 +
  49.103 +#$ name: update
  49.104 +
  49.105 +grep printf hello.c
  49.106 +hg update tip
  49.107 +grep printf hello.c
  49.108 +
  49.109 +#$ name: parents
  49.110 +
  49.111 +hg parents
  49.112 +
  49.113 +#$ name: older
  49.114 +
  49.115 +hg update 2
  49.116 +hg parents
  49.117 +hg update
  49.118 +
  49.119 +#$ name: clone-push
  49.120 +
  49.121 +cd ..
  49.122 +hg clone hello hello-push
  49.123 +
  49.124 +#$ name: outgoing
  49.125 +
  49.126 +cd my-hello
  49.127 +hg outgoing ../hello-push
  49.128 +
  49.129 +#$ name: push
  49.130 +
  49.131 +hg push ../hello-push
  49.132 +
  49.133 +#$ name: push.nothing
  49.134 +
  49.135 +hg push ../hello-push
  49.136 +
  49.137 +#$ name: outgoing.net
  49.138 +
  49.139 +hg outgoing http://hg.serpentine.com/tutorial/hello
  49.140 +
  49.141 +#$ name: push.net
  49.142 +
  49.143 +hg push http://hg.serpentine.com/tutorial/hello
  49.144 +
  49.145 +#$ name: merge.clone
  49.146 +
  49.147 +cd ..
  49.148 +hg clone hello my-new-hello
  49.149 +cd my-new-hello
  49.150 +sed -i '/printf/i\\tprintf("once more, hello.\\n");' hello.c
  49.151 +hg commit -m 'A new hello for a new day.'
  49.152 +
  49.153 +#$ name: merge.dummy2
  49.154 +
  49.155 +hg log -r 5 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV5.my-new-hello
  49.156 +
  49.157 +#$ name: merge.cat
  49.158 +
  49.159 +cat hello.c
  49.160 +cat ../my-hello/hello.c
  49.161 +
  49.162 +#$ name: merge.pull
  49.163 +
  49.164 +hg pull ../my-hello
  49.165 +
  49.166 +#$ name: merge.dummy3
  49.167 +
  49.168 +hg log -r 6 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV6.my-new-hello
  49.169 +
  49.170 +#$ name: merge.heads
  49.171 +
  49.172 +hg heads
  49.173 +
  49.174 +#$ name: merge.update
  49.175 +
  49.176 +hg update
  49.177 +
  49.178 +#$ name: merge.merge
  49.179 +
  49.180 +hg merge
  49.181 +
  49.182 +#$ name: merge.parents
  49.183 +
  49.184 +hg parents
  49.185 +cat hello.c
  49.186 +
  49.187 +#$ name: merge.commit
  49.188 +
  49.189 +hg commit -m 'Merged changes'
  49.190 +
  49.191 +#$ name: merge.dummy4
  49.192 +
  49.193 +hg log -r 7 | grep changeset | cut -c 16-19 2>/dev/null > /tmp/REV7.my-new-hello
  49.194 +
  49.195 +#$ name: merge.tip
  49.196 +
  49.197 +hg tip
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/fr/examples/tour-merge-conflict	Thu Feb 05 12:37:03 2009 +0100
    50.3 @@ -0,0 +1,73 @@
    50.4 +#!/bin/bash
    50.5 +
    50.6 +hg init scam
    50.7 +cd scam
    50.8 +
    50.9 +#$ name: wife
   50.10 +
   50.11 +cat > letter.txt <<EOF
   50.12 +Greetings!
   50.13 +
   50.14 +I am Mariam Abacha, the wife of former
   50.15 +Nigerian dictator Sani Abacha.
   50.16 +EOF
   50.17 +
   50.18 +hg add letter.txt
   50.19 +hg commit -m '419 scam, first draft'
   50.20 +
   50.21 +#$ name: cousin
   50.22 +
   50.23 +cd ..
   50.24 +hg clone scam scam-cousin
   50.25 +cd scam-cousin
   50.26 +
   50.27 +cat > letter.txt <<EOF
   50.28 +Greetings!
   50.29 +
   50.30 +I am Shehu Musa Abacha, cousin to the former
   50.31 +Nigerian dictator Sani Abacha.
   50.32 +EOF
   50.33 +
   50.34 +hg commit -m '419 scam, with cousin'
   50.35 +
   50.36 +#$ name: son
   50.37 +
   50.38 +cd ..
   50.39 +hg clone scam scam-son
   50.40 +cd scam-son
   50.41 +
   50.42 +cat > letter.txt <<EOF
   50.43 +Greetings!
   50.44 +
   50.45 +I am Alhaji Abba Abacha, son of the former
   50.46 +Nigerian dictator Sani Abacha.
   50.47 +EOF
   50.48 +
   50.49 +hg commit -m '419 scam, with son'
   50.50 +
   50.51 +#$ name: pull
   50.52 +
   50.53 +cd ..
   50.54 +hg clone scam-cousin scam-merge
   50.55 +cd scam-merge
   50.56 +hg pull -u ../scam-son
   50.57 +
   50.58 +#$ name: merge
   50.59 +#$ ignore: [<>]{7} /tmp/.*
   50.60 +
   50.61 +export HGMERGE=merge
   50.62 +hg merge
   50.63 +cat letter.txt
   50.64 +
   50.65 +#$ name: commit
   50.66 +
   50.67 +cat > letter.txt <<EOF
   50.68 +Greetings!
   50.69 +
   50.70 +I am Bryan O'Sullivan, no relation of the former
   50.71 +Nigerian dictator Sani Abacha.
   50.72 +EOF
   50.73 +
   50.74 +hg resolve -m letter.txt
   50.75 +hg commit -m 'Send me your money'
   50.76 +hg tip
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/fr/fblinks	Thu Feb 05 12:37:03 2009 +0100
    51.3 @@ -0,0 +1,67 @@
    51.4 +#!/usr/bin/python
    51.5 +
    51.6 +import errno
    51.7 +import os
    51.8 +import re
    51.9 +import sys
   51.10 +
   51.11 +hg_id = sys.argv[1]
   51.12 +
   51.13 +dest_dir = sys.argv[2]
   51.14 +
   51.15 +empty_re = re.compile(r'^\s*$')
   51.16 +line_re = re.compile(r'^(\w+)(.*)')
   51.17 +
   51.18 +try:
   51.19 +    os.makedirs(dest_dir)
   51.20 +except OSError, err:
   51.21 +    if err.errno != errno.EEXIST:
   51.22 +        raise
   51.23 +
   51.24 +def feedback(name, text, ctx_id):
   51.25 +    return r'\marginpar{\scriptsize \href{http://demesne:8000/book/feedback/submit/%s/%s/%d/}{Feedback}}' % (hg_id, name, ctx_id)
   51.26 +
   51.27 +ctxs = {}
   51.28 +try:
   51.29 +    cfp = open(os.path.join(dest_dir, 'rev-' + hg_id + '.ctx'), 'r+')
   51.30 +    for line in cfp:
   51.31 +        f, l, c = line.split(':', 2)
   51.32 +        ctxs[(f, int(l))] = c.strip()
   51.33 +except IOError, err:
   51.34 +    if err.errno != errno.ENOENT: raise
   51.35 +    cfp = open(os.path.join(dest_dir, 'rev-' + hg_id + '.ctx'), 'w+')
   51.36 +
   51.37 +changes = 0
   51.38 +
   51.39 +for name in sys.argv[3:]:
   51.40 +    if not name.endswith('.tex'):
   51.41 +        continue
   51.42 +    dest_name = os.path.join(dest_dir, name)
   51.43 +    ifp = open(name)
   51.44 +    ofp = open(dest_name, 'w')
   51.45 +    new_par = True
   51.46 +    line_num = 0
   51.47 +    par_num = 0
   51.48 +    for line in ifp:
   51.49 +        line_num += 1
   51.50 +        if new_par:
   51.51 +            m = line_re.match(line)
   51.52 +            if m:
   51.53 +                par_num += 1
   51.54 +                ls = line.strip()
   51.55 +                if ctxs.get((name, par_num)) != ls:
   51.56 +                    ctxs[(name, par_num)] = ls
   51.57 +                    changes += 1
   51.58 +                line = m.group(1) + feedback(name, line, par_num) + m.group(2)
   51.59 +                new_par = False
   51.60 +        elif not line.strip():
   51.61 +            new_par = True
   51.62 +        ofp.write(line)
   51.63 +
   51.64 +if changes:
   51.65 +    cfp.seek(0)
   51.66 +    print '%s: %d changes' % (cfp.name, changes)
   51.67 +    ctxs = ctxs.items()
   51.68 +    ctxs.sort()
   51.69 +    for ((file, line), content) in ctxs:
   51.70 +        cfp.write('%s:%d: %s\n' % (file, line, content))
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/fr/feature-branches.dot	Thu Feb 05 12:37:03 2009 +0100
    52.3 @@ -0,0 +1,8 @@
    52.4 +digraph feature_branches {
    52.5 +	master -> crypto;
    52.6 +	master -> filesystems;
    52.7 +	master -> ipc;
    52.8 +	master -> memory;
    52.9 +	master -> network;
   52.10 +	master -> security;
   52.11 +}
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/fr/filelog.svg	Thu Feb 05 12:37:03 2009 +0100
    53.3 @@ -0,0 +1,373 @@
    53.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    53.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    53.6 +<svg
    53.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    53.8 +   xmlns:cc="http://web.resource.org/cc/"
    53.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   53.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   53.11 +   xmlns="http://www.w3.org/2000/svg"
   53.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
   53.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   53.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   53.15 +   width="744.09448819"
   53.16 +   height="1052.3622047"
   53.17 +   id="svg2"
   53.18 +   sodipodi:version="0.32"
   53.19 +   inkscape:version="0.45.1"
   53.20 +   sodipodi:docname="filelog.svg"
   53.21 +   sodipodi:docbase="/home/arun/hgbook/en"
   53.22 +   inkscape:output_extension="org.inkscape.output.svg.inkscape">
   53.23 +  <defs
   53.24 +     id="defs4">
   53.25 +    <marker
   53.26 +       inkscape:stockid="Arrow1Mend"
   53.27 +       orient="auto"
   53.28 +       refY="0.0"
   53.29 +       refX="0.0"
   53.30 +       id="Arrow1Mend"
   53.31 +       style="overflow:visible;">
   53.32 +      <path
   53.33 +         id="path3128"
   53.34 +         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 "
   53.35 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   53.36 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   53.37 +    </marker>
   53.38 +    <linearGradient
   53.39 +       id="linearGradient2887">
   53.40 +      <stop
   53.41 +         style="stop-color:#91cfcf;stop-opacity:1;"
   53.42 +         offset="0"
   53.43 +         id="stop2889" />
   53.44 +      <stop
   53.45 +         style="stop-color:aqua;stop-opacity:0;"
   53.46 +         offset="1"
   53.47 +         id="stop2891" />
   53.48 +    </linearGradient>
   53.49 +    <linearGradient
   53.50 +       id="linearGradient2795">
   53.51 +      <stop
   53.52 +         style="stop-color:#ccc;stop-opacity:1;"
   53.53 +         offset="0"
   53.54 +         id="stop2797" />
   53.55 +      <stop
   53.56 +         style="stop-color:#ccc;stop-opacity:0;"
   53.57 +         offset="1"
   53.58 +         id="stop2799" />
   53.59 +    </linearGradient>
   53.60 +    <linearGradient
   53.61 +       inkscape:collect="always"
   53.62 +       xlink:href="#linearGradient2795"
   53.63 +       id="linearGradient3170"
   53.64 +       gradientUnits="userSpaceOnUse"
   53.65 +       gradientTransform="translate(121.2183,94.95434)"
   53.66 +       x1="81.322357"
   53.67 +       y1="404.34424"
   53.68 +       x2="201.52036"
   53.69 +       y2="373.03967" />
   53.70 +    <linearGradient
   53.71 +       inkscape:collect="always"
   53.72 +       xlink:href="#linearGradient2887"
   53.73 +       id="linearGradient3172"
   53.74 +       gradientUnits="userSpaceOnUse"
   53.75 +       gradientTransform="translate(0,12)"
   53.76 +       x1="62.634491"
   53.77 +       y1="503.3392"
   53.78 +       x2="248.49242"
   53.79 +       y2="462.94327" />
   53.80 +    <linearGradient
   53.81 +       inkscape:collect="always"
   53.82 +       xlink:href="#linearGradient2795"
   53.83 +       id="linearGradient3174"
   53.84 +       gradientUnits="userSpaceOnUse"
   53.85 +       gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)"
   53.86 +       x1="81.322357"
   53.87 +       y1="404.34424"
   53.88 +       x2="201.52036"
   53.89 +       y2="373.03967" />
   53.90 +    <linearGradient
   53.91 +       inkscape:collect="always"
   53.92 +       xlink:href="#linearGradient2887"
   53.93 +       id="linearGradient3176"
   53.94 +       gradientUnits="userSpaceOnUse"
   53.95 +       gradientTransform="translate(0,12)"
   53.96 +       x1="62.634491"
   53.97 +       y1="503.3392"
   53.98 +       x2="248.49242"
   53.99 +       y2="462.94327" />
  53.100 +    <linearGradient
  53.101 +       inkscape:collect="always"
  53.102 +       xlink:href="#linearGradient2795"
  53.103 +       id="linearGradient3208"
  53.104 +       gradientUnits="userSpaceOnUse"
  53.105 +       gradientTransform="matrix(1.001035,0,0,0.653159,236.7075,153.0415)"
  53.106 +       x1="81.322357"
  53.107 +       y1="404.34424"
  53.108 +       x2="201.52036"
  53.109 +       y2="373.03967" />
  53.110 +    <linearGradient
  53.111 +       inkscape:collect="always"
  53.112 +       xlink:href="#linearGradient2887"
  53.113 +       id="linearGradient3210"
  53.114 +       gradientUnits="userSpaceOnUse"
  53.115 +       gradientTransform="translate(0,12)"
  53.116 +       x1="62.634491"
  53.117 +       y1="503.3392"
  53.118 +       x2="248.49242"
  53.119 +       y2="462.94327" />
  53.120 +    <linearGradient
  53.121 +       inkscape:collect="always"
  53.122 +       xlink:href="#linearGradient2795"
  53.123 +       id="linearGradient3212"
  53.124 +       gradientUnits="userSpaceOnUse"
  53.125 +       gradientTransform="translate(121.2183,94.95434)"
  53.126 +       x1="81.322357"
  53.127 +       y1="404.34424"
  53.128 +       x2="201.52036"
  53.129 +       y2="373.03967" />
  53.130 +    <linearGradient
  53.131 +       inkscape:collect="always"
  53.132 +       xlink:href="#linearGradient2887"
  53.133 +       id="linearGradient3214"
  53.134 +       gradientUnits="userSpaceOnUse"
  53.135 +       gradientTransform="translate(0,12)"
  53.136 +       x1="62.634491"
  53.137 +       y1="503.3392"
  53.138 +       x2="248.49242"
  53.139 +       y2="462.94327" />
  53.140 +    <linearGradient
  53.141 +       inkscape:collect="always"
  53.142 +       xlink:href="#linearGradient2795"
  53.143 +       id="linearGradient3256"
  53.144 +       gradientUnits="userSpaceOnUse"
  53.145 +       gradientTransform="matrix(1.2343775,0,0,0.9981848,103.25588,95.681888)"
  53.146 +       x1="74.301666"
  53.147 +       y1="431.67441"
  53.148 +       x2="260.05884"
  53.149 +       y2="369.95322" />
  53.150 +    <linearGradient
  53.151 +       inkscape:collect="always"
  53.152 +       xlink:href="#linearGradient2887"
  53.153 +       id="linearGradient3258"
  53.154 +       gradientUnits="userSpaceOnUse"
  53.155 +       gradientTransform="matrix(1.228929,0,0,0.9972824,-62.037003,13.312997)"
  53.156 +       x1="62.634491"
  53.157 +       y1="503.3392"
  53.158 +       x2="248.49242"
  53.159 +       y2="462.94327" />
  53.160 +    <linearGradient
  53.161 +       inkscape:collect="always"
  53.162 +       xlink:href="#linearGradient2795"
  53.163 +       id="linearGradient3260"
  53.164 +       gradientUnits="userSpaceOnUse"
  53.165 +       gradientTransform="matrix(1.2300738,0,0,0.6517275,219.97511,153.61527)"
  53.166 +       x1="74.387527"
  53.167 +       y1="431.80576"
  53.168 +       x2="259.97339"
  53.169 +       y2="369.82224" />
  53.170 +    <linearGradient
  53.171 +       inkscape:collect="always"
  53.172 +       xlink:href="#linearGradient2887"
  53.173 +       id="linearGradient3262"
  53.174 +       gradientUnits="userSpaceOnUse"
  53.175 +       gradientTransform="matrix(1.2289272,0,0,0.9972824,-62.036756,13.312985)"
  53.176 +       x1="62.634491"
  53.177 +       y1="503.3392"
  53.178 +       x2="248.49242"
  53.179 +       y2="462.94327" />
  53.180 +  </defs>
  53.181 +  <sodipodi:namedview
  53.182 +     id="base"
  53.183 +     pagecolor="#ffffff"
  53.184 +     bordercolor="#666666"
  53.185 +     borderopacity="1.0"
  53.186 +     gridtolerance="10000"
  53.187 +     guidetolerance="10"
  53.188 +     objecttolerance="10"
  53.189 +     inkscape:pageopacity="0.0"
  53.190 +     inkscape:pageshadow="2"
  53.191 +     inkscape:zoom="1.4"
  53.192 +     inkscape:cx="455.8122"
  53.193 +     inkscape:cy="520"
  53.194 +     inkscape:document-units="px"
  53.195 +     inkscape:current-layer="layer1"
  53.196 +     inkscape:window-width="1680"
  53.197 +     inkscape:window-height="970"
  53.198 +     inkscape:window-x="0"
  53.199 +     inkscape:window-y="54" />
  53.200 +  <metadata
  53.201 +     id="metadata7">
  53.202 +    <rdf:RDF>
  53.203 +      <cc:Work
  53.204 +         rdf:about="">
  53.205 +        <dc:format>image/svg+xml</dc:format>
  53.206 +        <dc:type
  53.207 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  53.208 +      </cc:Work>
  53.209 +    </rdf:RDF>
  53.210 +  </metadata>
  53.211 +  <g
  53.212 +     inkscape:label="Layer 1"
  53.213 +     inkscape:groupmode="layer"
  53.214 +     id="layer1">
  53.215 +    <rect
  53.216 +       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"
  53.217 +       id="rect3180"
  53.218 +       width="273.81375"
  53.219 +       height="199.06245"
  53.220 +       x="369.1796"
  53.221 +       y="351.79019" />
  53.222 +    <rect
  53.223 +       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"
  53.224 +       id="rect3178"
  53.225 +       width="273.81339"
  53.226 +       height="199.06233"
  53.227 +       x="72.699799"
  53.228 +       y="351.78983" />
  53.229 +    <g
  53.230 +       id="g3144"
  53.231 +       transform="translate(80.467048,0.71578)">
  53.232 +      <g
  53.233 +         id="g2940">
  53.234 +        <rect
  53.235 +           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"
  53.236 +           id="rect2914"
  53.237 +           width="227.38896"
  53.238 +           height="39.500999"
  53.239 +           x="311.92496"
  53.240 +           y="395.08627" />
  53.241 +        <text
  53.242 +           xml:space="preserve"
  53.243 +           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"
  53.244 +           x="323.72824"
  53.245 +           y="416.7626"
  53.246 +           id="text2918"><tspan
  53.247 +             sodipodi:role="line"
  53.248 +             id="tspan2920"
  53.249 +             x="323.72824"
  53.250 +             y="416.7626"
  53.251 +             style="font-family:Courier">.hg/store/data/README.i</tspan></text>
  53.252 +      </g>
  53.253 +      <g
  53.254 +         transform="translate(3.79093e-5,-80.1853)"
  53.255 +         id="g2945">
  53.256 +        <g
  53.257 +           id="g2955">
  53.258 +          <rect
  53.259 +             y="475.4968"
  53.260 +             x="15.550935"
  53.261 +             height="39.500999"
  53.262 +             width="227.17694"
  53.263 +             id="rect2947"
  53.264 +             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" />
  53.265 +          <text
  53.266 +             id="text2949"
  53.267 +             y="498.35123"
  53.268 +             x="31.230644"
  53.269 +             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"
  53.270 +             xml:space="preserve"><tspan
  53.271 +               style="font-family:Courier"
  53.272 +               y="498.35123"
  53.273 +               x="31.230644"
  53.274 +               id="tspan2951"
  53.275 +               sodipodi:role="line">README</tspan></text>
  53.276 +        </g>
  53.277 +      </g>
  53.278 +      <path
  53.279 +         inkscape:connector-type="polyline"
  53.280 +         id="path2960"
  53.281 +         d="M 242.94685,414.91115 C 242.94685,414.91115 293.61127,415.26754 310.16269,415.38633"
  53.282 +         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"
  53.283 +         sodipodi:nodetypes="cz" />
  53.284 +    </g>
  53.285 +    <g
  53.286 +       id="g3156"
  53.287 +       transform="translate(80.467048,0.71578)">
  53.288 +      <g
  53.289 +         transform="translate(116,0)"
  53.290 +         id="g2831">
  53.291 +        <rect
  53.292 +           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"
  53.293 +           id="rect1906"
  53.294 +           width="228.18446"
  53.295 +           height="60.499123"
  53.296 +           x="195.52719"
  53.297 +           y="465.51859" />
  53.298 +        <g
  53.299 +           id="g2803"
  53.300 +           transform="translate(-0.893671,1.833581)">
  53.301 +          <text
  53.302 +             id="text1884"
  53.303 +             y="483.92801"
  53.304 +             x="208.95944"
  53.305 +             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"
  53.306 +             xml:space="preserve"><tspan
  53.307 +               style="font-family:Courier"
  53.308 +               y="483.92801"
  53.309 +               x="208.95944"
  53.310 +               id="tspan1886"
  53.311 +               sodipodi:role="line">.hg/store/data/src/hello.c.d</tspan></text>
  53.312 +          <text
  53.313 +             id="text1888"
  53.314 +             y="507.79309"
  53.315 +             x="208.95944"
  53.316 +             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"
  53.317 +             xml:space="preserve"><tspan
  53.318 +               style="font-family:Courier"
  53.319 +               y="507.79309"
  53.320 +               x="208.95944"
  53.321 +               id="tspan1890"
  53.322 +               sodipodi:role="line">.hg/store/data/src/hello.c.i</tspan></text>
  53.323 +        </g>
  53.324 +      </g>
  53.325 +      <g
  53.326 +         id="g2907">
  53.327 +        <rect
  53.328 +           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"
  53.329 +           id="rect2843"
  53.330 +           width="227.17728"
  53.331 +           height="39.500999"
  53.332 +           x="15.550805"
  53.333 +           y="475.4968" />
  53.334 +        <text
  53.335 +           xml:space="preserve"
  53.336 +           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"
  53.337 +           x="31.230644"
  53.338 +           y="498.35123"
  53.339 +           id="text2847"><tspan
  53.340 +             sodipodi:role="line"
  53.341 +             id="tspan2849"
  53.342 +             x="31.230644"
  53.343 +             y="498.35123"
  53.344 +             style="font-family:Courier">src/hello.c</tspan></text>
  53.345 +      </g>
  53.346 +      <path
  53.347 +         inkscape:connection-end="#g2831"
  53.348 +         inkscape:connection-start="#g2907"
  53.349 +         inkscape:connector-type="polyline"
  53.350 +         id="path2962"
  53.351 +         d="M 242.4315,495.88043 C 242.4315,495.88043 292.8861,495.99942 310.04102,496.03909"
  53.352 +         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"
  53.353 +         sodipodi:nodetypes="cs" />
  53.354 +    </g>
  53.355 +    <text
  53.356 +       xml:space="preserve"
  53.357 +       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"
  53.358 +       x="98.496666"
  53.359 +       y="373.96353"
  53.360 +       id="text3216"><tspan
  53.361 +         sodipodi:role="line"
  53.362 +         id="tspan3218"
  53.363 +         x="98.496666"
  53.364 +         y="373.96353">Working directory</tspan></text>
  53.365 +    <text
  53.366 +       xml:space="preserve"
  53.367 +       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"
  53.368 +       x="391.39197"
  53.369 +       y="373.96353"
  53.370 +       id="text3228"><tspan
  53.371 +         sodipodi:role="line"
  53.372 +         id="tspan3230"
  53.373 +         x="391.39197"
  53.374 +         y="373.96353">Repository</tspan></text>
  53.375 +  </g>
  53.376 +</svg>
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/fr/filenames.tex	Thu Feb 05 12:37:03 2009 +0100
    54.3 @@ -0,0 +1,306 @@
    54.4 +\chapter{File names and pattern matching}
    54.5 +\label{chap:names}
    54.6 +
    54.7 +Mercurial provides mechanisms that let you work with file names in a
    54.8 +consistent and expressive way.
    54.9 +
   54.10 +\section{Simple file naming}
   54.11 +
   54.12 +Mercurial uses a unified piece of machinery ``under the hood'' to
   54.13 +handle file names.  Every command behaves uniformly with respect to
   54.14 +file names.  The way in which commands work with file names is as
   54.15 +follows.
   54.16 +
   54.17 +If you explicitly name real files on the command line, Mercurial works
   54.18 +with exactly those files, as you would expect.
   54.19 +\interaction{filenames.files}
   54.20 +
   54.21 +When you provide a directory name, Mercurial will interpret this as
   54.22 +``operate on every file in this directory and its subdirectories''.
   54.23 +Mercurial traverses the files and subdirectories in a directory in
   54.24 +alphabetical order.  When it encounters a subdirectory, it will
   54.25 +traverse that subdirectory before continuing with the current
   54.26 +directory.
   54.27 +\interaction{filenames.dirs}
   54.28 +
   54.29 +\section{Running commands without any file names}
   54.30 +
   54.31 +Mercurial's commands that work with file names have useful default
   54.32 +behaviours when you invoke them without providing any file names or
   54.33 +patterns.  What kind of behaviour you should expect depends on what
   54.34 +the command does.  Here are a few rules of thumb you can use to
   54.35 +predict what a command is likely to do if you don't give it any names
   54.36 +to work with.
   54.37 +\begin{itemize}
   54.38 +\item Most commands will operate on the entire working directory.
   54.39 +  This is what the \hgcmd{add} command does, for example.
   54.40 +\item If the command has effects that are difficult or impossible to
   54.41 +  reverse, it will force you to explicitly provide at least one name
   54.42 +  or pattern (see below).  This protects you from accidentally
   54.43 +  deleting files by running \hgcmd{remove} with no arguments, for
   54.44 +  example.
   54.45 +\end{itemize}
   54.46 +
   54.47 +It's easy to work around these default behaviours if they don't suit
   54.48 +you.  If a command normally operates on the whole working directory,
   54.49 +you can invoke it on just the current directory and its subdirectories
   54.50 +by giving it the name ``\dirname{.}''.
   54.51 +\interaction{filenames.wdir-subdir}
   54.52 +
   54.53 +Along the same lines, some commands normally print file names relative
   54.54 +to the root of the repository, even if you're invoking them from a
   54.55 +subdirectory.  Such a command will print file names relative to your
   54.56 +subdirectory if you give it explicit names.  Here, we're going to run
   54.57 +\hgcmd{status} from a subdirectory, and get it to operate on the
   54.58 +entire working directory while printing file names relative to our
   54.59 +subdirectory, by passing it the output of the \hgcmd{root} command.
   54.60 +\interaction{filenames.wdir-relname}
   54.61 +
   54.62 +\section{Telling you what's going on}
   54.63 +
   54.64 +The \hgcmd{add} example in the preceding section illustrates something
   54.65 +else that's helpful about Mercurial commands.  If a command operates
   54.66 +on a file that you didn't name explicitly on the command line, it will
   54.67 +usually print the name of the file, so that you will not be surprised
   54.68 +what's going on.
   54.69 +
   54.70 +The principle here is of \emph{least surprise}.  If you've exactly
   54.71 +named a file on the command line, there's no point in repeating it
   54.72 +back at you.  If Mercurial is acting on a file \emph{implicitly},
   54.73 +because you provided no names, or a directory, or a pattern (see
   54.74 +below), it's safest to tell you what it's doing.
   54.75 +
   54.76 +For commands that behave this way, you can silence them using the
   54.77 +\hggopt{-q} option.  You can also get them to print the name of every
   54.78 +file, even those you've named explicitly, using the \hggopt{-v}
   54.79 +option.
   54.80 +
   54.81 +\section{Using patterns to identify files}
   54.82 +
   54.83 +In addition to working with file and directory names, Mercurial lets
   54.84 +you use \emph{patterns} to identify files.  Mercurial's pattern
   54.85 +handling is expressive.
   54.86 +
   54.87 +On Unix-like systems (Linux, MacOS, etc.), the job of matching file
   54.88 +names to patterns normally falls to the shell.  On these systems, you
   54.89 +must explicitly tell Mercurial that a name is a pattern.  On Windows,
   54.90 +the shell does not expand patterns, so Mercurial will automatically
   54.91 +identify names that are patterns, and expand them for you.
   54.92 +
   54.93 +To provide a pattern in place of a regular name on the command line,
   54.94 +the mechanism is simple:
   54.95 +\begin{codesample2}
   54.96 +  syntax:patternbody
   54.97 +\end{codesample2}
   54.98 +That is, a pattern is identified by a short text string that says what
   54.99 +kind of pattern this is, followed by a colon, followed by the actual
  54.100 +pattern.
  54.101 +
  54.102 +Mercurial supports two kinds of pattern syntax.  The most frequently
  54.103 +used is called \texttt{glob}; this is the same kind of pattern
  54.104 +matching used by the Unix shell, and should be familiar to Windows
  54.105 +command prompt users, too.  
  54.106 +
  54.107 +When Mercurial does automatic pattern matching on Windows, it uses
  54.108 +\texttt{glob} syntax.  You can thus omit the ``\texttt{glob:}'' prefix
  54.109 +on Windows, but it's safe to use it, too.
  54.110 +
  54.111 +The \texttt{re} syntax is more powerful; it lets you specify patterns
  54.112 +using regular expressions, also known as regexps.
  54.113 +
  54.114 +By the way, in the examples that follow, notice that I'm careful to
  54.115 +wrap all of my patterns in quote characters, so that they won't get
  54.116 +expanded by the shell before Mercurial sees them.
  54.117 +
  54.118 +\subsection{Shell-style \texttt{glob} patterns}
  54.119 +
  54.120 +This is an overview of the kinds of patterns you can use when you're
  54.121 +matching on glob patterns.
  54.122 +
  54.123 +The ``\texttt{*}'' character matches any string, within a single
  54.124 +directory.
  54.125 +\interaction{filenames.glob.star}
  54.126 +
  54.127 +The ``\texttt{**}'' pattern matches any string, and crosses directory
  54.128 +boundaries.  It's not a standard Unix glob token, but it's accepted by
  54.129 +several popular Unix shells, and is very useful.
  54.130 +\interaction{filenames.glob.starstar}
  54.131 +
  54.132 +The ``\texttt{?}'' pattern matches any single character.
  54.133 +\interaction{filenames.glob.question}
  54.134 +
  54.135 +The ``\texttt{[}'' character begins a \emph{character class}.  This
  54.136 +matches any single character within the class.  The class ends with a
  54.137 +``\texttt{]}'' character.  A class may contain multiple \emph{range}s
  54.138 +of the form ``\texttt{a-f}'', which is shorthand for
  54.139 +``\texttt{abcdef}''.
  54.140 +\interaction{filenames.glob.range}
  54.141 +If the first character after the ``\texttt{[}'' in a character class
  54.142 +is a ``\texttt{!}'', it \emph{negates} the class, making it match any
  54.143 +single character not in the class.
  54.144 +
  54.145 +A ``\texttt{\{}'' begins a group of subpatterns, where the whole group
  54.146 +matches if any subpattern in the group matches.  The ``\texttt{,}''
  54.147 +character separates subpatterns, and ``\texttt{\}}'' ends the group.
  54.148 +\interaction{filenames.glob.group}
  54.149 +
  54.150 +\subsubsection{Watch out!}
  54.151 +
  54.152 +Don't forget that if you want to match a pattern in any directory, you
  54.153 +should not be using the ``\texttt{*}'' match-any token, as this will
  54.154 +only match within one directory.  Instead, use the ``\texttt{**}''
  54.155 +token.  This small example illustrates the difference between the two.
  54.156 +\interaction{filenames.glob.star-starstar}
  54.157 +
  54.158 +\subsection{Regular expression matching with \texttt{re} patterns}
  54.159 +
  54.160 +Mercurial accepts the same regular expression syntax as the Python
  54.161 +programming language (it uses Python's regexp engine internally).
  54.162 +This is based on the Perl language's regexp syntax, which is the most
  54.163 +popular dialect in use (it's also used in Java, for example).
  54.164 +
  54.165 +I won't discuss Mercurial's regexp dialect in any detail here, as
  54.166 +regexps are not often used.  Perl-style regexps are in any case
  54.167 +already exhaustively documented on a multitude of web sites, and in
  54.168 +many books.  Instead, I will focus here on a few things you should
  54.169 +know if you find yourself needing to use regexps with Mercurial.
  54.170 +
  54.171 +A regexp is matched against an entire file name, relative to the root
  54.172 +of the repository.  In other words, even if you're already in
  54.173 +subbdirectory \dirname{foo}, if you want to match files under this
  54.174 +directory, your pattern must start with ``\texttt{foo/}''.
  54.175 +
  54.176 +One thing to note, if you're familiar with Perl-style regexps, is that
  54.177 +Mercurial's are \emph{rooted}.  That is, a regexp starts matching
  54.178 +against the beginning of a string; it doesn't look for a match
  54.179 +anywhere within the string.  To match anywhere in a string, start
  54.180 +your pattern with ``\texttt{.*}''.
  54.181 +
  54.182 +\section{Filtering files}
  54.183 +
  54.184 +Not only does Mercurial give you a variety of ways to specify files;
  54.185 +it lets you further winnow those files using \emph{filters}.  Commands
  54.186 +that work with file names accept two filtering options.
  54.187 +\begin{itemize}
  54.188 +\item \hggopt{-I}, or \hggopt{--include}, lets you specify a pattern
  54.189 +  that file names must match in order to be processed.
  54.190 +\item \hggopt{-X}, or \hggopt{--exclude}, gives you a way to
  54.191 +  \emph{avoid} processing files, if they match this pattern.
  54.192 +\end{itemize}
  54.193 +You can provide multiple \hggopt{-I} and \hggopt{-X} options on the
  54.194 +command line, and intermix them as you please.  Mercurial interprets
  54.195 +the patterns you provide using glob syntax by default (but you can use
  54.196 +regexps if you need to).
  54.197 +
  54.198 +You can read a \hggopt{-I} filter as ``process only the files that
  54.199 +match this filter''.
  54.200 +\interaction{filenames.filter.include}
  54.201 +The \hggopt{-X} filter is best read as ``process only the files that
  54.202 +don't match this pattern''.
  54.203 +\interaction{filenames.filter.exclude}
  54.204 +
  54.205 +\section{Ignoring unwanted files and directories}
  54.206 +
  54.207 +XXX.
  54.208 +
  54.209 +\section{Case sensitivity}
  54.210 +\label{sec:names:case}
  54.211 +
  54.212 +If you're working in a mixed development environment that contains
  54.213 +both Linux (or other Unix) systems and Macs or Windows systems, you
  54.214 +should keep in the back of your mind the knowledge that they treat the
  54.215 +case (``N'' versus ``n'') of file names in incompatible ways.  This is
  54.216 +not very likely to affect you, and it's easy to deal with if it does,
  54.217 +but it could surprise you if you don't know about it.
  54.218 +
  54.219 +Operating systems and filesystems differ in the way they handle the
  54.220 +\emph{case} of characters in file and directory names.  There are
  54.221 +three common ways to handle case in names.
  54.222 +\begin{itemize}
  54.223 +\item Completely case insensitive.  Uppercase and lowercase versions
  54.224 +  of a letter are treated as identical, both when creating a file and
  54.225 +  during subsequent accesses.  This is common on older DOS-based
  54.226 +  systems.
  54.227 +\item Case preserving, but insensitive.  When a file or directory is
  54.228 +  created, the case of its name is stored, and can be retrieved and
  54.229 +  displayed by the operating system.  When an existing file is being
  54.230 +  looked up, its case is ignored.  This is the standard arrangement on
  54.231 +  Windows and MacOS.  The names \filename{foo} and \filename{FoO}
  54.232 +  identify the same file.  This treatment of uppercase and lowercase
  54.233 +  letters as interchangeable is also referred to as \emph{case
  54.234 +    folding}.
  54.235 +\item Case sensitive.  The case of a name is significant at all times.
  54.236 +  The names \filename{foo} and {FoO} identify different files.  This
  54.237 +  is the way Linux and Unix systems normally work.
  54.238 +\end{itemize}
  54.239 +
  54.240 +On Unix-like systems, it is possible to have any or all of the above
  54.241 +ways of handling case in action at once.  For example, if you use a
  54.242 +USB thumb drive formatted with a FAT32 filesystem on a Linux system,
  54.243 +Linux will handle names on that filesystem in a case preserving, but
  54.244 +insensitive, way.
  54.245 +
  54.246 +\subsection{Safe, portable repository storage}
  54.247 +
  54.248 +Mercurial's repository storage mechanism is \emph{case safe}.  It
  54.249 +translates file names so that they can be safely stored on both case
  54.250 +sensitive and case insensitive filesystems.  This means that you can
  54.251 +use normal file copying tools to transfer a Mercurial repository onto,
  54.252 +for example, a USB thumb drive, and safely move that drive and
  54.253 +repository back and forth between a Mac, a PC running Windows, and a
  54.254 +Linux box.
  54.255 +
  54.256 +\subsection{Detecting case conflicts}
  54.257 +
  54.258 +When operating in the working directory, Mercurial honours the naming
  54.259 +policy of the filesystem where the working directory is located.  If
  54.260 +the filesystem is case preserving, but insensitive, Mercurial will
  54.261 +treat names that differ only in case as the same.
  54.262 +
  54.263 +An important aspect of this approach is that it is possible to commit
  54.264 +a changeset on a case sensitive (typically Linux or Unix) filesystem
  54.265 +that will cause trouble for users on case insensitive (usually Windows
  54.266 +and MacOS) users.  If a Linux user commits changes to two files, one
  54.267 +named \filename{myfile.c} and the other named \filename{MyFile.C},
  54.268 +they will be stored correctly in the repository.  And in the working
  54.269 +directories of other Linux users, they will be correctly represented
  54.270 +as separate files.
  54.271 +
  54.272 +If a Windows or Mac user pulls this change, they will not initially
  54.273 +have a problem, because Mercurial's repository storage mechanism is
  54.274 +case safe.  However, once they try to \hgcmd{update} the working
  54.275 +directory to that changeset, or \hgcmd{merge} with that changeset,
  54.276 +Mercurial will spot the conflict between the two file names that the
  54.277 +filesystem would treat as the same, and forbid the update or merge
  54.278 +from occurring.
  54.279 +
  54.280 +\subsection{Fixing a case conflict}
  54.281 +
  54.282 +If you are using Windows or a Mac in a mixed environment where some of
  54.283 +your collaborators are using Linux or Unix, and Mercurial reports a
  54.284 +case folding conflict when you try to \hgcmd{update} or \hgcmd{merge},
  54.285 +the procedure to fix the problem is simple.
  54.286 +
  54.287 +Just find a nearby Linux or Unix box, clone the problem repository
  54.288 +onto it, and use Mercurial's \hgcmd{rename} command to change the
  54.289 +names of any offending files or directories so that they will no
  54.290 +longer cause case folding conflicts.  Commit this change, \hgcmd{pull}
  54.291 +or \hgcmd{push} it across to your Windows or MacOS system, and
  54.292 +\hgcmd{update} to the revision with the non-conflicting names.
  54.293 +
  54.294 +The changeset with case-conflicting names will remain in your
  54.295 +project's history, and you still won't be able to \hgcmd{update} your
  54.296 +working directory to that changeset on a Windows or MacOS system, but
  54.297 +you can continue development unimpeded.
  54.298 +
  54.299 +\begin{note}
  54.300 +  Prior to version~0.9.3, Mercurial did not use a case safe repository
  54.301 +  storage mechanism, and did not detect case folding conflicts.  If
  54.302 +  you are using an older version of Mercurial on Windows or MacOS, I
  54.303 +  strongly recommend that you upgrade.
  54.304 +\end{note}
  54.305 +
  54.306 +%%% Local Variables: 
  54.307 +%%% mode: latex
  54.308 +%%% TeX-master: "00book"
  54.309 +%%% End: 
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/fr/fixhtml.py	Thu Feb 05 12:37:03 2009 +0100
    55.3 @@ -0,0 +1,50 @@
    55.4 +#!/usr/bin/env python
    55.5 +#
    55.6 +# This script attempts to work around some of the more bizarre and
    55.7 +# quirky behaviours of htlatex.
    55.8 +#
    55.9 +# - We've persuaded htlatex to produce UTF-8, which unfortunately
   55.10 +#   causes it to use huge character sequences to represent even the
   55.11 +#   safe 7-bit ASCII subset of UTF-8.  We fix that up.
   55.12 +#
   55.13 +# - BUT we have to treat angle brackets (for example, redirections in
   55.14 +#   shell script snippets) specially, otherwise they'll break the
   55.15 +#   generated HTML.  (Reported by Johannes Hoff.)
   55.16 +#
   55.17 +# - For some reason, htlatex gives a unique ID to each fancyvrb
   55.18 +#   environment, which makes writing a sane, small CSS stylesheet
   55.19 +#   impossible.  We squish all those IDs down to nothing.
   55.20 +
   55.21 +import os
   55.22 +import sys
   55.23 +import re
   55.24 +
   55.25 +angle_re = re.compile(r'(&#x003[CE];)')
   55.26 +unicode_re = re.compile(r'&#x00([0-7][0-9A-F]);')
   55.27 +fancyvrb_re = re.compile(r'id="fancyvrb\d+"', re.I)
   55.28 +ligature_re = re.compile(r'&#xFB0([0-4]);')
   55.29 +
   55.30 +tmpsuffix = '.tmp.' + str(os.getpid())
   55.31 +
   55.32 +def hide_angle(m):
   55.33 +    return m.group(1).lower()
   55.34 +
   55.35 +def fix_ascii(m):
   55.36 +    return chr(int(m.group(1), 16))
   55.37 +
   55.38 +ligatures = ['ff', 'fi', 'fl', 'ffi', 'ffl']
   55.39 +
   55.40 +def expand_ligature(m):
   55.41 +    return ligatures[int(m.group(1))]
   55.42 +
   55.43 +for name in sys.argv[1:]:
   55.44 +    tmpname = name + tmpsuffix
   55.45 +    ofp = file(tmpname, 'w')
   55.46 +    for line in file(name):
   55.47 +        line = angle_re.sub(hide_angle, line)
   55.48 +        line = unicode_re.sub(fix_ascii, line)
   55.49 +        line = ligature_re.sub(expand_ligature, line)
   55.50 +        line = fancyvrb_re.sub('id="fancyvrb"', line)
   55.51 +        ofp.write(line)
   55.52 +    ofp.close()
   55.53 +    os.rename(tmpname, name)
    56.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    56.2 +++ b/fr/fixsvg	Thu Feb 05 12:37:03 2009 +0100
    56.3 @@ -0,0 +1,29 @@
    56.4 +#!/bin/bash
    56.5 +
    56.6 +test -d hello || hg clone http://hg.serpentine.com/tutorial/hello
    56.7 +
    56.8 +set -e
    56.9 +
   56.10 +for i in 0 1 2 3 4
   56.11 +do
   56.12 +  export REV$i=$(hg --cwd hello log -r $i --template '{node|short}' | cut -c1-4)
   56.13 +done
   56.14 +export REV_my_hello=$(cat /tmp/REV5.my-hello)
   56.15 +export REV_my_new_hello=$(cat /tmp/REV5.my-new-hello)
   56.16 +export REV6_my_new_hello=$(cat /tmp/REV6.my-new-hello)
   56.17 +export REV7_my_new_hello=$(cat /tmp/REV7.my-new-hello)
   56.18 +
   56.19 +FILE=$1
   56.20 +OUTFILE=$FILE-tmp.svg
   56.21 +rm -f $OUTFILE
   56.22 +echo "Fixing $FILE"
   56.23 +cp $FILE $OUTFILE
   56.24 +perl -p -i -e "s#REV0#$REV0#" $OUTFILE
   56.25 +perl -p -i -e "s#REV1#$REV1#" $OUTFILE
   56.26 +perl -p -i -e "s#REV2#$REV2#" $OUTFILE
   56.27 +perl -p -i -e "s#REV3#$REV3#" $OUTFILE
   56.28 +perl -p -i -e "s#REV4#$REV4#" $OUTFILE
   56.29 +perl -p -i -e "s#REV_my_hello#$REV_my_hello#" $OUTFILE
   56.30 +perl -p -i -e "s#REV_my_new_hello#$REV_my_new_hello#" $OUTFILE
   56.31 +perl -p -i -e "s#REV6_my_new_hello#$REV6_my_new_hello#" $OUTFILE
   56.32 +perl -p -i -e "s#REV7_my_new_hello#$REV7_my_new_hello#" $OUTFILE
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/fr/hgbook.css	Thu Feb 05 12:37:03 2009 +0100
    57.3 @@ -0,0 +1,441 @@
    57.4 +body {
    57.5 +  font: 12px/1.5 Verdana, sans-serif;
    57.6 +  padding-top: 50px;
    57.7 +  padding-left: 80px;
    57.8 +  padding-right: 80px;
    57.9 +  padding-bottom: 90px;
   57.10 +}
   57.11 +.ptmr7t- {
   57.12 +  font-family: monospace;
   57.13 +}
   57.14 +.ptmr7t-x-x-172 {
   57.15 +  font-size: 172%;
   57.16 +  font-family: monospace;
   57.17 +}
   57.18 +.ptmr7t-x-x-120 {
   57.19 +  font-size: 120%;
   57.20 +}
   57.21 +.zpzccmry-x-x-120 {
   57.22 +  font-size: 120%;
   57.23 +  font-weight: bold;
   57.24 +  font-style: italic;
   57.25 +}
   57.26 +.zpzccmry-x-x-120 {
   57.27 +  font-weight: bold;
   57.28 +  font-style: italic;
   57.29 +}
   57.30 +.pcrr7tn- {
   57.31 +  font-family: monospace;
   57.32 +}
   57.33 +.ptmri7t- {
   57.34 +  font-style: italic;
   57.35 +}
   57.36 +.ptmr7t-x-x-50 {
   57.37 +  font-size: 50%;
   57.38 +  font-family: monospace;
   57.39 +}
   57.40 +.ptmb7t- {
   57.41 +  font-weight: bold;
   57.42 +}
   57.43 +.zptmcmr- {
   57.44 +  font-style: italic;
   57.45 +}
   57.46 +.zptmcmrm- {
   57.47 +  font-style: italic;
   57.48 +}
   57.49 +.zpzccmry- {
   57.50 +  font-weight: bold;
   57.51 +  font-style: italic;
   57.52 +}
   57.53 +.pcrb7t- {
   57.54 +  font-family: monospace;
   57.55 +  font-weight: bold;
   57.56 +}
   57.57 +.pcrro7t- {
   57.58 +  font-family: monospace;
   57.59 +  font-style: oblique;
   57.60 +}
   57.61 +p.noindent {
   57.62 +  text-indent: 0em;
   57.63 +  margin: 0em;
   57.64 +}
   57.65 +p.nopar {
   57.66 +  text-indent: 0em;
   57.67 +}
   57.68 +p.indent {
   57.69 +  text-indent: 1.5em;
   57.70 +  margin: 0em;
   57.71 +}
   57.72 +a img {
   57.73 +  border-top: 0;
   57.74 +  border-left: 0;
   57.75 +  border-right: 0;
   57.76 +}
   57.77 +center {
   57.78 +  margin-top: 1em;
   57.79 +  margin-bottom: 1em;
   57.80 +}
   57.81 +td center {
   57.82 +  margin-top: 0em;
   57.83 +  margin-bottom: 0em;
   57.84 +}
   57.85 +.Canvas {
   57.86 +  position: relative;
   57.87 +}
   57.88 +img.math {
   57.89 +  vertical-align: middle;
   57.90 +}
   57.91 +li p.indent {
   57.92 +  text-indent: 0em;
   57.93 +}
   57.94 +.enumerate1 {
   57.95 +  list-style-type: decimal;
   57.96 +}
   57.97 +.enumerate2 {
   57.98 +  list-style-type: lower-alpha;
   57.99 +}
  57.100 +.enumerate3 {
  57.101 +  list-style-type: lower-roman;
  57.102 +}
  57.103 +.enumerate4 {
  57.104 +  list-style-type: upper-alpha;
  57.105 +}
  57.106 +div.newtheorem {
  57.107 +  margin-bottom: 2em;
  57.108 +  margin-top: 2em;
  57.109 +}
  57.110 +.obeylines-h,.obeylines-v {
  57.111 +  white-space: nowrap;
  57.112 +}
  57.113 +div.obeylines-v p {
  57.114 +  margin-top: 0;
  57.115 +  margin-bottom: 0;
  57.116 +}
  57.117 +.overline {
  57.118 +  text-decoration: overline;
  57.119 +}
  57.120 +.overline img {
  57.121 +  border-top: 1px solid black;
  57.122 +}
  57.123 +td.displaylines {
  57.124 +  text-align: center;
  57.125 +  white-space: nowrap;
  57.126 +}
  57.127 +.centerline {
  57.128 +  text-align: center;
  57.129 +}
  57.130 +.rightline {
  57.131 +  text-align: right;
  57.132 +}
  57.133 +div.verbatim {
  57.134 +  font-family: monospace;
  57.135 +  white-space: nowrap;
  57.136 +}
  57.137 +table.verbatim {
  57.138 +  width: 100%;
  57.139 +}
  57.140 +.fbox {
  57.141 +  background: url(note.png) no-repeat #cec;
  57.142 +  padding-left: 65px;
  57.143 +  padding-top: 1em;
  57.144 +  padding-bottom: 1em;
  57.145 +  padding-right: 1em;
  57.146 +  text-indent: 0pt;
  57.147 +  border: dotted black 1px;
  57.148 +}
  57.149 +div.center div.fbox {
  57.150 +  text-align: center;
  57.151 +  clear: both;
  57.152 +  padding-left: 3.0pt;
  57.153 +  padding-right: 3.0pt;
  57.154 +  text-indent: 0pt;
  57.155 +  border: solid black 0.4pt;
  57.156 +}
  57.157 +table.minipage {
  57.158 +  width: 100%;
  57.159 +}
  57.160 +div.center, div.center div.center {
  57.161 +  text-align: center;
  57.162 +  margin-left: 1em;
  57.163 +  margin-right: 1em;
  57.164 +}
  57.165 +div.center div {
  57.166 +  text-align: left;
  57.167 +}
  57.168 +div.flushright, div.flushright div.flushright {
  57.169 +  text-align: right;
  57.170 +}
  57.171 +div.flushright div {
  57.172 +  text-align: left;
  57.173 +}
  57.174 +div.flushleft {
  57.175 +  text-align: left;
  57.176 +}
  57.177 +.underline {
  57.178 +  text-decoration: underline;
  57.179 +}
  57.180 +.underline img {
  57.181 +  border-bottom: 1px solid black;
  57.182 +  margin-bottom: 1pt;
  57.183 +}
  57.184 +.framebox-c, .framebox-l, .framebox-r {
  57.185 +  padding-left: 3.0pt;
  57.186 +  padding-right: 3.0pt;
  57.187 +  text-indent: 0pt;
  57.188 +  border: solid black 0.4pt;
  57.189 +}
  57.190 +.framebox-c {
  57.191 +  text-align: center;
  57.192 +}
  57.193 +.framebox-l {
  57.194 +  text-align: left;
  57.195 +}
  57.196 +.framebox-r {
  57.197 +  text-align: right;
  57.198 +}
  57.199 +span.thank-mark {
  57.200 +  vertical-align: super
  57.201 +}
  57.202 +span.footnote-mark sup.textsuperscript, span.footnote-mark a sup.textsuperscript {
  57.203 +  font-size: 80%;
  57.204 +}
  57.205 +div.tabular, div.center div.tabular {
  57.206 +  text-align: center;
  57.207 +  margin-top: 0.5em;
  57.208 +  margin-bottom: 0.5em;
  57.209 +}
  57.210 +table.tabular td p {
  57.211 +  margin-top: 0em;
  57.212 +}
  57.213 +table.tabular {
  57.214 +  margin-left: auto;
  57.215 +  margin-right: auto;
  57.216 +}
  57.217 +div.td00 {
  57.218 +  margin-left: 0pt;
  57.219 +  margin-right: 0pt;
  57.220 +}
  57.221 +div.td01 {
  57.222 +  margin-left: 0pt;
  57.223 +  margin-right: 5pt;
  57.224 +}
  57.225 +div.td10 {
  57.226 +  margin-left: 5pt;
  57.227 +  margin-right: 0pt;
  57.228 +}
  57.229 +div.td11 {
  57.230 +  margin-left: 5pt;
  57.231 +  margin-right: 5pt;
  57.232 +}
  57.233 +table[rules] {
  57.234 +  border-left: solid black 0.4pt;
  57.235 +  border-right: solid black 0.4pt;
  57.236 +}
  57.237 +td.td00 {
  57.238 +  padding-left: 0pt;
  57.239 +  padding-right: 0pt;
  57.240 +}
  57.241 +td.td01 {
  57.242 +  padding-left: 0pt;
  57.243 +  padding-right: 5pt;
  57.244 +}
  57.245 +td.td10 {
  57.246 +  padding-left: 5pt;
  57.247 +  padding-right: 0pt;
  57.248 +}
  57.249 +td.td11 {
  57.250 +  padding-left: 5pt;
  57.251 +  padding-right: 5pt;
  57.252 +}
  57.253 +table[rules] {
  57.254 +  border-left: solid black 0.4pt;
  57.255 +  border-right: solid black 0.4pt;
  57.256 +}
  57.257 +.hline hr, .cline hr {
  57.258 +  height : 1px;
  57.259 +  margin: 0px;
  57.260 +}
  57.261 +.tabbing-right {
  57.262 +  text-align: right;
  57.263 +}
  57.264 +span.TEX {
  57.265 +  letter-spacing: -0.125em;
  57.266 +}
  57.267 +span.TEX span.E {
  57.268 +  position: relative;top: 0.5ex;left: -0.0417em;
  57.269 +}
  57.270 +a span.TEX span.E {
  57.271 +  text-decoration: none;
  57.272 +}
  57.273 +span.LATEX span.A {
  57.274 +  position: relative;
  57.275 +  top: -0.5ex;
  57.276 +  left: -0.4em;
  57.277 +  font-size: 85%;
  57.278 +}
  57.279 +span.LATEX span.TEX {
  57.280 +  position: relative;
  57.281 +  left: -0.4em;
  57.282 +}
  57.283 +div.float img, div.float .caption {
  57.284 +  text-align: center;
  57.285 +}
  57.286 +div.figure img, div.figure .caption {
  57.287 +  text-align: center;
  57.288 +}
  57.289 +.marginpar {
  57.290 +  width: 20%;
  57.291 +  float: right;
  57.292 +  text-align: left;
  57.293 +  margin-left: auto;
  57.294 +  margin-top: 0.5em;
  57.295 +  font-size: 85%;
  57.296 +  text-decoration: underline;
  57.297 +}
  57.298 +.marginpar p {
  57.299 +  margin-top: 0.4em;
  57.300 +  margin-bottom: 0.4em;
  57.301 +}
  57.302 +table.equation {
  57.303 +  width: 100%;
  57.304 +}
  57.305 +.equation td {
  57.306 +  text-align: center;
  57.307 +}
  57.308 +td.equation {
  57.309 +  margin-top: 1em;
  57.310 +  margin-bottom: 1em;
  57.311 +} 
  57.312 +td.equation-label {
  57.313 +  width: 5%;
  57.314 +  text-align: center;
  57.315 +}
  57.316 +td.eqnarray4 {
  57.317 +  width: 5%;
  57.318 +  white-space: normal;
  57.319 +}
  57.320 +td.eqnarray2 {
  57.321 +  width: 5%;
  57.322 +}
  57.323 +table.eqnarray-star, table.eqnarray {
  57.324 +  width: 100%;
  57.325 +}
  57.326 +div.eqnarray {
  57.327 +  text-align: center;
  57.328 +}
  57.329 +div.array {
  57.330 +  text-align: center;
  57.331 +}
  57.332 +div.pmatrix {
  57.333 +  text-align: center;
  57.334 +}
  57.335 +table.pmatrix {
  57.336 +  width: 100%;
  57.337 +}
  57.338 +span.pmatrix img {
  57.339 +  vertical-align: middle;
  57.340 +}
  57.341 +div.pmatrix {
  57.342 +  text-align: center;
  57.343 +}
  57.344 +table.pmatrix {
  57.345 +  width: 100%;
  57.346 +}
  57.347 +img.cdots {
  57.348 +  vertical-align: middle;
  57.349 +}
  57.350 +.partToc a, .partToc, .likepartToc a, .likepartToc {
  57.351 +  line-height: 200%;
  57.352 +  font-weight: bold;
  57.353 +  font-size: 110%;
  57.354 +}
  57.355 +.chapterToc a, .chapterToc, .likechapterToc a, .likechapterToc, .appendixToc a, .appendixToc {
  57.356 +  line-height: 200%;
  57.357 +  font-weight: bold;
  57.358 +}
  57.359 +.caption td.id {
  57.360 +  font-weight: bold;
  57.361 +  white-space: nowrap;
  57.362 +}
  57.363 +table.caption {
  57.364 +  text-align: center;
  57.365 +}
  57.366 +h1.partHead {
  57.367 +  text-align: center;
  57.368 +}
  57.369 +p.bibitem {
  57.370 +  text-indent: -2em;
  57.371 +  margin-left: 2em;
  57.372 +  margin-top: 0.6em;
  57.373 +  margin-bottom: 0.6em;
  57.374 +}
  57.375 +p.bibitem-p {
  57.376 +  text-indent: 0em;
  57.377 +  margin-left: 2em;
  57.378 +  margin-top: 0.6em;
  57.379 +  margin-bottom: 0.6em;
  57.380 +}
  57.381 +.paragraphHead, .likeparagraphHead {
  57.382 +  margin-top: 2em;
  57.383 +  font-weight: bold;
  57.384 +}
  57.385 +.subparagraphHead, .likesubparagraphHead {
  57.386 +  font-weight: bold;
  57.387 +}
  57.388 +.quote {
  57.389 +  margin-bottom: 0.25em;
  57.390 +  margin-top: 0.25em;
  57.391 +  margin-left: 1em;
  57.392 +  margin-right: 1em;
  57.393 +  text-align: justify;
  57.394 +}
  57.395 +.verse {
  57.396 +  white-space: nowrap;
  57.397 +  margin-left: 2em}
  57.398 +div.maketitle {
  57.399 +  text-align: center;
  57.400 +}
  57.401 +h2.titleHead {
  57.402 +  text-align: center;
  57.403 +}
  57.404 +div.maketitle {
  57.405 +  margin-bottom: 2em;
  57.406 +}
  57.407 +div.author, div.date {
  57.408 +  text-align: center;
  57.409 +}
  57.410 +div.thanks {
  57.411 +  text-align: left;
  57.412 +  margin-left: 10%;
  57.413 +  font-size: 85%;
  57.414 +  font-style: italic;
  57.415 +}
  57.416 +div.author {
  57.417 +  white-space: nowrap;
  57.418 +}
  57.419 +.quotation {
  57.420 +  margin-bottom: 0.25em;
  57.421 +  margin-top: 0.25em;
  57.422 +  margin-left: 1em;
  57.423 +}
  57.424 +h1.partHead {
  57.425 +  text-align: center;
  57.426 +}
  57.427 +img.graphics {
  57.428 +  margin-left: 10%;
  57.429 +}
  57.430 +.figure {
  57.431 +  width: 100%;
  57.432 +}
  57.433 +P.fancyvrb {
  57.434 +  white-space: nowrap;
  57.435 +}
  57.436 +hr {
  57.437 +  border: 0;
  57.438 +  height: 1px;
  57.439 +}
  57.440 +div#fancyvrb {
  57.441 +  white-space: nowrap;
  57.442 +  background: #eee;
  57.443 +  padding: 1em;
  57.444 +}
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/fr/hgext.tex	Thu Feb 05 12:37:03 2009 +0100
    58.3 @@ -0,0 +1,429 @@
    58.4 +\chapter{Adding functionality with extensions}
    58.5 +\label{chap:hgext}
    58.6 +
    58.7 +While the core of Mercurial is quite complete from a functionality
    58.8 +standpoint, it's deliberately shorn of fancy features.  This approach
    58.9 +of preserving simplicity keeps the software easy to deal with for both
   58.10 +maintainers and users.
   58.11 +
   58.12 +However, Mercurial doesn't box you in with an inflexible command set:
   58.13 +you can add features to it as \emph{extensions} (sometimes known as
   58.14 +\emph{plugins}).  We've already discussed a few of these extensions in
   58.15 +earlier chapters.
   58.16 +\begin{itemize}
   58.17 +\item Section~\ref{sec:tour-merge:fetch} covers the \hgext{fetch}
   58.18 +  extension; this combines pulling new changes and merging them with
   58.19 +  local changes into a single command, \hgxcmd{fetch}{fetch}.
   58.20 +\item In chapter~\ref{chap:hook}, we covered several extensions that
   58.21 +  are useful for hook-related functionality: \hgext{acl} adds access
   58.22 +  control lists; \hgext{bugzilla} adds integration with the Bugzilla
   58.23 +  bug tracking system; and \hgext{notify} sends notification emails on
   58.24 +  new changes.
   58.25 +\item The Mercurial Queues patch management extension is so invaluable
   58.26 +  that it merits two chapters and an appendix all to itself.
   58.27 +  Chapter~\ref{chap:mq} covers the basics;
   58.28 +  chapter~\ref{chap:mq-collab} discusses advanced topics; and
   58.29 +  appendix~\ref{chap:mqref} goes into detail on each command.
   58.30 +\end{itemize}
   58.31 +
   58.32 +In this chapter, we'll cover some of the other extensions that are
   58.33 +available for Mercurial, and briefly touch on some of the machinery
   58.34 +you'll need to know about if you want to write an extension of your
   58.35 +own.
   58.36 +\begin{itemize}
   58.37 +\item In section~\ref{sec:hgext:inotify}, we'll discuss the
   58.38 +  possibility of \emph{huge} performance improvements using the
   58.39 +  \hgext{inotify} extension.
   58.40 +\end{itemize}
   58.41 +
   58.42 +\section{Improve performance with the \hgext{inotify} extension}
   58.43 +\label{sec:hgext:inotify}
   58.44 +
   58.45 +Are you interested in having some of the most common Mercurial
   58.46 +operations run as much as a hundred times faster?  Read on!
   58.47 +
   58.48 +Mercurial has great performance under normal circumstances.  For
   58.49 +example, when you run the \hgcmd{status} command, Mercurial has to
   58.50 +scan almost every directory and file in your repository so that it can
   58.51 +display file status.  Many other Mercurial commands need to do the
   58.52 +same work behind the scenes; for example, the \hgcmd{diff} command
   58.53 +uses the status machinery to avoid doing an expensive comparison
   58.54 +operation on files that obviously haven't changed.
   58.55 +
   58.56 +Because obtaining file status is crucial to good performance, the
   58.57 +authors of Mercurial have optimised this code to within an inch of its
   58.58 +life.  However, there's no avoiding the fact that when you run
   58.59 +\hgcmd{status}, Mercurial is going to have to perform at least one
   58.60 +expensive system call for each managed file to determine whether it's
   58.61 +changed since the last time Mercurial checked.  For a sufficiently
   58.62 +large repository, this can take a long time.
   58.63 +
   58.64 +To put a number on the magnitude of this effect, I created a
   58.65 +repository containing 150,000 managed files.  I timed \hgcmd{status}
   58.66 +as taking ten seconds to run, even when \emph{none} of those files had
   58.67 +been modified.
   58.68 +
   58.69 +Many modern operating systems contain a file notification facility.
   58.70 +If a program signs up to an appropriate service, the operating system
   58.71 +will notify it every time a file of interest is created, modified, or
   58.72 +deleted.  On Linux systems, the kernel component that does this is
   58.73 +called \texttt{inotify}.
   58.74 +
   58.75 +Mercurial's \hgext{inotify} extension talks to the kernel's
   58.76 +\texttt{inotify} component to optimise \hgcmd{status} commands.  The
   58.77 +extension has two components.  A daemon sits in the background and
   58.78 +receives notifications from the \texttt{inotify} subsystem.  It also
   58.79 +listens for connections from a regular Mercurial command.  The
   58.80 +extension modifies Mercurial's behaviour so that instead of scanning
   58.81 +the filesystem, it queries the daemon.  Since the daemon has perfect
   58.82 +information about the state of the repository, it can respond with a
   58.83 +result instantaneously, avoiding the need to scan every directory and
   58.84 +file in the repository.
   58.85 +
   58.86 +Recall the ten seconds that I measured plain Mercurial as taking to
   58.87 +run \hgcmd{status} on a 150,000 file repository.  With the
   58.88 +\hgext{inotify} extension enabled, the time dropped to 0.1~seconds, a
   58.89 +factor of \emph{one hundred} faster.
   58.90 +
   58.91 +Before we continue, please pay attention to some caveats.
   58.92 +\begin{itemize}
   58.93 +\item The \hgext{inotify} extension is Linux-specific.  Because it
   58.94 +  interfaces directly to the Linux kernel's \texttt{inotify}
   58.95 +  subsystem, it does not work on other operating systems.
   58.96 +\item It should work on any Linux distribution that was released after
   58.97 +  early~2005.  Older distributions are likely to have a kernel that
   58.98 +  lacks \texttt{inotify}, or a version of \texttt{glibc} that does not
   58.99 +  have the necessary interfacing support.
  58.100 +\item Not all filesystems are suitable for use with the
  58.101 +  \hgext{inotify} extension.  Network filesystems such as NFS are a
  58.102 +  non-starter, for example, particularly if you're running Mercurial
  58.103 +  on several systems, all mounting the same network filesystem.  The
  58.104 +  kernel's \texttt{inotify} system has no way of knowing about changes
  58.105 +  made on another system.  Most local filesystems (e.g.~ext3, XFS,
  58.106 +  ReiserFS) should work fine.
  58.107 +\end{itemize}
  58.108 +
  58.109 +The \hgext{inotify} extension is not yet shipped with Mercurial as of
  58.110 +May~2007, so it's a little more involved to set up than other
  58.111 +extensions.  But the performance improvement is worth it!
  58.112 +
  58.113 +The extension currently comes in two parts: a set of patches to the
  58.114 +Mercurial source code, and a library of Python bindings to the
  58.115 +\texttt{inotify} subsystem.
  58.116 +\begin{note}
  58.117 +  There are \emph{two} Python \texttt{inotify} binding libraries.  One
  58.118 +  of them is called \texttt{pyinotify}, and is packaged by some Linux
  58.119 +  distributions as \texttt{python-inotify}.  This is \emph{not} the
  58.120 +  one you'll need, as it is too buggy and inefficient to be practical.
  58.121 +\end{note}
  58.122 +To get going, it's best to already have a functioning copy of
  58.123 +Mercurial installed.
  58.124 +\begin{note}
  58.125 +  If you follow the instructions below, you'll be \emph{replacing} and
  58.126 +  overwriting any existing installation of Mercurial that you might
  58.127 +  already have, using the latest ``bleeding edge'' Mercurial code.
  58.128 +  Don't say you weren't warned!
  58.129 +\end{note}
  58.130 +\begin{enumerate}
  58.131 +\item Clone the Python \texttt{inotify} binding repository.  Build and
  58.132 +  install it.
  58.133 +  \begin{codesample4}
  58.134 +    hg clone http://hg.kublai.com/python/inotify
  58.135 +    cd inotify
  58.136 +    python setup.py build --force
  58.137 +    sudo python setup.py install --skip-build
  58.138 +  \end{codesample4}
  58.139 +\item Clone the \dirname{crew} Mercurial repository.  Clone the
  58.140 +  \hgext{inotify} patch repository so that Mercurial Queues will be
  58.141 +  able to apply patches to your cope of the \dirname{crew} repository.
  58.142 +  \begin{codesample4}
  58.143 +    hg clone http://hg.intevation.org/mercurial/crew
  58.144 +    hg clone crew inotify
  58.145 +    hg clone http://hg.kublai.com/mercurial/patches/inotify inotify/.hg/patches
  58.146 +  \end{codesample4}
  58.147 +\item Make sure that you have the Mercurial Queues extension,
  58.148 +  \hgext{mq}, enabled.  If you've never used MQ, read
  58.149 +  section~\ref{sec:mq:start} to get started quickly.
  58.150 +\item Go into the \dirname{inotify} repo, and apply all of the
  58.151 +  \hgext{inotify} patches using the \hgxopt{mq}{qpush}{-a} option to
  58.152 +  the \hgxcmd{mq}{qpush} command.
  58.153 +  \begin{codesample4}
  58.154 +    cd inotify
  58.155 +    hg qpush -a
  58.156 +  \end{codesample4}
  58.157 +  If you get an error message from \hgxcmd{mq}{qpush}, you should not
  58.158 +  continue.  Instead, ask for help.
  58.159 +\item Build and install the patched version of Mercurial.
  58.160 +  \begin{codesample4}
  58.161 +    python setup.py build --force
  58.162 +    sudo python setup.py install --skip-build
  58.163 +  \end{codesample4}
  58.164 +\end{enumerate}
  58.165 +Once you've build a suitably patched version of Mercurial, all you
  58.166 +need to do to enable the \hgext{inotify} extension is add an entry to
  58.167 +your \hgrc.
  58.168 +\begin{codesample2}
  58.169 +  [extensions]
  58.170 +  inotify =
  58.171 +\end{codesample2}
  58.172 +When the \hgext{inotify} extension is enabled, Mercurial will
  58.173 +automatically and transparently start the status daemon the first time
  58.174 +you run a command that needs status in a repository.  It runs one
  58.175 +status daemon per repository.
  58.176 +
  58.177 +The status daemon is started silently, and runs in the background.  If
  58.178 +you look at a list of running processes after you've enabled the
  58.179 +\hgext{inotify} extension and run a few commands in different
  58.180 +repositories, you'll thus see a few \texttt{hg} processes sitting
  58.181 +around, waiting for updates from the kernel and queries from
  58.182 +Mercurial.
  58.183 +
  58.184 +The first time you run a Mercurial command in a repository when you
  58.185 +have the \hgext{inotify} extension enabled, it will run with about the
  58.186 +same performance as a normal Mercurial command.  This is because the
  58.187 +status daemon needs to perform a normal status scan so that it has a
  58.188 +baseline against which to apply later updates from the kernel.
  58.189 +However, \emph{every} subsequent command that does any kind of status
  58.190 +check should be noticeably faster on repositories of even fairly
  58.191 +modest size.  Better yet, the bigger your repository is, the greater a
  58.192 +performance advantage you'll see.  The \hgext{inotify} daemon makes
  58.193 +status operations almost instantaneous on repositories of all sizes!
  58.194 +
  58.195 +If you like, you can manually start a status daemon using the
  58.196 +\hgxcmd{inotify}{inserve} command.  This gives you slightly finer
  58.197 +control over how the daemon ought to run.  This command will of course
  58.198 +only be available when the \hgext{inotify} extension is enabled.
  58.199 +
  58.200 +When you're using the \hgext{inotify} extension, you should notice
  58.201 +\emph{no difference at all} in Mercurial's behaviour, with the sole
  58.202 +exception of status-related commands running a whole lot faster than
  58.203 +they used to.  You should specifically expect that commands will not
  58.204 +print different output; neither should they give different results.
  58.205 +If either of these situations occurs, please report a bug.
  58.206 +
  58.207 +\section{Flexible diff support with the \hgext{extdiff} extension}
  58.208 +\label{sec:hgext:extdiff}
  58.209 +
  58.210 +Mercurial's built-in \hgcmd{diff} command outputs plaintext unified
  58.211 +diffs.
  58.212 +\interaction{extdiff.diff}
  58.213 +If you would like to use an external tool to display modifications,
  58.214 +you'll want to use the \hgext{extdiff} extension.  This will let you
  58.215 +use, for example, a graphical diff tool.
  58.216 +
  58.217 +The \hgext{extdiff} extension is bundled with Mercurial, so it's easy
  58.218 +to set up.  In the \rcsection{extensions} section of your \hgrc,
  58.219 +simply add a one-line entry to enable the extension.
  58.220 +\begin{codesample2}
  58.221 +  [extensions]
  58.222 +  extdiff =
  58.223 +\end{codesample2}
  58.224 +This introduces a command named \hgxcmd{extdiff}{extdiff}, which by
  58.225 +default uses your system's \command{diff} command to generate a
  58.226 +unified diff in the same form as the built-in \hgcmd{diff} command.
  58.227 +\interaction{extdiff.extdiff}
  58.228 +The result won't be exactly the same as with the built-in \hgcmd{diff}
  58.229 +variations, because the output of \command{diff} varies from one
  58.230 +system to another, even when passed the same options.
  58.231 +
  58.232 +As the ``\texttt{making snapshot}'' lines of output above imply, the
  58.233 +\hgxcmd{extdiff}{extdiff} command works by creating two snapshots of
  58.234 +your source tree.  The first snapshot is of the source revision; the
  58.235 +second, of the target revision or working directory.  The
  58.236 +\hgxcmd{extdiff}{extdiff} command generates these snapshots in a
  58.237 +temporary directory, passes the name of each directory to an external
  58.238 +diff viewer, then deletes the temporary directory.  For efficiency, it
  58.239 +only snapshots the directories and files that have changed between the
  58.240 +two revisions.
  58.241 +
  58.242 +Snapshot directory names have the same base name as your repository.
  58.243 +If your repository path is \dirname{/quux/bar/foo}, then \dirname{foo}
  58.244 +will be the name of each snapshot directory.  Each snapshot directory
  58.245 +name has its changeset ID appended, if appropriate.  If a snapshot is
  58.246 +of revision \texttt{a631aca1083f}, the directory will be named
  58.247 +\dirname{foo.a631aca1083f}.  A snapshot of the working directory won't
  58.248 +have a changeset ID appended, so it would just be \dirname{foo} in
  58.249 +this example.  To see what this looks like in practice, look again at
  58.250 +the \hgxcmd{extdiff}{extdiff} example above.  Notice that the diff has
  58.251 +the snapshot directory names embedded in its header.
  58.252 +
  58.253 +The \hgxcmd{extdiff}{extdiff} command accepts two important options.
  58.254 +The \hgxopt{extdiff}{extdiff}{-p} option lets you choose a program to
  58.255 +view differences with, instead of \command{diff}.  With the
  58.256 +\hgxopt{extdiff}{extdiff}{-o} option, you can change the options that
  58.257 +\hgxcmd{extdiff}{extdiff} passes to the program (by default, these
  58.258 +options are ``\texttt{-Npru}'', which only make sense if you're
  58.259 +running \command{diff}).  In other respects, the
  58.260 +\hgxcmd{extdiff}{extdiff} command acts similarly to the built-in
  58.261 +\hgcmd{diff} command: you use the same option names, syntax, and
  58.262 +arguments to specify the revisions you want, the files you want, and
  58.263 +so on.
  58.264 +
  58.265 +As an example, here's how to run the normal system \command{diff}
  58.266 +command, getting it to generate context diffs (using the
  58.267 +\cmdopt{diff}{-c} option) instead of unified diffs, and five lines of
  58.268 +context instead of the default three (passing \texttt{5} as the
  58.269 +argument to the \cmdopt{diff}{-C} option).
  58.270 +\interaction{extdiff.extdiff-ctx}
  58.271 +
  58.272 +Launching a visual diff tool is just as easy.  Here's how to launch
  58.273 +the \command{kdiff3} viewer.
  58.274 +\begin{codesample2}
  58.275 +  hg extdiff -p kdiff3 -o ''
  58.276 +\end{codesample2}
  58.277 +
  58.278 +If your diff viewing command can't deal with directories, you can
  58.279 +easily work around this with a little scripting.  For an example of
  58.280 +such scripting in action with the \hgext{mq} extension and the
  58.281 +\command{interdiff} command, see
  58.282 +section~\ref{mq-collab:tips:interdiff}.
  58.283 +
  58.284 +\subsection{Defining command aliases}
  58.285 +
  58.286 +It can be cumbersome to remember the options to both the
  58.287 +\hgxcmd{extdiff}{extdiff} command and the diff viewer you want to use,
  58.288 +so the \hgext{extdiff} extension lets you define \emph{new} commands
  58.289 +that will invoke your diff viewer with exactly the right options.
  58.290 +
  58.291 +All you need to do is edit your \hgrc, and add a section named
  58.292 +\rcsection{extdiff}.  Inside this section, you can define multiple
  58.293 +commands.  Here's how to add a \texttt{kdiff3} command.  Once you've
  58.294 +defined this, you can type ``\texttt{hg kdiff3}'' and the
  58.295 +\hgext{extdiff} extension will run \command{kdiff3} for you.
  58.296 +\begin{codesample2}
  58.297 +  [extdiff]
  58.298 +  cmd.kdiff3 =
  58.299 +\end{codesample2}
  58.300 +If you leave the right hand side of the definition empty, as above,
  58.301 +the \hgext{extdiff} extension uses the name of the command you defined
  58.302 +as the name of the external program to run.  But these names don't
  58.303 +have to be the same.  Here, we define a command named ``\texttt{hg
  58.304 +  wibble}'', which runs \command{kdiff3}.
  58.305 +\begin{codesample2}
  58.306 +  [extdiff]
  58.307 +  cmd.wibble = kdiff3
  58.308 +\end{codesample2}
  58.309 +
  58.310 +You can also specify the default options that you want to invoke your
  58.311 +diff viewing program with.  The prefix to use is ``\texttt{opts.}'',
  58.312 +followed by the name of the command to which the options apply.  This
  58.313 +example defines a ``\texttt{hg vimdiff}'' command that runs the
  58.314 +\command{vim} editor's \texttt{DirDiff} extension.
  58.315 +\begin{codesample2}
  58.316 +  [extdiff]  
  58.317 +  cmd.vimdiff = vim
  58.318 +  opts.vimdiff = -f '+next' '+execute "DirDiff" argv(0) argv(1)'
  58.319 +\end{codesample2}
  58.320 +
  58.321 +\section{Cherrypicking changes with the \hgext{transplant} extension}
  58.322 +\label{sec:hgext:transplant}
  58.323 +
  58.324 +Need to have a long chat with Brendan about this.
  58.325 +
  58.326 +\section{Send changes via email with the \hgext{patchbomb} extension}
  58.327 +\label{sec:hgext:patchbomb}
  58.328 +
  58.329 +Many projects have a culture of ``change review'', in which people
  58.330 +send their modifications to a mailing list for others to read and
  58.331 +comment on before they commit the final version to a shared
  58.332 +repository.  Some projects have people who act as gatekeepers; they
  58.333 +apply changes from other people to a repository to which those others
  58.334 +don't have access.
  58.335 +
  58.336 +Mercurial makes it easy to send changes over email for review or
  58.337 +application, via its \hgext{patchbomb} extension.  The extension is so
  58.338 +namd because changes are formatted as patches, and it's usual to send
  58.339 +one changeset per email message.  Sending a long series of changes by
  58.340 +email is thus much like ``bombing'' the recipient's inbox, hence
  58.341 +``patchbomb''.
  58.342 +
  58.343 +As usual, the basic configuration of the \hgext{patchbomb} extension
  58.344 +takes just one or two lines in your \hgrc.
  58.345 +\begin{codesample2}
  58.346 +  [extensions]
  58.347 +  patchbomb =
  58.348 +\end{codesample2}
  58.349 +Once you've enabled the extension, you will have a new command
  58.350 +available, named \hgxcmd{patchbomb}{email}.
  58.351 +
  58.352 +The safest and best way to invoke the \hgxcmd{patchbomb}{email}
  58.353 +command is to \emph{always} run it first with the
  58.354 +\hgxopt{patchbomb}{email}{-n} option.  This will show you what the
  58.355 +command \emph{would} send, without actually sending anything.  Once
  58.356 +you've had a quick glance over the changes and verified that you are
  58.357 +sending the right ones, you can rerun the same command, with the
  58.358 +\hgxopt{patchbomb}{email}{-n} option removed.
  58.359 +
  58.360 +The \hgxcmd{patchbomb}{email} command accepts the same kind of
  58.361 +revision syntax as every other Mercurial command.  For example, this
  58.362 +command will send every revision between 7 and \texttt{tip},
  58.363 +inclusive.
  58.364 +\begin{codesample2}
  58.365 +  hg email -n 7:tip
  58.366 +\end{codesample2}
  58.367 +You can also specify a \emph{repository} to compare with.  If you
  58.368 +provide a repository but no revisions, the \hgxcmd{patchbomb}{email}
  58.369 +command will send all revisions in the local repository that are not
  58.370 +present in the remote repository.  If you additionally specify
  58.371 +revisions or a branch name (the latter using the
  58.372 +\hgxopt{patchbomb}{email}{-b} option), this will constrain the
  58.373 +revisions sent.
  58.374 +
  58.375 +It's perfectly safe to run the \hgxcmd{patchbomb}{email} command
  58.376 +without the names of the people you want to send to: if you do this,
  58.377 +it will just prompt you for those values interactively.  (If you're
  58.378 +using a Linux or Unix-like system, you should have enhanced
  58.379 +\texttt{readline}-style editing capabilities when entering those
  58.380 +headers, too, which is useful.)
  58.381 +
  58.382 +When you are sending just one revision, the \hgxcmd{patchbomb}{email}
  58.383 +command will by default use the first line of the changeset
  58.384 +description as the subject of the single email message it sends.
  58.385 +
  58.386 +If you send multiple revisions, the \hgxcmd{patchbomb}{email} command
  58.387 +will usually send one message per changeset.  It will preface the
  58.388 +series with an introductory message, in which you should describe the
  58.389 +purpose of the series of changes you're sending.
  58.390 +
  58.391 +\subsection{Changing the behaviour of patchbombs}
  58.392 +
  58.393 +Not every project has exactly the same conventions for sending changes
  58.394 +in email; the \hgext{patchbomb} extension tries to accommodate a
  58.395 +number of variations through command line options.
  58.396 +\begin{itemize}
  58.397 +\item You can write a subject for the introductory message on the
  58.398 +  command line using the \hgxopt{patchbomb}{email}{-s} option.  This
  58.399 +  takes one argument, the text of the subject to use.
  58.400 +\item To change the email address from which the messages originate,
  58.401 +  use the \hgxopt{patchbomb}{email}{-f} option.  This takes one
  58.402 +  argument, the email address to use.
  58.403 +\item The default behaviour is to send unified diffs (see
  58.404 +  section~\ref{sec:mq:patch} for a description of the format), one per
  58.405 +  message.  You can send a binary bundle instead with the
  58.406 +  \hgxopt{patchbomb}{email}{-b} option.  
  58.407 +\item Unified diffs are normally prefaced with a metadata header.  You
  58.408 +  can omit this, and send unadorned diffs, with the
  58.409 +  \hgxopt{patchbomb}{email}{--plain} option.
  58.410 +\item Diffs are normally sent ``inline'', in the same body part as the
  58.411 +  description of a patch.  This makes it easiest for the largest
  58.412 +  number of readers to quote and respond to parts of a diff, as some
  58.413 +  mail clients will only quote the first MIME body part in a message.
  58.414 +  If you'd prefer to send the description and the diff in separate
  58.415 +  body parts, use the \hgxopt{patchbomb}{email}{-a} option.
  58.416 +\item Instead of sending mail messages, you can write them to an
  58.417 +  \texttt{mbox}-format mail folder using the
  58.418 +  \hgxopt{patchbomb}{email}{-m} option.  That option takes one
  58.419 +  argument, the name of the file to write to.
  58.420 +\item If you would like to add a \command{diffstat}-format summary to
  58.421 +  each patch, and one to the introductory message, use the
  58.422 +  \hgxopt{patchbomb}{email}{-d} option.  The \command{diffstat}
  58.423 +  command displays a table containing the name of each file patched,
  58.424 +  the number of lines affected, and a histogram showing how much each
  58.425 +  file is modified.  This gives readers a qualitative glance at how
  58.426 +  complex a patch is.
  58.427 +\end{itemize}
  58.428 +
  58.429 +%%% Local Variables: 
  58.430 +%%% mode: latex
  58.431 +%%% TeX-master: "00book"
  58.432 +%%% End: 
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/fr/hook.tex	Thu Feb 05 12:37:03 2009 +0100
    59.3 @@ -0,0 +1,1413 @@
    59.4 +\chapter{Handling repository events with hooks}
    59.5 +\label{chap:hook}
    59.6 +
    59.7 +Mercurial offers a powerful mechanism to let you perform automated
    59.8 +actions in response to events that occur in a repository.  In some
    59.9 +cases, you can even control Mercurial's response to those events.
   59.10 +
   59.11 +The name Mercurial uses for one of these actions is a \emph{hook}.
   59.12 +Hooks are called ``triggers'' in some revision control systems, but
   59.13 +the two names refer to the same idea.
   59.14 +
   59.15 +\section{An overview of hooks in Mercurial}
   59.16 +
   59.17 +Here is a brief list of the hooks that Mercurial supports.  We will
   59.18 +revisit each of these hooks in more detail later, in
   59.19 +section~\ref{sec:hook:ref}.
   59.20 +
   59.21 +\begin{itemize}
   59.22 +\item[\small\hook{changegroup}] This is run after a group of
   59.23 +  changesets has been brought into the repository from elsewhere.
   59.24 +\item[\small\hook{commit}] This is run after a new changeset has been
   59.25 +  created in the local repository.
   59.26 +\item[\small\hook{incoming}] This is run once for each new changeset
   59.27 +  that is brought into the repository from elsewhere.  Notice the
   59.28 +  difference from \hook{changegroup}, which is run once per
   59.29 +  \emph{group} of changesets brought in.
   59.30 +\item[\small\hook{outgoing}] This is run after a group of changesets
   59.31 +  has been transmitted from this repository.
   59.32 +\item[\small\hook{prechangegroup}] This is run before starting to
   59.33 +  bring a group of changesets into the repository.
   59.34 +\item[\small\hook{precommit}] Controlling. This is run before starting
   59.35 +  a commit.
   59.36 +\item[\small\hook{preoutgoing}] Controlling. This is run before
   59.37 +  starting to transmit a group of changesets from this repository.
   59.38 +\item[\small\hook{pretag}] Controlling. This is run before creating a tag.
   59.39 +\item[\small\hook{pretxnchangegroup}] Controlling. This is run after a
   59.40 +  group of changesets has been brought into the local repository from
   59.41 +  another, but before the transaction completes that will make the
   59.42 +  changes permanent in the repository.
   59.43 +\item[\small\hook{pretxncommit}] Controlling. This is run after a new
   59.44 +  changeset has been created in the local repository, but before the
   59.45 +  transaction completes that will make it permanent.
   59.46 +\item[\small\hook{preupdate}] Controlling. This is run before starting
   59.47 +  an update or merge of the working directory.
   59.48 +\item[\small\hook{tag}] This is run after a tag is created.
   59.49 +\item[\small\hook{update}] This is run after an update or merge of the
   59.50 +  working directory has finished.
   59.51 +\end{itemize}
   59.52 +Each of the hooks whose description begins with the word
   59.53 +``Controlling'' has the ability to determine whether an activity can
   59.54 +proceed.  If the hook succeeds, the activity may proceed; if it fails,
   59.55 +the activity is either not permitted or undone, depending on the hook.
   59.56 +
   59.57 +\section{Hooks and security}
   59.58 +
   59.59 +\subsection{Hooks are run with your privileges}
   59.60 +
   59.61 +When you run a Mercurial command in a repository, and the command
   59.62 +causes a hook to run, that hook runs on \emph{your} system, under
   59.63 +\emph{your} user account, with \emph{your} privilege level.  Since
   59.64 +hooks are arbitrary pieces of executable code, you should treat them
   59.65 +with an appropriate level of suspicion.  Do not install a hook unless
   59.66 +you are confident that you know who created it and what it does.
   59.67 +
   59.68 +In some cases, you may be exposed to hooks that you did not install
   59.69 +yourself.  If you work with Mercurial on an unfamiliar system,
   59.70 +Mercurial will run hooks defined in that system's global \hgrc\ file.
   59.71 +
   59.72 +If you are working with a repository owned by another user, Mercurial
   59.73 +can run hooks defined in that user's repository, but it will still run
   59.74 +them as ``you''.  For example, if you \hgcmd{pull} from that
   59.75 +repository, and its \sfilename{.hg/hgrc} defines a local
   59.76 +\hook{outgoing} hook, that hook will run under your user account, even
   59.77 +though you don't own that repository.
   59.78 +
   59.79 +\begin{note}
   59.80 +  This only applies if you are pulling from a repository on a local or
   59.81 +  network filesystem.  If you're pulling over http or ssh, any
   59.82 +  \hook{outgoing} hook will run under whatever account is executing
   59.83 +  the server process, on the server.
   59.84 +\end{note}
   59.85 +
   59.86 +XXX To see what hooks are defined in a repository, use the
   59.87 +\hgcmdargs{config}{hooks} command.  If you are working in one
   59.88 +repository, but talking to another that you do not own (e.g.~using
   59.89 +\hgcmd{pull} or \hgcmd{incoming}), remember that it is the other
   59.90 +repository's hooks you should be checking, not your own.
   59.91 +
   59.92 +\subsection{Hooks do not propagate}
   59.93 +
   59.94 +In Mercurial, hooks are not revision controlled, and do not propagate
   59.95 +when you clone, or pull from, a repository.  The reason for this is
   59.96 +simple: a hook is a completely arbitrary piece of executable code.  It
   59.97 +runs under your user identity, with your privilege level, on your
   59.98 +machine.
   59.99 +
  59.100 +It would be extremely reckless for any distributed revision control
  59.101 +system to implement revision-controlled hooks, as this would offer an
  59.102 +easily exploitable way to subvert the accounts of users of the
  59.103 +revision control system.
  59.104 +
  59.105 +Since Mercurial does not propagate hooks, if you are collaborating
  59.106 +with other people on a common project, you should not assume that they
  59.107 +are using the same Mercurial hooks as you are, or that theirs are
  59.108 +correctly configured.  You should document the hooks you expect people
  59.109 +to use.
  59.110 +
  59.111 +In a corporate intranet, this is somewhat easier to control, as you
  59.112 +can for example provide a ``standard'' installation of Mercurial on an
  59.113 +NFS filesystem, and use a site-wide \hgrc\ file to define hooks that
  59.114 +all users will see.  However, this too has its limits; see below.
  59.115 +
  59.116 +\subsection{Hooks can be overridden}
  59.117 +
  59.118 +Mercurial allows you to override a hook definition by redefining the
  59.119 +hook.  You can disable it by setting its value to the empty string, or
  59.120 +change its behaviour as you wish.
  59.121 +
  59.122 +If you deploy a system-~or site-wide \hgrc\ file that defines some
  59.123 +hooks, you should thus understand that your users can disable or
  59.124 +override those hooks.
  59.125 +
  59.126 +\subsection{Ensuring that critical hooks are run}
  59.127 +
  59.128 +Sometimes you may want to enforce a policy that you do not want others
  59.129 +to be able to work around.  For example, you may have a requirement
  59.130 +that every changeset must pass a rigorous set of tests.  Defining this
  59.131 +requirement via a hook in a site-wide \hgrc\ won't work for remote
  59.132 +users on laptops, and of course local users can subvert it at will by
  59.133 +overriding the hook.
  59.134 +
  59.135 +Instead, you can set up your policies for use of Mercurial so that
  59.136 +people are expected to propagate changes through a well-known
  59.137 +``canonical'' server that you have locked down and configured
  59.138 +appropriately.
  59.139 +
  59.140 +One way to do this is via a combination of social engineering and
  59.141 +technology.  Set up a restricted-access account; users can push
  59.142 +changes over the network to repositories managed by this account, but
  59.143 +they cannot log into the account and run normal shell commands.  In
  59.144 +this scenario, a user can commit a changeset that contains any old
  59.145 +garbage they want.
  59.146 +
  59.147 +When someone pushes a changeset to the server that everyone pulls
  59.148 +from, the server will test the changeset before it accepts it as
  59.149 +permanent, and reject it if it fails to pass the test suite.  If
  59.150 +people only pull changes from this filtering server, it will serve to
  59.151 +ensure that all changes that people pull have been automatically
  59.152 +vetted.
  59.153 +
  59.154 +\section{Care with \texttt{pretxn} hooks in a shared-access repository}
  59.155 +
  59.156 +If you want to use hooks to do some automated work in a repository
  59.157 +that a number of people have shared access to, you need to be careful
  59.158 +in how you do this.
  59.159 +
  59.160 +Mercurial only locks a repository when it is writing to the
  59.161 +repository, and only the parts of Mercurial that write to the
  59.162 +repository pay attention to locks.  Write locks are necessary to
  59.163 +prevent multiple simultaneous writers from scribbling on each other's
  59.164 +work, corrupting the repository.
  59.165 +
  59.166 +Because Mercurial is careful with the order in which it reads and
  59.167 +writes data, it does not need to acquire a lock when it wants to read
  59.168 +data from the repository.  The parts of Mercurial that read from the
  59.169 +repository never pay attention to locks.  This lockless reading scheme
  59.170 +greatly increases performance and concurrency.
  59.171 +
  59.172 +With great performance comes a trade-off, though, one which has the
  59.173 +potential to cause you trouble unless you're aware of it.  To describe
  59.174 +this requires a little detail about how Mercurial adds changesets to a
  59.175 +repository and reads those changes.
  59.176 +
  59.177 +When Mercurial \emph{writes} metadata, it writes it straight into the
  59.178 +destination file.  It writes file data first, then manifest data
  59.179 +(which contains pointers to the new file data), then changelog data
  59.180 +(which contains pointers to the new manifest data).  Before the first
  59.181 +write to each file, it stores a record of where the end of the file
  59.182 +was in its transaction log.  If the transaction must be rolled back,
  59.183 +Mercurial simply truncates each file back to the size it was before the
  59.184 +transaction began.
  59.185 +
  59.186 +When Mercurial \emph{reads} metadata, it reads the changelog first,
  59.187 +then everything else.  Since a reader will only access parts of the
  59.188 +manifest or file metadata that it can see in the changelog, it can
  59.189 +never see partially written data.
  59.190 +
  59.191 +Some controlling hooks (\hook{pretxncommit} and
  59.192 +\hook{pretxnchangegroup}) run when a transaction is almost complete.
  59.193 +All of the metadata has been written, but Mercurial can still roll the
  59.194 +transaction back and cause the newly-written data to disappear.
  59.195 +
  59.196 +If one of these hooks runs for long, it opens a window of time during
  59.197 +which a reader can see the metadata for changesets that are not yet
  59.198 +permanent, and should not be thought of as ``really there''.  The
  59.199 +longer the hook runs, the longer that window is open.
  59.200 +
  59.201 +\subsection{The problem illustrated}
  59.202 +
  59.203 +In principle, a good use for the \hook{pretxnchangegroup} hook would
  59.204 +be to automatically build and test incoming changes before they are
  59.205 +accepted into a central repository.  This could let you guarantee that
  59.206 +nobody can push changes to this repository that ``break the build''.
  59.207 +But if a client can pull changes while they're being tested, the
  59.208 +usefulness of the test is zero; an unsuspecting someone can pull
  59.209 +untested changes, potentially breaking their build.
  59.210 +
  59.211 +The safest technological answer to this challenge is to set up such a
  59.212 +``gatekeeper'' repository as \emph{unidirectional}.  Let it take
  59.213 +changes pushed in from the outside, but do not allow anyone to pull
  59.214 +changes from it (use the \hook{preoutgoing} hook to lock it down).
  59.215 +Configure a \hook{changegroup} hook so that if a build or test
  59.216 +succeeds, the hook will push the new changes out to another repository
  59.217 +that people \emph{can} pull from.
  59.218 +
  59.219 +In practice, putting a centralised bottleneck like this in place is
  59.220 +not often a good idea, and transaction visibility has nothing to do
  59.221 +with the problem.  As the size of a project---and the time it takes to
  59.222 +build and test---grows, you rapidly run into a wall with this ``try
  59.223 +before you buy'' approach, where you have more changesets to test than
  59.224 +time in which to deal with them.  The inevitable result is frustration
  59.225 +on the part of all involved.
  59.226 +
  59.227 +An approach that scales better is to get people to build and test
  59.228 +before they push, then run automated builds and tests centrally
  59.229 +\emph{after} a push, to be sure all is well.  The advantage of this
  59.230 +approach is that it does not impose a limit on the rate at which the
  59.231 +repository can accept changes.
  59.232 +
  59.233 +\section{A short tutorial on using hooks}
  59.234 +\label{sec:hook:simple}
  59.235 +
  59.236 +It is easy to write a Mercurial hook.  Let's start with a hook that
  59.237 +runs when you finish a \hgcmd{commit}, and simply prints the hash of
  59.238 +the changeset you just created.  The hook is called \hook{commit}.
  59.239 +
  59.240 +\begin{figure}[ht]
  59.241 +  \interaction{hook.simple.init}
  59.242 +  \caption{A simple hook that runs when a changeset is committed}
  59.243 +  \label{ex:hook:init}
  59.244 +\end{figure}
  59.245 +
  59.246 +All hooks follow the pattern in example~\ref{ex:hook:init}.  You add
  59.247 +an entry to the \rcsection{hooks} section of your \hgrc.  On the left
  59.248 +is the name of the event to trigger on; on the right is the action to
  59.249 +take.  As you can see, you can run an arbitrary shell command in a
  59.250 +hook.  Mercurial passes extra information to the hook using
  59.251 +environment variables (look for \envar{HG\_NODE} in the example).
  59.252 +
  59.253 +\subsection{Performing multiple actions per event}
  59.254 +
  59.255 +Quite often, you will want to define more than one hook for a
  59.256 +particular kind of event, as shown in example~\ref{ex:hook:ext}.
  59.257 +Mercurial lets you do this by adding an \emph{extension} to the end of
  59.258 +a hook's name.  You extend a hook's name by giving the name of the
  59.259 +hook, followed by a full stop (the ``\texttt{.}'' character), followed
  59.260 +by some more text of your choosing.  For example, Mercurial will run
  59.261 +both \texttt{commit.foo} and \texttt{commit.bar} when the
  59.262 +\texttt{commit} event occurs.
  59.263 +
  59.264 +\begin{figure}[ht]
  59.265 +  \interaction{hook.simple.ext}
  59.266 +  \caption{Defining a second \hook{commit} hook}
  59.267 +  \label{ex:hook:ext}
  59.268 +\end{figure}
  59.269 +
  59.270 +To give a well-defined order of execution when there are multiple
  59.271 +hooks defined for an event, Mercurial sorts hooks by extension, and
  59.272 +executes the hook commands in this sorted order.  In the above
  59.273 +example, it will execute \texttt{commit.bar} before
  59.274 +\texttt{commit.foo}, and \texttt{commit} before both.
  59.275 +
  59.276 +It is a good idea to use a somewhat descriptive extension when you
  59.277 +define a new hook.  This will help you to remember what the hook was
  59.278 +for.  If the hook fails, you'll get an error message that contains the
  59.279 +hook name and extension, so using a descriptive extension could give
  59.280 +you an immediate hint as to why the hook failed (see
  59.281 +section~\ref{sec:hook:perm} for an example).
  59.282 +
  59.283 +\subsection{Controlling whether an activity can proceed}
  59.284 +\label{sec:hook:perm}
  59.285 +
  59.286 +In our earlier examples, we used the \hook{commit} hook, which is
  59.287 +run after a commit has completed.  This is one of several Mercurial
  59.288 +hooks that run after an activity finishes.  Such hooks have no way of
  59.289 +influencing the activity itself.
  59.290 +
  59.291 +Mercurial defines a number of events that occur before an activity
  59.292 +starts; or after it starts, but before it finishes.  Hooks that
  59.293 +trigger on these events have the added ability to choose whether the
  59.294 +activity can continue, or will abort.  
  59.295 +
  59.296 +The \hook{pretxncommit} hook runs after a commit has all but
  59.297 +completed.  In other words, the metadata representing the changeset
  59.298 +has been written out to disk, but the transaction has not yet been
  59.299 +allowed to complete.  The \hook{pretxncommit} hook has the ability to
  59.300 +decide whether the transaction can complete, or must be rolled back.
  59.301 +
  59.302 +If the \hook{pretxncommit} hook exits with a status code of zero, the
  59.303 +transaction is allowed to complete; the commit finishes; and the
  59.304 +\hook{commit} hook is run.  If the \hook{pretxncommit} hook exits with
  59.305 +a non-zero status code, the transaction is rolled back; the metadata
  59.306 +representing the changeset is erased; and the \hook{commit} hook is
  59.307 +not run.
  59.308 +
  59.309 +\begin{figure}[ht]
  59.310 +  \interaction{hook.simple.pretxncommit}
  59.311 +  \caption{Using the \hook{pretxncommit} hook to control commits}
  59.312 +  \label{ex:hook:pretxncommit}
  59.313 +\end{figure}
  59.314 +
  59.315 +The hook in example~\ref{ex:hook:pretxncommit} checks that a commit
  59.316 +comment contains a bug ID.  If it does, the commit can complete.  If
  59.317 +not, the commit is rolled back.
  59.318 +
  59.319 +\section{Writing your own hooks}
  59.320 +
  59.321 +When you are writing a hook, you might find it useful to run Mercurial
  59.322 +either with the \hggopt{-v} option, or the \rcitem{ui}{verbose} config
  59.323 +item set to ``true''.  When you do so, Mercurial will print a message
  59.324 +before it calls each hook.
  59.325 +
  59.326 +\subsection{Choosing how your hook should run}
  59.327 +\label{sec:hook:lang}
  59.328 +
  59.329 +You can write a hook either as a normal program---typically a shell
  59.330 +script---or as a Python function that is executed within the Mercurial
  59.331 +process.
  59.332 +
  59.333 +Writing a hook as an external program has the advantage that it
  59.334 +requires no knowledge of Mercurial's internals.  You can call normal
  59.335 +Mercurial commands to get any added information you need.  The
  59.336 +trade-off is that external hooks are slower than in-process hooks.
  59.337 +
  59.338 +An in-process Python hook has complete access to the Mercurial API,
  59.339 +and does not ``shell out'' to another process, so it is inherently
  59.340 +faster than an external hook.  It is also easier to obtain much of the
  59.341 +information that a hook requires by using the Mercurial API than by
  59.342 +running Mercurial commands.
  59.343 +
  59.344 +If you are comfortable with Python, or require high performance,
  59.345 +writing your hooks in Python may be a good choice.  However, when you
  59.346 +have a straightforward hook to write and you don't need to care about
  59.347 +performance (probably the majority of hooks), a shell script is
  59.348 +perfectly fine.
  59.349 +
  59.350 +\subsection{Hook parameters}
  59.351 +\label{sec:hook:param}
  59.352 +
  59.353 +Mercurial calls each hook with a set of well-defined parameters.  In
  59.354 +Python, a parameter is passed as a keyword argument to your hook
  59.355 +function.  For an external program, a parameter is passed as an
  59.356 +environment variable.
  59.357 +
  59.358 +Whether your hook is written in Python or as a shell script, the
  59.359 +hook-specific parameter names and values will be the same.  A boolean
  59.360 +parameter will be represented as a boolean value in Python, but as the
  59.361 +number 1 (for ``true'') or 0 (for ``false'') as an environment
  59.362 +variable for an external hook.  If a hook parameter is named
  59.363 +\texttt{foo}, the keyword argument for a Python hook will also be
  59.364 +named \texttt{foo}, while the environment variable for an external
  59.365 +hook will be named \texttt{HG\_FOO}.
  59.366 +
  59.367 +\subsection{Hook return values and activity control}
  59.368 +
  59.369 +A hook that executes successfully must exit with a status of zero if
  59.370 +external, or return boolean ``false'' if in-process.  Failure is
  59.371 +indicated with a non-zero exit status from an external hook, or an
  59.372 +in-process hook returning boolean ``true''.  If an in-process hook
  59.373 +raises an exception, the hook is considered to have failed.
  59.374 +
  59.375 +For a hook that controls whether an activity can proceed, zero/false
  59.376 +means ``allow'', while non-zero/true/exception means ``deny''.
  59.377 +
  59.378 +\subsection{Writing an external hook}
  59.379 +
  59.380 +When you define an external hook in your \hgrc\ and the hook is run,
  59.381 +its value is passed to your shell, which interprets it.  This means
  59.382 +that you can use normal shell constructs in the body of the hook.
  59.383 +
  59.384 +An executable hook is always run with its current directory set to a
  59.385 +repository's root directory.
  59.386 +
  59.387 +Each hook parameter is passed in as an environment variable; the name
  59.388 +is upper-cased, and prefixed with the string ``\texttt{HG\_}''.
  59.389 +
  59.390 +With the exception of hook parameters, Mercurial does not set or
  59.391 +modify any environment variables when running a hook.  This is useful
  59.392 +to remember if you are writing a site-wide hook that may be run by a
  59.393 +number of different users with differing environment variables set.
  59.394 +In multi-user situations, you should not rely on environment variables
  59.395 +being set to the values you have in your environment when testing the
  59.396 +hook.
  59.397 +
  59.398 +\subsection{Telling Mercurial to use an in-process hook}
  59.399 +
  59.400 +The \hgrc\ syntax for defining an in-process hook is slightly
  59.401 +different than for an executable hook.  The value of the hook must
  59.402 +start with the text ``\texttt{python:}'', and continue with the
  59.403 +fully-qualified name of a callable object to use as the hook's value.
  59.404 +
  59.405 +The module in which a hook lives is automatically imported when a hook
  59.406 +is run.  So long as you have the module name and \envar{PYTHONPATH}
  59.407 +right, it should ``just work''.
  59.408 +
  59.409 +The following \hgrc\ example snippet illustrates the syntax and
  59.410 +meaning of the notions we just described.
  59.411 +\begin{codesample2}
  59.412 +  [hooks]
  59.413 +  commit.example = python:mymodule.submodule.myhook
  59.414 +\end{codesample2}
  59.415 +When Mercurial runs the \texttt{commit.example} hook, it imports
  59.416 +\texttt{mymodule.submodule}, looks for the callable object named
  59.417 +\texttt{myhook}, and calls it.
  59.418 +
  59.419 +\subsection{Writing an in-process hook}
  59.420 +
  59.421 +The simplest in-process hook does nothing, but illustrates the basic
  59.422 +shape of the hook API:
  59.423 +\begin{codesample2}
  59.424 +  def myhook(ui, repo, **kwargs):
  59.425 +      pass
  59.426 +\end{codesample2}
  59.427 +The first argument to a Python hook is always a
  59.428 +\pymodclass{mercurial.ui}{ui} object.  The second is a repository object;
  59.429 +at the moment, it is always an instance of
  59.430 +\pymodclass{mercurial.localrepo}{localrepository}.  Following these two
  59.431 +arguments are other keyword arguments.  Which ones are passed in
  59.432 +depends on the hook being called, but a hook can ignore arguments it
  59.433 +doesn't care about by dropping them into a keyword argument dict, as
  59.434 +with \texttt{**kwargs} above.
  59.435 +
  59.436 +\section{Some hook examples}
  59.437 +
  59.438 +\subsection{Writing meaningful commit messages}
  59.439 +
  59.440 +It's hard to imagine a useful commit message being very short.  The
  59.441 +simple \hook{pretxncommit} hook of figure~\ref{ex:hook:msglen.go}
  59.442 +will prevent you from committing a changeset with a message that is
  59.443 +less than ten bytes long.
  59.444 +
  59.445 +\begin{figure}[ht]
  59.446 +  \interaction{hook.msglen.go}
  59.447 +  \caption{A hook that forbids overly short commit messages}
  59.448 +  \label{ex:hook:msglen.go}
  59.449 +\end{figure}
  59.450 +
  59.451 +\subsection{Checking for trailing whitespace}
  59.452 +
  59.453 +An interesting use of a commit-related hook is to help you to write
  59.454 +cleaner code.  A simple example of ``cleaner code'' is the dictum that
  59.455 +a change should not add any new lines of text that contain ``trailing
  59.456 +whitespace''.  Trailing whitespace is a series of space and tab
  59.457 +characters at the end of a line of text.  In most cases, trailing
  59.458 +whitespace is unnecessary, invisible noise, but it is occasionally
  59.459 +problematic, and people often prefer to get rid of it.
  59.460 +
  59.461 +You can use either the \hook{precommit} or \hook{pretxncommit} hook to
  59.462 +tell whether you have a trailing whitespace problem.  If you use the
  59.463 +\hook{precommit} hook, the hook will not know which files you are
  59.464 +committing, so it will have to check every modified file in the
  59.465 +repository for trailing white space.  If you want to commit a change
  59.466 +to just the file \filename{foo}, but the file \filename{bar} contains
  59.467 +trailing whitespace, doing a check in the \hook{precommit} hook will
  59.468 +prevent you from committing \filename{foo} due to the problem with
  59.469 +\filename{bar}.  This doesn't seem right.
  59.470 +
  59.471 +Should you choose the \hook{pretxncommit} hook, the check won't occur
  59.472 +until just before the transaction for the commit completes.  This will
  59.473 +allow you to check for problems only the exact files that are being
  59.474 +committed.  However, if you entered the commit message interactively
  59.475 +and the hook fails, the transaction will roll back; you'll have to
  59.476 +re-enter the commit message after you fix the trailing whitespace and
  59.477 +run \hgcmd{commit} again.
  59.478 +
  59.479 +\begin{figure}[ht]
  59.480 +  \interaction{hook.ws.simple}
  59.481 +  \caption{A simple hook that checks for trailing whitespace}
  59.482 +  \label{ex:hook:ws.simple}
  59.483 +\end{figure}
  59.484 +
  59.485 +Figure~\ref{ex:hook:ws.simple} introduces a simple \hook{pretxncommit}
  59.486 +hook that checks for trailing whitespace.  This hook is short, but not
  59.487 +very helpful.  It exits with an error status if a change adds a line
  59.488 +with trailing whitespace to any file, but does not print any
  59.489 +information that might help us to identify the offending file or
  59.490 +line.  It also has the nice property of not paying attention to
  59.491 +unmodified lines; only lines that introduce new trailing whitespace
  59.492 +cause problems.
  59.493 +
  59.494 +\begin{figure}[ht]
  59.495 +  \interaction{hook.ws.better}
  59.496 +  \caption{A better trailing whitespace hook}
  59.497 +  \label{ex:hook:ws.better}
  59.498 +\end{figure}
  59.499 +
  59.500 +The example of figure~\ref{ex:hook:ws.better} is much more complex,
  59.501 +but also more useful.  It parses a unified diff to see if any lines
  59.502 +add trailing whitespace, and prints the name of the file and the line
  59.503 +number of each such occurrence.  Even better, if the change adds
  59.504 +trailing whitespace, this hook saves the commit comment and prints the
  59.505 +name of the save file before exiting and telling Mercurial to roll the
  59.506 +transaction back, so you can use
  59.507 +\hgcmdargs{commit}{\hgopt{commit}{-l}~\emph{filename}} to reuse the
  59.508 +saved commit message once you've corrected the problem.
  59.509 +
  59.510 +As a final aside, note in figure~\ref{ex:hook:ws.better} the use of
  59.511 +\command{perl}'s in-place editing feature to get rid of trailing
  59.512 +whitespace from a file.  This is concise and useful enough that I will
  59.513 +reproduce it here.
  59.514 +\begin{codesample2}
  59.515 +  perl -pi -e 's,\textbackslash{}s+\$,,' filename
  59.516 +\end{codesample2}
  59.517 +
  59.518 +\section{Bundled hooks}
  59.519 +
  59.520 +Mercurial ships with several bundled hooks.  You can find them in the
  59.521 +\dirname{hgext} directory of a Mercurial source tree.  If you are
  59.522 +using a Mercurial binary package, the hooks will be located in the
  59.523 +\dirname{hgext} directory of wherever your package installer put
  59.524 +Mercurial.
  59.525 +
  59.526 +\subsection{\hgext{acl}---access control for parts of a repository}
  59.527 +
  59.528 +The \hgext{acl} extension lets you control which remote users are
  59.529 +allowed to push changesets to a networked server.  You can protect any
  59.530 +portion of a repository (including the entire repo), so that a
  59.531 +specific remote user can push changes that do not affect the protected
  59.532 +portion.
  59.533 +
  59.534 +This extension implements access control based on the identity of the
  59.535 +user performing a push, \emph{not} on who committed the changesets
  59.536 +they're pushing.  It makes sense to use this hook only if you have a
  59.537 +locked-down server environment that authenticates remote users, and
  59.538 +you want to be sure that only specific users are allowed to push
  59.539 +changes to that server.
  59.540 +
  59.541 +\subsubsection{Configuring the \hook{acl} hook}
  59.542 +
  59.543 +In order to manage incoming changesets, the \hgext{acl} hook must be
  59.544 +used as a \hook{pretxnchangegroup} hook.  This lets it see which files
  59.545 +are modified by each incoming changeset, and roll back a group of
  59.546 +changesets if they modify ``forbidden'' files.  Example:
  59.547 +\begin{codesample2}
  59.548 +  [hooks]
  59.549 +  pretxnchangegroup.acl = python:hgext.acl.hook
  59.550 +\end{codesample2}
  59.551 +
  59.552 +The \hgext{acl} extension is configured using three sections.  
  59.553 +
  59.554 +The \rcsection{acl} section has only one entry, \rcitem{acl}{sources},
  59.555 +which lists the sources of incoming changesets that the hook should
  59.556 +pay attention to.  You don't normally need to configure this section.
  59.557 +\begin{itemize}
  59.558 +\item[\rcitem{acl}{serve}] Control incoming changesets that are arriving
  59.559 +  from a remote repository over http or ssh.  This is the default
  59.560 +  value of \rcitem{acl}{sources}, and usually the only setting you'll
  59.561 +  need for this configuration item.
  59.562 +\item[\rcitem{acl}{pull}] Control incoming changesets that are
  59.563 +  arriving via a pull from a local repository.
  59.564 +\item[\rcitem{acl}{push}] Control incoming changesets that are
  59.565 +  arriving via a push from a local repository.
  59.566 +\item[\rcitem{acl}{bundle}] Control incoming changesets that are
  59.567 +  arriving from another repository via a bundle.
  59.568 +\end{itemize}
  59.569 +
  59.570 +The \rcsection{acl.allow} section controls the users that are allowed to
  59.571 +add changesets to the repository.  If this section is not present, all
  59.572 +users that are not explicitly denied are allowed.  If this section is
  59.573 +present, all users that are not explicitly allowed are denied (so an
  59.574 +empty section means that all users are denied).
  59.575 +
  59.576 +The \rcsection{acl.deny} section determines which users are denied
  59.577 +from adding changesets to the repository.  If this section is not
  59.578 +present or is empty, no users are denied.
  59.579 +
  59.580 +The syntaxes for the \rcsection{acl.allow} and \rcsection{acl.deny}
  59.581 +sections are identical.  On the left of each entry is a glob pattern
  59.582 +that matches files or directories, relative to the root of the
  59.583 +repository; on the right, a user name.
  59.584 +
  59.585 +In the following example, the user \texttt{docwriter} can only push
  59.586 +changes to the \dirname{docs} subtree of the repository, while
  59.587 +\texttt{intern} can push changes to any file or directory except
  59.588 +\dirname{source/sensitive}.
  59.589 +\begin{codesample2}
  59.590 +  [acl.allow]
  59.591 +  docs/** = docwriter
  59.592 +
  59.593 +  [acl.deny]
  59.594 +  source/sensitive/** = intern
  59.595 +\end{codesample2}
  59.596 +
  59.597 +\subsubsection{Testing and troubleshooting}
  59.598 +
  59.599 +If you want to test the \hgext{acl} hook, run it with Mercurial's
  59.600 +debugging output enabled.  Since you'll probably be running it on a
  59.601 +server where it's not convenient (or sometimes possible) to pass in
  59.602 +the \hggopt{--debug} option, don't forget that you can enable
  59.603 +debugging output in your \hgrc:
  59.604 +\begin{codesample2}
  59.605 +  [ui]
  59.606 +  debug = true
  59.607 +\end{codesample2}
  59.608 +With this enabled, the \hgext{acl} hook will print enough information
  59.609 +to let you figure out why it is allowing or forbidding pushes from
  59.610 +specific users.
  59.611 +
  59.612 +\subsection{\hgext{bugzilla}---integration with Bugzilla}
  59.613 +
  59.614 +The \hgext{bugzilla} extension adds a comment to a Bugzilla bug
  59.615 +whenever it finds a reference to that bug ID in a commit comment.  You
  59.616 +can install this hook on a shared server, so that any time a remote
  59.617 +user pushes changes to this server, the hook gets run.  
  59.618 +
  59.619 +It adds a comment to the bug that looks like this (you can configure
  59.620 +the contents of the comment---see below):
  59.621 +\begin{codesample2}
  59.622 +  Changeset aad8b264143a, made by Joe User <joe.user@domain.com> in
  59.623 +  the frobnitz repository, refers to this bug.
  59.624 +
  59.625 +  For complete details, see
  59.626 +  http://hg.domain.com/frobnitz?cmd=changeset;node=aad8b264143a
  59.627 +
  59.628 +  Changeset description:
  59.629 +        Fix bug 10483 by guarding against some NULL pointers
  59.630 +\end{codesample2}
  59.631 +The value of this hook is that it automates the process of updating a
  59.632 +bug any time a changeset refers to it.  If you configure the hook
  59.633 +properly, it makes it easy for people to browse straight from a
  59.634 +Bugzilla bug to a changeset that refers to that bug.
  59.635 +
  59.636 +You can use the code in this hook as a starting point for some more
  59.637 +exotic Bugzilla integration recipes.  Here are a few possibilities:
  59.638 +\begin{itemize}
  59.639 +\item Require that every changeset pushed to the server have a valid
  59.640 +  bug~ID in its commit comment.  In this case, you'd want to configure
  59.641 +  the hook as a \hook{pretxncommit} hook.  This would allow the hook
  59.642 +  to reject changes that didn't contain bug IDs.
  59.643 +\item Allow incoming changesets to automatically modify the
  59.644 +  \emph{state} of a bug, as well as simply adding a comment.  For
  59.645 +  example, the hook could recognise the string ``fixed bug 31337'' as
  59.646 +  indicating that it should update the state of bug 31337 to
  59.647 +  ``requires testing''.
  59.648 +\end{itemize}
  59.649 +
  59.650 +\subsubsection{Configuring the \hook{bugzilla} hook}
  59.651 +\label{sec:hook:bugzilla:config}
  59.652 +
  59.653 +You should configure this hook in your server's \hgrc\ as an
  59.654 +\hook{incoming} hook, for example as follows:
  59.655 +\begin{codesample2}
  59.656 +  [hooks]
  59.657 +  incoming.bugzilla = python:hgext.bugzilla.hook
  59.658 +\end{codesample2}
  59.659 +
  59.660 +Because of the specialised nature of this hook, and because Bugzilla
  59.661 +was not written with this kind of integration in mind, configuring
  59.662 +this hook is a somewhat involved process.
  59.663 +
  59.664 +Before you begin, you must install the MySQL bindings for Python on
  59.665 +the host(s) where you'll be running the hook.  If this is not
  59.666 +available as a binary package for your system, you can download it
  59.667 +from~\cite{web:mysql-python}.
  59.668 +
  59.669 +Configuration information for this hook lives in the
  59.670 +\rcsection{bugzilla} section of your \hgrc.
  59.671 +\begin{itemize}
  59.672 +\item[\rcitem{bugzilla}{version}] The version of Bugzilla installed on
  59.673 +  the server.  The database schema that Bugzilla uses changes
  59.674 +  occasionally, so this hook has to know exactly which schema to use.
  59.675 +  At the moment, the only version supported is \texttt{2.16}.
  59.676 +\item[\rcitem{bugzilla}{host}] The hostname of the MySQL server that
  59.677 +  stores your Bugzilla data.  The database must be configured to allow
  59.678 +  connections from whatever host you are running the \hook{bugzilla}
  59.679 +  hook on.
  59.680 +\item[\rcitem{bugzilla}{user}] The username with which to connect to
  59.681 +  the MySQL server.  The database must be configured to allow this
  59.682 +  user to connect from whatever host you are running the
  59.683 +  \hook{bugzilla} hook on.  This user must be able to access and
  59.684 +  modify Bugzilla tables.  The default value of this item is
  59.685 +  \texttt{bugs}, which is the standard name of the Bugzilla user in a
  59.686 +  MySQL database.
  59.687 +\item[\rcitem{bugzilla}{password}] The MySQL password for the user you
  59.688 +  configured above.  This is stored as plain text, so you should make
  59.689 +  sure that unauthorised users cannot read the \hgrc\ file where you
  59.690 +  store this information.
  59.691 +\item[\rcitem{bugzilla}{db}] The name of the Bugzilla database on the
  59.692 +  MySQL server.  The default value of this item is \texttt{bugs},
  59.693 +  which is the standard name of the MySQL database where Bugzilla
  59.694 +  stores its data.
  59.695 +\item[\rcitem{bugzilla}{notify}] If you want Bugzilla to send out a
  59.696 +  notification email to subscribers after this hook has added a
  59.697 +  comment to a bug, you will need this hook to run a command whenever
  59.698 +  it updates the database.  The command to run depends on where you
  59.699 +  have installed Bugzilla, but it will typically look something like
  59.700 +  this, if you have Bugzilla installed in
  59.701 +  \dirname{/var/www/html/bugzilla}:
  59.702 +  \begin{codesample4}
  59.703 +    cd /var/www/html/bugzilla && ./processmail %s nobody@nowhere.com
  59.704 +  \end{codesample4}
  59.705 +  The Bugzilla \texttt{processmail} program expects to be given a
  59.706 +  bug~ID (the hook replaces ``\texttt{\%s}'' with the bug~ID) and an
  59.707 +  email address.  It also expects to be able to write to some files in
  59.708 +  the directory that it runs in.  If Bugzilla and this hook are not
  59.709 +  installed on the same machine, you will need to find a way to run
  59.710 +  \texttt{processmail} on the server where Bugzilla is installed.
  59.711 +\end{itemize}
  59.712 +
  59.713 +\subsubsection{Mapping committer names to Bugzilla user names}
  59.714 +
  59.715 +By default, the \hgext{bugzilla} hook tries to use the email address
  59.716 +of a changeset's committer as the Bugzilla user name with which to
  59.717 +update a bug.  If this does not suit your needs, you can map committer
  59.718 +email addresses to Bugzilla user names using a \rcsection{usermap}
  59.719 +section.
  59.720 +
  59.721 +Each item in the \rcsection{usermap} section contains an email address
  59.722 +on the left, and a Bugzilla user name on the right.
  59.723 +\begin{codesample2}
  59.724 +  [usermap]
  59.725 +  jane.user@example.com = jane
  59.726 +\end{codesample2}
  59.727 +You can either keep the \rcsection{usermap} data in a normal \hgrc, or
  59.728 +tell the \hgext{bugzilla} hook to read the information from an
  59.729 +external \filename{usermap} file.  In the latter case, you can store
  59.730 +\filename{usermap} data by itself in (for example) a user-modifiable
  59.731 +repository.  This makes it possible to let your users maintain their
  59.732 +own \rcitem{bugzilla}{usermap} entries.  The main \hgrc\ file might
  59.733 +look like this:
  59.734 +\begin{codesample2}
  59.735 +  # regular hgrc file refers to external usermap file
  59.736 +  [bugzilla]
  59.737 +  usermap = /home/hg/repos/userdata/bugzilla-usermap.conf
  59.738 +\end{codesample2}
  59.739 +While the \filename{usermap} file that it refers to might look like
  59.740 +this:
  59.741 +\begin{codesample2}
  59.742 +  # bugzilla-usermap.conf - inside a hg repository
  59.743 +  [usermap]
  59.744 +  stephanie@example.com = steph
  59.745 +\end{codesample2}
  59.746 +
  59.747 +\subsubsection{Configuring the text that gets added to a bug}
  59.748 +
  59.749 +You can configure the text that this hook adds as a comment; you
  59.750 +specify it in the form of a Mercurial template.  Several \hgrc\
  59.751 +entries (still in the \rcsection{bugzilla} section) control this
  59.752 +behaviour.
  59.753 +\begin{itemize}
  59.754 +\item[\texttt{strip}] The number of leading path elements to strip
  59.755 +  from a repository's path name to construct a partial path for a URL.
  59.756 +  For example, if the repositories on your server live under
  59.757 +  \dirname{/home/hg/repos}, and you have a repository whose path is
  59.758 +  \dirname{/home/hg/repos/app/tests}, then setting \texttt{strip} to
  59.759 +  \texttt{4} will give a partial path of \dirname{app/tests}.  The
  59.760 +  hook will make this partial path available when expanding a
  59.761 +  template, as \texttt{webroot}.
  59.762 +\item[\texttt{template}] The text of the template to use.  In addition
  59.763 +  to the usual changeset-related variables, this template can use
  59.764 +  \texttt{hgweb} (the value of the \texttt{hgweb} configuration item
  59.765 +  above) and \texttt{webroot} (the path constructed using
  59.766 +  \texttt{strip} above).
  59.767 +\end{itemize}
  59.768 +
  59.769 +In addition, you can add a \rcitem{web}{baseurl} item to the
  59.770 +\rcsection{web} section of your \hgrc.  The \hgext{bugzilla} hook will
  59.771 +make this available when expanding a template, as the base string to
  59.772 +use when constructing a URL that will let users browse from a Bugzilla
  59.773 +comment to view a changeset.  Example:
  59.774 +\begin{codesample2}
  59.775 +  [web]
  59.776 +  baseurl = http://hg.domain.com/
  59.777 +\end{codesample2}
  59.778 +
  59.779 +Here is an example set of \hgext{bugzilla} hook config information.
  59.780 +\begin{codesample2}
  59.781 +  [bugzilla]
  59.782 +  host = bugzilla.example.com
  59.783 +  password = mypassword
  59.784 +  version = 2.16
  59.785 +  # server-side repos live in /home/hg/repos, so strip 4 leading
  59.786 +  # separators
  59.787 +  strip = 4
  59.788 +  hgweb = http://hg.example.com/
  59.789 +  usermap = /home/hg/repos/notify/bugzilla.conf
  59.790 +  template = Changeset \{node|short\}, made by \{author\} in the \{webroot\}
  59.791 +    repo, refers to this bug.\\nFor complete details, see 
  59.792 +    \{hgweb\}\{webroot\}?cmd=changeset;node=\{node|short\}\\nChangeset
  59.793 +    description:\\n\\t\{desc|tabindent\}
  59.794 +\end{codesample2}
  59.795 +
  59.796 +\subsubsection{Testing and troubleshooting}
  59.797 +
  59.798 +The most common problems with configuring the \hgext{bugzilla} hook
  59.799 +relate to running Bugzilla's \filename{processmail} script and mapping
  59.800 +committer names to user names.
  59.801 +
  59.802 +Recall from section~\ref{sec:hook:bugzilla:config} above that the user
  59.803 +that runs the Mercurial process on the server is also the one that
  59.804 +will run the \filename{processmail} script.  The
  59.805 +\filename{processmail} script sometimes causes Bugzilla to write to
  59.806 +files in its configuration directory, and Bugzilla's configuration
  59.807 +files are usually owned by the user that your web server runs under.
  59.808 +
  59.809 +You can cause \filename{processmail} to be run with the suitable
  59.810 +user's identity using the \command{sudo} command.  Here is an example
  59.811 +entry for a \filename{sudoers} file.
  59.812 +\begin{codesample2}
  59.813 +  hg_user = (httpd_user) NOPASSWD: /var/www/html/bugzilla/processmail-wrapper %s
  59.814 +\end{codesample2}
  59.815 +This allows the \texttt{hg\_user} user to run a
  59.816 +\filename{processmail-wrapper} program under the identity of
  59.817 +\texttt{httpd\_user}.
  59.818 +
  59.819 +This indirection through a wrapper script is necessary, because
  59.820 +\filename{processmail} expects to be run with its current directory
  59.821 +set to wherever you installed Bugzilla; you can't specify that kind of
  59.822 +constraint in a \filename{sudoers} file.  The contents of the wrapper
  59.823 +script are simple:
  59.824 +\begin{codesample2}
  59.825 +  #!/bin/sh
  59.826 +  cd `dirname $0` && ./processmail "$1" nobody@example.com
  59.827 +\end{codesample2}
  59.828 +It doesn't seem to matter what email address you pass to
  59.829 +\filename{processmail}.
  59.830 +
  59.831 +If your \rcsection{usermap} is not set up correctly, users will see an
  59.832 +error message from the \hgext{bugzilla} hook when they push changes
  59.833 +to the server.  The error message will look like this:
  59.834 +\begin{codesample2}
  59.835 +  cannot find bugzilla user id for john.q.public@example.com
  59.836 +\end{codesample2}
  59.837 +What this means is that the committer's address,
  59.838 +\texttt{john.q.public@example.com}, is not a valid Bugzilla user name,
  59.839 +nor does it have an entry in your \rcsection{usermap} that maps it to
  59.840 +a valid Bugzilla user name.
  59.841 +
  59.842 +\subsection{\hgext{notify}---send email notifications}
  59.843 +
  59.844 +Although Mercurial's built-in web server provides RSS feeds of changes
  59.845 +in every repository, many people prefer to receive change
  59.846 +notifications via email.  The \hgext{notify} hook lets you send out
  59.847 +notifications to a set of email addresses whenever changesets arrive
  59.848 +that those subscribers are interested in.
  59.849 +
  59.850 +As with the \hgext{bugzilla} hook, the \hgext{notify} hook is
  59.851 +template-driven, so you can customise the contents of the notification
  59.852 +messages that it sends.
  59.853 +
  59.854 +By default, the \hgext{notify} hook includes a diff of every changeset
  59.855 +that it sends out; you can limit the size of the diff, or turn this
  59.856 +feature off entirely.  It is useful for letting subscribers review
  59.857 +changes immediately, rather than clicking to follow a URL.
  59.858 +
  59.859 +\subsubsection{Configuring the \hgext{notify} hook}
  59.860 +
  59.861 +You can set up the \hgext{notify} hook to send one email message per
  59.862 +incoming changeset, or one per incoming group of changesets (all those
  59.863 +that arrived in a single pull or push).
  59.864 +\begin{codesample2}
  59.865 +  [hooks]
  59.866 +  # send one email per group of changes
  59.867 +  changegroup.notify = python:hgext.notify.hook
  59.868 +  # send one email per change
  59.869 +  incoming.notify = python:hgext.notify.hook
  59.870 +\end{codesample2}
  59.871 +
  59.872 +Configuration information for this hook lives in the
  59.873 +\rcsection{notify} section of a \hgrc\ file.
  59.874 +\begin{itemize}
  59.875 +\item[\rcitem{notify}{test}] By default, this hook does not send out
  59.876 +  email at all; instead, it prints the message that it \emph{would}
  59.877 +  send.  Set this item to \texttt{false} to allow email to be sent.
  59.878 +  The reason that sending of email is turned off by default is that it
  59.879 +  takes several tries to configure this extension exactly as you would
  59.880 +  like, and it would be bad form to spam subscribers with a number of
  59.881 +  ``broken'' notifications while you debug your configuration.
  59.882 +\item[\rcitem{notify}{config}] The path to a configuration file that
  59.883 +  contains subscription information.  This is kept separate from the
  59.884 +  main \hgrc\ so that you can maintain it in a repository of its own.
  59.885 +  People can then clone that repository, update their subscriptions,
  59.886 +  and push the changes back to your server.
  59.887 +\item[\rcitem{notify}{strip}] The number of leading path separator
  59.888 +  characters to strip from a repository's path, when deciding whether
  59.889 +  a repository has subscribers.  For example, if the repositories on
  59.890 +  your server live in \dirname{/home/hg/repos}, and \hgext{notify} is
  59.891 +  considering a repository named \dirname{/home/hg/repos/shared/test},
  59.892 +  setting \rcitem{notify}{strip} to \texttt{4} will cause
  59.893 +  \hgext{notify} to trim the path it considers down to
  59.894 +  \dirname{shared/test}, and it will match subscribers against that.
  59.895 +\item[\rcitem{notify}{template}] The template text to use when sending
  59.896 +  messages.  This specifies both the contents of the message header
  59.897 +  and its body.
  59.898 +\item[\rcitem{notify}{maxdiff}] The maximum number of lines of diff
  59.899 +  data to append to the end of a message.  If a diff is longer than
  59.900 +  this, it is truncated.  By default, this is set to 300.  Set this to
  59.901 +  \texttt{0} to omit diffs from notification emails.
  59.902 +\item[\rcitem{notify}{sources}] A list of sources of changesets to
  59.903 +  consider.  This lets you limit \hgext{notify} to only sending out
  59.904 +  email about changes that remote users pushed into this repository
  59.905 +  via a server, for example.  See section~\ref{sec:hook:sources} for
  59.906 +  the sources you can specify here.
  59.907 +\end{itemize}
  59.908 +
  59.909 +If you set the \rcitem{web}{baseurl} item in the \rcsection{web}
  59.910 +section, you can use it in a template; it will be available as
  59.911 +\texttt{webroot}.
  59.912 +
  59.913 +Here is an example set of \hgext{notify} configuration information.
  59.914 +\begin{codesample2}
  59.915 +  [notify]
  59.916 +  # really send email
  59.917 +  test = false
  59.918 +  # subscriber data lives in the notify repo
  59.919 +  config = /home/hg/repos/notify/notify.conf
  59.920 +  # repos live in /home/hg/repos on server, so strip 4 "/" chars
  59.921 +  strip = 4
  59.922 +  template = X-Hg-Repo: \{webroot\}
  59.923 +    Subject: \{webroot\}: \{desc|firstline|strip\}
  59.924 +    From: \{author\}
  59.925 +
  59.926 +    changeset \{node|short\} in \{root\}
  59.927 +    details: \{baseurl\}\{webroot\}?cmd=changeset;node=\{node|short\}
  59.928 +    description:
  59.929 +      \{desc|tabindent|strip\}
  59.930 +
  59.931 +  [web]
  59.932 +  baseurl = http://hg.example.com/
  59.933 +\end{codesample2}
  59.934 +
  59.935 +This will produce a message that looks like the following:
  59.936 +\begin{codesample2}
  59.937 +  X-Hg-Repo: tests/slave
  59.938 +  Subject: tests/slave: Handle error case when slave has no buffers
  59.939 +  Date: Wed,  2 Aug 2006 15:25:46 -0700 (PDT)
  59.940 +
  59.941 +  changeset 3cba9bfe74b5 in /home/hg/repos/tests/slave
  59.942 +  details: http://hg.example.com/tests/slave?cmd=changeset;node=3cba9bfe74b5
  59.943 +  description:
  59.944 +          Handle error case when slave has no buffers
  59.945 +  diffs (54 lines):
  59.946 +
  59.947 +  diff -r 9d95df7cf2ad -r 3cba9bfe74b5 include/tests.h
  59.948 +  --- a/include/tests.h      Wed Aug 02 15:19:52 2006 -0700
  59.949 +  +++ b/include/tests.h      Wed Aug 02 15:25:26 2006 -0700
  59.950 +  @@ -212,6 +212,15 @@ static __inline__ void test_headers(void *h)
  59.951 +  [...snip...]
  59.952 +\end{codesample2}
  59.953 +
  59.954 +\subsubsection{Testing and troubleshooting}
  59.955 +
  59.956 +Do not forget that by default, the \hgext{notify} extension \emph{will
  59.957 +  not send any mail} until you explicitly configure it to do so, by
  59.958 +setting \rcitem{notify}{test} to \texttt{false}.  Until you do that,
  59.959 +it simply prints the message it \emph{would} send.
  59.960 +
  59.961 +\section{Information for writers of hooks}
  59.962 +\label{sec:hook:ref}
  59.963 +
  59.964 +\subsection{In-process hook execution}
  59.965 +
  59.966 +An in-process hook is called with arguments of the following form:
  59.967 +\begin{codesample2}
  59.968 +  def myhook(ui, repo, **kwargs):
  59.969 +      pass
  59.970 +\end{codesample2}
  59.971 +The \texttt{ui} parameter is a \pymodclass{mercurial.ui}{ui} object.
  59.972 +The \texttt{repo} parameter is a
  59.973 +\pymodclass{mercurial.localrepo}{localrepository} object.  The
  59.974 +names and values of the \texttt{**kwargs} parameters depend on the
  59.975 +hook being invoked, with the following common features:
  59.976 +\begin{itemize}
  59.977 +\item If a parameter is named \texttt{node} or
  59.978 +  \texttt{parent\emph{N}}, it will contain a hexadecimal changeset ID.
  59.979 +  The empty string is used to represent ``null changeset ID'' instead
  59.980 +  of a string of zeroes.
  59.981 +\item If a parameter is named \texttt{url}, it will contain the URL of
  59.982 +  a remote repository, if that can be determined.
  59.983 +\item Boolean-valued parameters are represented as Python
  59.984 +  \texttt{bool} objects.
  59.985 +\end{itemize}
  59.986 +
  59.987 +An in-process hook is called without a change to the process's working
  59.988 +directory (unlike external hooks, which are run in the root of the
  59.989 +repository).  It must not change the process's working directory, or
  59.990 +it will cause any calls it makes into the Mercurial API to fail.
  59.991 +
  59.992 +If a hook returns a boolean ``false'' value, it is considered to have
  59.993 +succeeded.  If it returns a boolean ``true'' value or raises an
  59.994 +exception, it is considered to have failed.  A useful way to think of
  59.995 +the calling convention is ``tell me if you fail''.
  59.996 +
  59.997 +Note that changeset IDs are passed into Python hooks as hexadecimal
  59.998 +strings, not the binary hashes that Mercurial's APIs normally use.  To
  59.999 +convert a hash from hex to binary, use the
 59.1000 +\pymodfunc{mercurial.node}{bin} function.
 59.1001 +
 59.1002 +\subsection{External hook execution}
 59.1003 +
 59.1004 +An external hook is passed to the shell of the user running Mercurial.
 59.1005 +Features of that shell, such as variable substitution and command
 59.1006 +redirection, are available.  The hook is run in the root directory of
 59.1007 +the repository (unlike in-process hooks, which are run in the same
 59.1008 +directory that Mercurial was run in).
 59.1009 +
 59.1010 +Hook parameters are passed to the hook as environment variables.  Each
 59.1011 +environment variable's name is converted in upper case and prefixed
 59.1012 +with the string ``\texttt{HG\_}''.  For example, if the name of a
 59.1013 +parameter is ``\texttt{node}'', the name of the environment variable
 59.1014 +representing that parameter will be ``\texttt{HG\_NODE}''.
 59.1015 +
 59.1016 +A boolean parameter is represented as the string ``\texttt{1}'' for
 59.1017 +``true'', ``\texttt{0}'' for ``false''.  If an environment variable is
 59.1018 +named \envar{HG\_NODE}, \envar{HG\_PARENT1} or \envar{HG\_PARENT2}, it
 59.1019 +contains a changeset ID represented as a hexadecimal string.  The
 59.1020 +empty string is used to represent ``null changeset ID'' instead of a
 59.1021 +string of zeroes.  If an environment variable is named
 59.1022 +\envar{HG\_URL}, it will contain the URL of a remote repository, if
 59.1023 +that can be determined.
 59.1024 +
 59.1025 +If a hook exits with a status of zero, it is considered to have
 59.1026 +succeeded.  If it exits with a non-zero status, it is considered to
 59.1027 +have failed.
 59.1028 +
 59.1029 +\subsection{Finding out where changesets come from}
 59.1030 +
 59.1031 +A hook that involves the transfer of changesets between a local
 59.1032 +repository and another may be able to find out information about the
 59.1033 +``far side''.  Mercurial knows \emph{how} changes are being
 59.1034 +transferred, and in many cases \emph{where} they are being transferred
 59.1035 +to or from.
 59.1036 +
 59.1037 +\subsubsection{Sources of changesets}
 59.1038 +\label{sec:hook:sources}
 59.1039 +
 59.1040 +Mercurial will tell a hook what means are, or were, used to transfer
 59.1041 +changesets between repositories.  This is provided by Mercurial in a
 59.1042 +Python parameter named \texttt{source}, or an environment variable named
 59.1043 +\envar{HG\_SOURCE}.
 59.1044 +
 59.1045 +\begin{itemize}
 59.1046 +\item[\texttt{serve}] Changesets are transferred to or from a remote
 59.1047 +  repository over http or ssh.
 59.1048 +\item[\texttt{pull}] Changesets are being transferred via a pull from
 59.1049 +  one repository into another.
 59.1050 +\item[\texttt{push}] Changesets are being transferred via a push from
 59.1051 +  one repository into another.
 59.1052 +\item[\texttt{bundle}] Changesets are being transferred to or from a
 59.1053 +  bundle.
 59.1054 +\end{itemize}
 59.1055 +
 59.1056 +\subsubsection{Where changes are going---remote repository URLs}
 59.1057 +\label{sec:hook:url}
 59.1058 +
 59.1059 +When possible, Mercurial will tell a hook the location of the ``far
 59.1060 +side'' of an activity that transfers changeset data between
 59.1061 +repositories.  This is provided by Mercurial in a Python parameter
 59.1062 +named \texttt{url}, or an environment variable named \envar{HG\_URL}.
 59.1063 +
 59.1064 +This information is not always known.  If a hook is invoked in a
 59.1065 +repository that is being served via http or ssh, Mercurial cannot tell
 59.1066 +where the remote repository is, but it may know where the client is
 59.1067 +connecting from.  In such cases, the URL will take one of the
 59.1068 +following forms:
 59.1069 +\begin{itemize}
 59.1070 +\item \texttt{remote:ssh:\emph{ip-address}}---remote ssh client, at
 59.1071 +  the given IP address.
 59.1072 +\item \texttt{remote:http:\emph{ip-address}}---remote http client, at
 59.1073 +  the given IP address.  If the client is using SSL, this will be of
 59.1074 +  the form \texttt{remote:https:\emph{ip-address}}.
 59.1075 +\item Empty---no information could be discovered about the remote
 59.1076 +  client.
 59.1077 +\end{itemize}
 59.1078 +
 59.1079 +\section{Hook reference}
 59.1080 +
 59.1081 +\subsection{\hook{changegroup}---after remote changesets added}
 59.1082 +\label{sec:hook:changegroup}
 59.1083 +
 59.1084 +This hook is run after a group of pre-existing changesets has been
 59.1085 +added to the repository, for example via a \hgcmd{pull} or
 59.1086 +\hgcmd{unbundle}.  This hook is run once per operation that added one
 59.1087 +or more changesets.  This is in contrast to the \hook{incoming} hook,
 59.1088 +which is run once per changeset, regardless of whether the changesets
 59.1089 +arrive in a group.
 59.1090 +
 59.1091 +Some possible uses for this hook include kicking off an automated
 59.1092 +build or test of the added changesets, updating a bug database, or
 59.1093 +notifying subscribers that a repository contains new changes.
 59.1094 +
 59.1095 +Parameters to this hook:
 59.1096 +\begin{itemize}
 59.1097 +\item[\texttt{node}] A changeset ID.  The changeset ID of the first
 59.1098 +  changeset in the group that was added.  All changesets between this
 59.1099 +  and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by
 59.1100 +  a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}.
 59.1101 +\item[\texttt{source}] A string.  The source of these changes.  See
 59.1102 +  section~\ref{sec:hook:sources} for details.
 59.1103 +\item[\texttt{url}] A URL.  The location of the remote repository, if
 59.1104 +  known.  See section~\ref{sec:hook:url} for more information.
 59.1105 +\end{itemize}
 59.1106 +
 59.1107 +See also: \hook{incoming} (section~\ref{sec:hook:incoming}),
 59.1108 +\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}),
 59.1109 +\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup})
 59.1110 +
 59.1111 +\subsection{\hook{commit}---after a new changeset is created}
 59.1112 +\label{sec:hook:commit}
 59.1113 +
 59.1114 +This hook is run after a new changeset has been created.
 59.1115 +
 59.1116 +Parameters to this hook:
 59.1117 +\begin{itemize}
 59.1118 +\item[\texttt{node}] A changeset ID.  The changeset ID of the newly
 59.1119 +  committed changeset.
 59.1120 +\item[\texttt{parent1}] A changeset ID.  The changeset ID of the first
 59.1121 +  parent of the newly committed changeset.
 59.1122 +\item[\texttt{parent2}] A changeset ID.  The changeset ID of the second
 59.1123 +  parent of the newly committed changeset.
 59.1124 +\end{itemize}
 59.1125 +
 59.1126 +See also: \hook{precommit} (section~\ref{sec:hook:precommit}),
 59.1127 +\hook{pretxncommit} (section~\ref{sec:hook:pretxncommit})
 59.1128 +
 59.1129 +\subsection{\hook{incoming}---after one remote changeset is added}
 59.1130 +\label{sec:hook:incoming}
 59.1131 +
 59.1132 +This hook is run after a pre-existing changeset has been added to the
 59.1133 +repository, for example via a \hgcmd{push}.  If a group of changesets
 59.1134 +was added in a single operation, this hook is called once for each
 59.1135 +added changeset.
 59.1136 +
 59.1137 +You can use this hook for the same purposes as the \hook{changegroup}
 59.1138 +hook (section~\ref{sec:hook:changegroup}); it's simply more convenient
 59.1139 +sometimes to run a hook once per group of changesets, while other
 59.1140 +times it's handier once per changeset.
 59.1141 +
 59.1142 +Parameters to this hook:
 59.1143 +\begin{itemize}
 59.1144 +\item[\texttt{node}] A changeset ID.  The ID of the newly added
 59.1145 +  changeset.
 59.1146 +\item[\texttt{source}] A string.  The source of these changes.  See
 59.1147 +  section~\ref{sec:hook:sources} for details.
 59.1148 +\item[\texttt{url}] A URL.  The location of the remote repository, if
 59.1149 +  known.  See section~\ref{sec:hook:url} for more information.
 59.1150 +\end{itemize}
 59.1151 +
 59.1152 +See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}) \hook{prechangegroup} (section~\ref{sec:hook:prechangegroup}), \hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup})
 59.1153 +
 59.1154 +\subsection{\hook{outgoing}---after changesets are propagated}
 59.1155 +\label{sec:hook:outgoing}
 59.1156 +
 59.1157 +This hook is run after a group of changesets has been propagated out
 59.1158 +of this repository, for example by a \hgcmd{push} or \hgcmd{bundle}
 59.1159 +command.
 59.1160 +
 59.1161 +One possible use for this hook is to notify administrators that
 59.1162 +changes have been pulled.
 59.1163 +
 59.1164 +Parameters to this hook:
 59.1165 +\begin{itemize}
 59.1166 +\item[\texttt{node}] A changeset ID.  The changeset ID of the first
 59.1167 +  changeset of the group that was sent.
 59.1168 +\item[\texttt{source}] A string.  The source of the of the operation
 59.1169 +  (see section~\ref{sec:hook:sources}).  If a remote client pulled
 59.1170 +  changes from this repository, \texttt{source} will be
 59.1171 +  \texttt{serve}.  If the client that obtained changes from this
 59.1172 +  repository was local, \texttt{source} will be \texttt{bundle},
 59.1173 +  \texttt{pull}, or \texttt{push}, depending on the operation the
 59.1174 +  client performed.
 59.1175 +\item[\texttt{url}] A URL.  The location of the remote repository, if
 59.1176 +  known.  See section~\ref{sec:hook:url} for more information.
 59.1177 +\end{itemize}
 59.1178 +
 59.1179 +See also: \hook{preoutgoing} (section~\ref{sec:hook:preoutgoing})
 59.1180 +
 59.1181 +\subsection{\hook{prechangegroup}---before starting to add remote changesets}
 59.1182 +\label{sec:hook:prechangegroup}
 59.1183 +
 59.1184 +This controlling hook is run before Mercurial begins to add a group of
 59.1185 +changesets from another repository.
 59.1186 +
 59.1187 +This hook does not have any information about the changesets to be
 59.1188 +added, because it is run before transmission of those changesets is
 59.1189 +allowed to begin.  If this hook fails, the changesets will not be
 59.1190 +transmitted.
 59.1191 +
 59.1192 +One use for this hook is to prevent external changes from being added
 59.1193 +to a repository.  For example, you could use this to ``freeze'' a
 59.1194 +server-hosted branch temporarily or permanently so that users cannot
 59.1195 +push to it, while still allowing a local administrator to modify the
 59.1196 +repository.
 59.1197 +
 59.1198 +Parameters to this hook:
 59.1199 +\begin{itemize}
 59.1200 +\item[\texttt{source}] A string.  The source of these changes.  See
 59.1201 +  section~\ref{sec:hook:sources} for details.
 59.1202 +\item[\texttt{url}] A URL.  The location of the remote repository, if
 59.1203 +  known.  See section~\ref{sec:hook:url} for more information.
 59.1204 +\end{itemize}
 59.1205 +
 59.1206 +See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}),
 59.1207 +\hook{incoming} (section~\ref{sec:hook:incoming}), ,
 59.1208 +\hook{pretxnchangegroup} (section~\ref{sec:hook:pretxnchangegroup})
 59.1209 +
 59.1210 +\subsection{\hook{precommit}---before starting to commit a changeset}
 59.1211 +\label{sec:hook:precommit}
 59.1212 +
 59.1213 +This hook is run before Mercurial begins to commit a new changeset.
 59.1214 +It is run before Mercurial has any of the metadata for the commit,
 59.1215 +such as the files to be committed, the commit message, or the commit
 59.1216 +date.
 59.1217 +
 59.1218 +One use for this hook is to disable the ability to commit new
 59.1219 +changesets, while still allowing incoming changesets.  Another is to
 59.1220 +run a build or test, and only allow the commit to begin if the build
 59.1221 +or test succeeds.
 59.1222 +
 59.1223 +Parameters to this hook:
 59.1224 +\begin{itemize}
 59.1225 +\item[\texttt{parent1}] A changeset ID.  The changeset ID of the first
 59.1226 +  parent of the working directory.
 59.1227 +\item[\texttt{parent2}] A changeset ID.  The changeset ID of the second
 59.1228 +  parent of the working directory.
 59.1229 +\end{itemize}
 59.1230 +If the commit proceeds, the parents of the working directory will
 59.1231 +become the parents of the new changeset.
 59.1232 +
 59.1233 +See also: \hook{commit} (section~\ref{sec:hook:commit}),
 59.1234 +\hook{pretxncommit} (section~\ref{sec:hook:pretxncommit})
 59.1235 +
 59.1236 +\subsection{\hook{preoutgoing}---before starting to propagate changesets}
 59.1237 +\label{sec:hook:preoutgoing}
 59.1238 +
 59.1239 +This hook is invoked before Mercurial knows the identities of the
 59.1240 +changesets to be transmitted.
 59.1241 +
 59.1242 +One use for this hook is to prevent changes from being transmitted to
 59.1243 +another repository.
 59.1244 +
 59.1245 +Parameters to this hook:
 59.1246 +\begin{itemize}
 59.1247 +\item[\texttt{source}] A string.  The source of the operation that is
 59.1248 +  attempting to obtain changes from this repository (see
 59.1249 +  section~\ref{sec:hook:sources}).  See the documentation for the
 59.1250 +  \texttt{source} parameter to the \hook{outgoing} hook, in
 59.1251 +  section~\ref{sec:hook:outgoing}, for possible values of this
 59.1252 +  parameter.
 59.1253 +\item[\texttt{url}] A URL.  The location of the remote repository, if
 59.1254 +  known.  See section~\ref{sec:hook:url} for more information.
 59.1255 +\end{itemize}
 59.1256 +
 59.1257 +See also: \hook{outgoing} (section~\ref{sec:hook:outgoing})
 59.1258 +
 59.1259 +\subsection{\hook{pretag}---before tagging a changeset}
 59.1260 +\label{sec:hook:pretag}
 59.1261 +
 59.1262 +This controlling hook is run before a tag is created.  If the hook
 59.1263 +succeeds, creation of the tag proceeds.  If the hook fails, the tag is
 59.1264 +not created.
 59.1265 +
 59.1266 +Parameters to this hook:
 59.1267 +\begin{itemize}
 59.1268 +\item[\texttt{local}] A boolean.  Whether the tag is local to this
 59.1269 +  repository instance (i.e.~stored in \sfilename{.hg/localtags}) or
 59.1270 +  managed by Mercurial (stored in \sfilename{.hgtags}).
 59.1271 +\item[\texttt{node}] A changeset ID.  The ID of the changeset to be tagged.
 59.1272 +\item[\texttt{tag}] A string.  The name of the tag to be created.
 59.1273 +\end{itemize}
 59.1274 +
 59.1275 +If the tag to be created is revision-controlled, the \hook{precommit}
 59.1276 +and \hook{pretxncommit} hooks (sections~\ref{sec:hook:commit}
 59.1277 +and~\ref{sec:hook:pretxncommit}) will also be run.
 59.1278 +
 59.1279 +See also: \hook{tag} (section~\ref{sec:hook:tag})
 59.1280 +
 59.1281 +\subsection{\hook{pretxnchangegroup}---before completing addition of
 59.1282 +  remote changesets}
 59.1283 +\label{sec:hook:pretxnchangegroup}
 59.1284 +
 59.1285 +This controlling hook is run before a transaction---that manages the
 59.1286 +addition of a group of new changesets from outside the
 59.1287 +repository---completes.  If the hook succeeds, the transaction
 59.1288 +completes, and all of the changesets become permanent within this
 59.1289 +repository.  If the hook fails, the transaction is rolled back, and
 59.1290 +the data for the changesets is erased.
 59.1291 +
 59.1292 +This hook can access the metadata associated with the almost-added
 59.1293 +changesets, but it should not do anything permanent with this data.
 59.1294 +It must also not modify the working directory.
 59.1295 +
 59.1296 +While this hook is running, if other Mercurial processes access this
 59.1297 +repository, they will be able to see the almost-added changesets as if
 59.1298 +they are permanent.  This may lead to race conditions if you do not
 59.1299 +take steps to avoid them.
 59.1300 +
 59.1301 +This hook can be used to automatically vet a group of changesets.  If
 59.1302 +the hook fails, all of the changesets are ``rejected'' when the
 59.1303 +transaction rolls back.
 59.1304 +
 59.1305 +Parameters to this hook:
 59.1306 +\begin{itemize}
 59.1307 +\item[\texttt{node}] A changeset ID.  The changeset ID of the first
 59.1308 +  changeset in the group that was added.  All changesets between this
 59.1309 +  and \index{tags!\texttt{tip}}\texttt{tip}, inclusive, were added by
 59.1310 +  a single \hgcmd{pull}, \hgcmd{push} or \hgcmd{unbundle}.
 59.1311 +\item[\texttt{source}] A string.  The source of these changes.  See
 59.1312 +  section~\ref{sec:hook:sources} for details.
 59.1313 +\item[\texttt{url}] A URL.  The location of the remote repository, if
 59.1314 +  known.  See section~\ref{sec:hook:url} for more information.
 59.1315 +\end{itemize}
 59.1316 +
 59.1317 +See also: \hook{changegroup} (section~\ref{sec:hook:changegroup}),
 59.1318 +\hook{incoming} (section~\ref{sec:hook:incoming}),
 59.1319 +\hook{prechangegroup} (section~\ref{sec:hook:prechangegroup})
 59.1320 +
 59.1321 +\subsection{\hook{pretxncommit}---before completing commit of new changeset}
 59.1322 +\label{sec:hook:pretxncommit}
 59.1323 +
 59.1324 +This controlling hook is run before a transaction---that manages a new
 59.1325 +commit---completes.  If the hook succeeds, the transaction completes
 59.1326 +and the changeset becomes permanent within this repository.  If the
 59.1327 +hook fails, the transaction is rolled back, and the commit data is
 59.1328 +erased.
 59.1329 +
 59.1330 +This hook can access the metadata associated with the almost-new
 59.1331 +changeset, but it should not do anything permanent with this data.  It
 59.1332 +must also not modify the working directory.
 59.1333 +
 59.1334 +While this hook is running, if other Mercurial processes access this
 59.1335 +repository, they will be able to see the almost-new changeset as if it
 59.1336 +is permanent.  This may lead to race conditions if you do not take
 59.1337 +steps to avoid them.
 59.1338 +
 59.1339 +Parameters to this hook:
 59.1340 +\begin{itemize}
 59.1341 +\item[\texttt{node}] A changeset ID.  The changeset ID of the newly
 59.1342 +  committed changeset.
 59.1343 +\item[\texttt{parent1}] A changeset ID.  The changeset ID of the first
 59.1344 +  parent of the newly committed changeset.
 59.1345 +\item[\texttt{parent2}] A changeset ID.  The changeset ID of the second
 59.1346 +  parent of the newly committed changeset.
 59.1347 +\end{itemize}
 59.1348 +
 59.1349 +See also: \hook{precommit} (section~\ref{sec:hook:precommit})
 59.1350 +
 59.1351 +\subsection{\hook{preupdate}---before updating or merging working directory}
 59.1352 +\label{sec:hook:preupdate}
 59.1353 +
 59.1354 +This controlling hook is run before an update or merge of the working
 59.1355 +directory begins.  It is run only if Mercurial's normal pre-update
 59.1356 +checks determine that the update or merge can proceed.  If the hook
 59.1357 +succeeds, the update or merge may proceed; if it fails, the update or
 59.1358 +merge does not start.
 59.1359 +
 59.1360 +Parameters to this hook:
 59.1361 +\begin{itemize}
 59.1362 +\item[\texttt{parent1}] A changeset ID.  The ID of the parent that the
 59.1363 +  working directory is to be updated to.  If the working directory is
 59.1364 +  being merged, it will not change this parent.
 59.1365 +\item[\texttt{parent2}] A changeset ID.  Only set if the working
 59.1366 +  directory is being merged.  The ID of the revision that the working
 59.1367 +  directory is being merged with.
 59.1368 +\end{itemize}
 59.1369 +
 59.1370 +See also: \hook{update} (section~\ref{sec:hook:update})
 59.1371 +
 59.1372 +\subsection{\hook{tag}---after tagging a changeset}
 59.1373 +\label{sec:hook:tag}
 59.1374 +
 59.1375 +This hook is run after a tag has been created.
 59.1376 +
 59.1377 +Parameters to this hook:
 59.1378 +\begin{itemize}
 59.1379 +\item[\texttt{local}] A boolean.  Whether the new tag is local to this
 59.1380 +  repository instance (i.e.~stored in \sfilename{.hg/localtags}) or
 59.1381 +  managed by Mercurial (stored in \sfilename{.hgtags}).
 59.1382 +\item[\texttt{node}] A changeset ID.  The ID of the changeset that was
 59.1383 +  tagged.
 59.1384 +\item[\texttt{tag}] A string.  The name of the tag that was created.
 59.1385 +\end{itemize}
 59.1386 +
 59.1387 +If the created tag is revision-controlled, the \hook{commit} hook
 59.1388 +(section~\ref{sec:hook:commit}) is run before this hook.
 59.1389 +
 59.1390 +See also: \hook{pretag} (section~\ref{sec:hook:pretag})
 59.1391 +
 59.1392 +\subsection{\hook{update}---after updating or merging working directory}
 59.1393 +\label{sec:hook:update}
 59.1394 +
 59.1395 +This hook is run after an update or merge of the working directory
 59.1396 +completes.  Since a merge can fail (if the external \command{hgmerge}
 59.1397 +command fails to resolve conflicts in a file), this hook communicates
 59.1398 +whether the update or merge completed cleanly.
 59.1399 +
 59.1400 +\begin{itemize}
 59.1401 +\item[\texttt{error}] A boolean.  Indicates whether the update or
 59.1402 +  merge completed successfully.
 59.1403 +\item[\texttt{parent1}] A changeset ID.  The ID of the parent that the
 59.1404 +  working directory was updated to.  If the working directory was
 59.1405 +  merged, it will not have changed this parent.
 59.1406 +\item[\texttt{parent2}] A changeset ID.  Only set if the working
 59.1407 +  directory was merged.  The ID of the revision that the working
 59.1408 +  directory was merged with.
 59.1409 +\end{itemize}
 59.1410 +
 59.1411 +See also: \hook{preupdate} (section~\ref{sec:hook:preupdate})
 59.1412 +
 59.1413 +%%% Local Variables: 
 59.1414 +%%% mode: latex
 59.1415 +%%% TeX-master: "00book"
 59.1416 +%%% End: 
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/fr/htlatex.book	Thu Feb 05 12:37:03 2009 +0100
    60.3 @@ -0,0 +1,12 @@
    60.4 +#!/bin/bash
    60.5 +#
    60.6 +# This script is horrible.  It's essentially a hacked copy of
    60.7 +# /usr/bin/htlatex from Fedora Core 6.  I apologise for any lasting
    60.8 +# pain reading it causes.
    60.9 +
   60.10 +latex $5 '\makeatletter\def\HCode{\futurelet\HCode\HChar}\def\HChar{\ifx"\HCode\def\HCode"##1"{\Link##1}\expandafter\HCode\else\expandafter\Link\fi}\def\Link#1.a.b.c.{\g@addto@macro\@documentclasshook{\RequirePackage[#1,html]{tex4ht}}\let\HCode\documentstyle\def\documentstyle{\let\documentstyle\HCode\expandafter\def\csname tex4ht\endcsname{#1,html}\def\HCode####1{\documentstyle[tex4ht,}\@ifnextchar[{\HCode}{\documentstyle[tex4ht]}}}\makeatother\HCode '$2'.a.b.c.\input ' $1
   60.11 +(cd $4 && bibtex hgbook)
   60.12 +(cd $4 && makeindex hgbook)
   60.13 +latex $5 '\makeatletter\def\HCode{\futurelet\HCode\HChar}\def\HChar{\ifx"\HCode\def\HCode"##1"{\Link##1}\expandafter\HCode\else\expandafter\Link\fi}\def\Link#1.a.b.c.{\g@addto@macro\@documentclasshook{\RequirePackage[#1,html]{tex4ht}}\let\HCode\documentstyle\def\documentstyle{\let\documentstyle\HCode\expandafter\def\csname tex4ht\endcsname{#1,html}\def\HCode####1{\documentstyle[tex4ht,}\@ifnextchar[{\HCode}{\documentstyle[tex4ht]}}}\makeatother\HCode '$2'.a.b.c.\input ' $1
   60.14 +latex $5 '\makeatletter\def\HCode{\futurelet\HCode\HChar}\def\HChar{\ifx"\HCode\def\HCode"##1"{\Link##1}\expandafter\HCode\else\expandafter\Link\fi}\def\Link#1.a.b.c.{\g@addto@macro\@documentclasshook{\RequirePackage[#1,html]{tex4ht}}\let\HCode\documentstyle\def\documentstyle{\let\documentstyle\HCode\expandafter\def\csname tex4ht\endcsname{#1,html}\def\HCode####1{\documentstyle[tex4ht,}\@ifnextchar[{\HCode}{\documentstyle[tex4ht]}}}\makeatother\HCode '$2'.a.b.c.\input ' $1
   60.15 +echo status $$
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/fr/intro.tex	Thu Feb 05 12:37:03 2009 +0100
    61.3 @@ -0,0 +1,561 @@
    61.4 +\chapter{Introduction}
    61.5 +\label{chap:intro}
    61.6 +
    61.7 +\section{About revision control}
    61.8 +
    61.9 +Revision control is the process of managing multiple versions of a
   61.10 +piece of information.  In its simplest form, this is something that
   61.11 +many people do by hand: every time you modify a file, save it under a
   61.12 +new name that contains a number, each one higher than the number of
   61.13 +the preceding version.
   61.14 +
   61.15 +Manually managing multiple versions of even a single file is an
   61.16 +error-prone task, though, so software tools to help automate this
   61.17 +process have long been available.  The earliest automated revision
   61.18 +control tools were intended to help a single user to manage revisions
   61.19 +of a single file.  Over the past few decades, the scope of revision
   61.20 +control tools has expanded greatly; they now manage multiple files,
   61.21 +and help multiple people to work together.  The best modern revision
   61.22 +control tools have no problem coping with thousands of people working
   61.23 +together on projects that consist of hundreds of thousands of files.
   61.24 +
   61.25 +\subsection{Why use revision control?}
   61.26 +
   61.27 +There are a number of reasons why you or your team might want to use
   61.28 +an automated revision control tool for a project.
   61.29 +\begin{itemize}
   61.30 +\item It will track the history and evolution of your project, so you
   61.31 +  don't have to.  For every change, you'll have a log of \emph{who}
   61.32 +  made it; \emph{why} they made it; \emph{when} they made it; and
   61.33 +  \emph{what} the change was.
   61.34 +\item When you're working with other people, revision control software
   61.35 +  makes it easier for you to collaborate.  For example, when people
   61.36 +  more or less simultaneously make potentially incompatible changes,
   61.37 +  the software will help you to identify and resolve those conflicts.
   61.38 +\item It can help you to recover from mistakes.  If you make a change
   61.39 +  that later turns out to be in error, you can revert to an earlier
   61.40 +  version of one or more files.  In fact, a \emph{really} good
   61.41 +  revision control tool will even help you to efficiently figure out
   61.42 +  exactly when a problem was introduced (see
   61.43 +  section~\ref{sec:undo:bisect} for details).
   61.44 +\item It will help you to work simultaneously on, and manage the drift
   61.45 +  between, multiple versions of your project.
   61.46 +\end{itemize}
   61.47 +Most of these reasons are equally valid---at least in theory---whether
   61.48 +you're working on a project by yourself, or with a hundred other
   61.49 +people.
   61.50 +
   61.51 +A key question about the practicality of revision control at these two
   61.52 +different scales (``lone hacker'' and ``huge team'') is how its
   61.53 +\emph{benefits} compare to its \emph{costs}.  A revision control tool
   61.54 +that's difficult to understand or use is going to impose a high cost.
   61.55 +
   61.56 +A five-hundred-person project is likely to collapse under its own
   61.57 +weight almost immediately without a revision control tool and process.
   61.58 +In this case, the cost of using revision control might hardly seem
   61.59 +worth considering, since \emph{without} it, failure is almost
   61.60 +guaranteed.
   61.61 +
   61.62 +On the other hand, a one-person ``quick hack'' might seem like a poor
   61.63 +place to use a revision control tool, because surely the cost of using
   61.64 +one must be close to the overall cost of the project.  Right?
   61.65 +
   61.66 +Mercurial uniquely supports \emph{both} of these scales of
   61.67 +development.  You can learn the basics in just a few minutes, and due
   61.68 +to its low overhead, you can apply revision control to the smallest of
   61.69 +projects with ease.  Its simplicity means you won't have a lot of
   61.70 +abstruse concepts or command sequences competing for mental space with
   61.71 +whatever you're \emph{really} trying to do.  At the same time,
   61.72 +Mercurial's high performance and peer-to-peer nature let you scale
   61.73 +painlessly to handle large projects.
   61.74 +
   61.75 +No revision control tool can rescue a poorly run project, but a good
   61.76 +choice of tools can make a huge difference to the fluidity with which
   61.77 +you can work on a project.
   61.78 +
   61.79 +\subsection{The many names of revision control}
   61.80 +
   61.81 +Revision control is a diverse field, so much so that it doesn't
   61.82 +actually have a single name or acronym.  Here are a few of the more
   61.83 +common names and acronyms you'll encounter:
   61.84 +\begin{itemize}
   61.85 +\item Revision control (RCS)
   61.86 +\item Software configuration management (SCM), or configuration management
   61.87 +\item Source code management
   61.88 +\item Source code control, or source control
   61.89 +\item Version control (VCS)
   61.90 +\end{itemize}
   61.91 +Some people claim that these terms actually have different meanings,
   61.92 +but in practice they overlap so much that there's no agreed or even
   61.93 +useful way to tease them apart.
   61.94 +
   61.95 +\section{A short history of revision control}
   61.96 +
   61.97 +The best known of the old-time revision control tools is SCCS (Source
   61.98 +Code Control System), which Marc Rochkind wrote at Bell Labs, in the
   61.99 +early 1970s.  SCCS operated on individual files, and required every
  61.100 +person working on a project to have access to a shared workspace on a
  61.101 +single system.  Only one person could modify a file at any time;
  61.102 +arbitration for access to files was via locks.  It was common for
  61.103 +people to lock files, and later forget to unlock them, preventing
  61.104 +anyone else from modifying those files without the help of an
  61.105 +administrator.  
  61.106 +
  61.107 +Walter Tichy developed a free alternative to SCCS in the early 1980s;
  61.108 +he called his program RCS (Revison Control System).  Like SCCS, RCS
  61.109 +required developers to work in a single shared workspace, and to lock
  61.110 +files to prevent multiple people from modifying them simultaneously.
  61.111 +
  61.112 +Later in the 1980s, Dick Grune used RCS as a building block for a set
  61.113 +of shell scripts he initially called cmt, but then renamed to CVS
  61.114 +(Concurrent Versions System).  The big innovation of CVS was that it
  61.115 +let developers work simultaneously and somewhat independently in their
  61.116 +own personal workspaces.  The personal workspaces prevented developers
  61.117 +from stepping on each other's toes all the time, as was common with
  61.118 +SCCS and RCS.  Each developer had a copy of every project file, and
  61.119 +could modify their copies independently.  They had to merge their
  61.120 +edits prior to committing changes to the central repository.
  61.121 +
  61.122 +Brian Berliner took Grune's original scripts and rewrote them in~C,
  61.123 +releasing in 1989 the code that has since developed into the modern
  61.124 +version of CVS.  CVS subsequently acquired the ability to operate over
  61.125 +a network connection, giving it a client/server architecture.  CVS's
  61.126 +architecture is centralised; only the server has a copy of the history
  61.127 +of the project.  Client workspaces just contain copies of recent
  61.128 +versions of the project's files, and a little metadata to tell them
  61.129 +where the server is.  CVS has been enormously successful; it is
  61.130 +probably the world's most widely used revision control system.
  61.131 +
  61.132 +In the early 1990s, Sun Microsystems developed an early distributed
  61.133 +revision control system, called TeamWare.  A TeamWare workspace
  61.134 +contains a complete copy of the project's history.  TeamWare has no
  61.135 +notion of a central repository.  (CVS relied upon RCS for its history
  61.136 +storage; TeamWare used SCCS.)
  61.137 +
  61.138 +As the 1990s progressed, awareness grew of a number of problems with
  61.139 +CVS.  It records simultaneous changes to multiple files individually,
  61.140 +instead of grouping them together as a single logically atomic
  61.141 +operation.  It does not manage its file hierarchy well; it is easy to
  61.142 +make a mess of a repository by renaming files and directories.  Worse,
  61.143 +its source code is difficult to read and maintain, which made the
  61.144 +``pain level'' of fixing these architectural problems prohibitive.
  61.145 +
  61.146 +In 2001, Jim Blandy and Karl Fogel, two developers who had worked on
  61.147 +CVS, started a project to replace it with a tool that would have a
  61.148 +better architecture and cleaner code.  The result, Subversion, does
  61.149 +not stray from CVS's centralised client/server model, but it adds
  61.150 +multi-file atomic commits, better namespace management, and a number
  61.151 +of other features that make it a generally better tool than CVS.
  61.152 +Since its initial release, it has rapidly grown in popularity.
  61.153 +
  61.154 +More or less simultaneously, Graydon Hoare began working on an
  61.155 +ambitious distributed revision control system that he named Monotone.
  61.156 +While Monotone addresses many of CVS's design flaws and has a
  61.157 +peer-to-peer architecture, it goes beyond earlier (and subsequent)
  61.158 +revision control tools in a number of innovative ways.  It uses
  61.159 +cryptographic hashes as identifiers, and has an integral notion of
  61.160 +``trust'' for code from different sources.
  61.161 +
  61.162 +Mercurial began life in 2005.  While a few aspects of its design are
  61.163 +influenced by Monotone, Mercurial focuses on ease of use, high
  61.164 +performance, and scalability to very large projects.
  61.165 +
  61.166 +\section{Trends in revision control}
  61.167 +
  61.168 +There has been an unmistakable trend in the development and use of
  61.169 +revision control tools over the past four decades, as people have
  61.170 +become familiar with the capabilities of their tools and constrained
  61.171 +by their limitations.
  61.172 +
  61.173 +The first generation began by managing single files on individual
  61.174 +computers.  Although these tools represented a huge advance over
  61.175 +ad-hoc manual revision control, their locking model and reliance on a
  61.176 +single computer limited them to small, tightly-knit teams.
  61.177 +
  61.178 +The second generation loosened these constraints by moving to
  61.179 +network-centered architectures, and managing entire projects at a
  61.180 +time.  As projects grew larger, they ran into new problems.  With
  61.181 +clients needing to talk to servers very frequently, server scaling
  61.182 +became an issue for large projects.  An unreliable network connection
  61.183 +could prevent remote users from being able to talk to the server at
  61.184 +all.  As open source projects started making read-only access
  61.185 +available anonymously to anyone, people without commit privileges
  61.186 +found that they could not use the tools to interact with a project in
  61.187 +a natural way, as they could not record their changes.
  61.188 +
  61.189 +The current generation of revision control tools is peer-to-peer in
  61.190 +nature.  All of these systems have dropped the dependency on a single
  61.191 +central server, and allow people to distribute their revision control
  61.192 +data to where it's actually needed.  Collaboration over the Internet
  61.193 +has moved from constrained by technology to a matter of choice and
  61.194 +consensus.  Modern tools can operate offline indefinitely and
  61.195 +autonomously, with a network connection only needed when syncing
  61.196 +changes with another repository.
  61.197 +
  61.198 +\section{A few of the advantages of distributed revision control}
  61.199 +
  61.200 +Even though distributed revision control tools have for several years
  61.201 +been as robust and usable as their previous-generation counterparts,
  61.202 +people using older tools have not yet necessarily woken up to their
  61.203 +advantages.  There are a number of ways in which distributed tools
  61.204 +shine relative to centralised ones.
  61.205 +
  61.206 +For an individual developer, distributed tools are almost always much
  61.207 +faster than centralised tools.  This is for a simple reason: a
  61.208 +centralised tool needs to talk over the network for many common
  61.209 +operations, because most metadata is stored in a single copy on the
  61.210 +central server.  A distributed tool stores all of its metadata
  61.211 +locally.  All else being equal, talking over the network adds overhead
  61.212 +to a centralised tool.  Don't underestimate the value of a snappy,
  61.213 +responsive tool: you're going to spend a lot of time interacting with
  61.214 +your revision control software.
  61.215 +
  61.216 +Distributed tools are indifferent to the vagaries of your server
  61.217 +infrastructure, again because they replicate metadata to so many
  61.218 +locations.  If you use a centralised system and your server catches
  61.219 +fire, you'd better hope that your backup media are reliable, and that
  61.220 +your last backup was recent and actually worked.  With a distributed
  61.221 +tool, you have many backups available on every contributor's computer.
  61.222 +
  61.223 +The reliability of your network will affect distributed tools far less
  61.224 +than it will centralised tools.  You can't even use a centralised tool
  61.225 +without a network connection, except for a few highly constrained
  61.226 +commands.  With a distributed tool, if your network connection goes
  61.227 +down while you're working, you may not even notice.  The only thing
  61.228 +you won't be able to do is talk to repositories on other computers,
  61.229 +something that is relatively rare compared with local operations.  If
  61.230 +you have a far-flung team of collaborators, this may be significant.
  61.231 +
  61.232 +\subsection{Advantages for open source projects}
  61.233 +
  61.234 +If you take a shine to an open source project and decide that you
  61.235 +would like to start hacking on it, and that project uses a distributed
  61.236 +revision control tool, you are at once a peer with the people who
  61.237 +consider themselves the ``core'' of that project.  If they publish
  61.238 +their repositories, you can immediately copy their project history,
  61.239 +start making changes, and record your work, using the same tools in
  61.240 +the same ways as insiders.  By contrast, with a centralised tool, you
  61.241 +must use the software in a ``read only'' mode unless someone grants
  61.242 +you permission to commit changes to their central server.  Until then,
  61.243 +you won't be able to record changes, and your local modifications will
  61.244 +be at risk of corruption any time you try to update your client's view
  61.245 +of the repository.
  61.246 +
  61.247 +\subsubsection{The forking non-problem}
  61.248 +
  61.249 +It has been suggested that distributed revision control tools pose
  61.250 +some sort of risk to open source projects because they make it easy to
  61.251 +``fork'' the development of a project.  A fork happens when there are
  61.252 +differences in opinion or attitude between groups of developers that
  61.253 +cause them to decide that they can't work together any longer.  Each
  61.254 +side takes a more or less complete copy of the project's source code,
  61.255 +and goes off in its own direction.
  61.256 +
  61.257 +Sometimes the camps in a fork decide to reconcile their differences.
  61.258 +With a centralised revision control system, the \emph{technical}
  61.259 +process of reconciliation is painful, and has to be performed largely
  61.260 +by hand.  You have to decide whose revision history is going to
  61.261 +``win'', and graft the other team's changes into the tree somehow.
  61.262 +This usually loses some or all of one side's revision history.
  61.263 +
  61.264 +What distributed tools do with respect to forking is they make forking
  61.265 +the \emph{only} way to develop a project.  Every single change that
  61.266 +you make is potentially a fork point.  The great strength of this
  61.267 +approach is that a distributed revision control tool has to be really
  61.268 +good at \emph{merging} forks, because forks are absolutely
  61.269 +fundamental: they happen all the time.  
  61.270 +
  61.271 +If every piece of work that everybody does, all the time, is framed in
  61.272 +terms of forking and merging, then what the open source world refers
  61.273 +to as a ``fork'' becomes \emph{purely} a social issue.  If anything,
  61.274 +distributed tools \emph{lower} the likelihood of a fork:
  61.275 +\begin{itemize}
  61.276 +\item They eliminate the social distinction that centralised tools
  61.277 +  impose: that between insiders (people with commit access) and
  61.278 +  outsiders (people without).
  61.279 +\item They make it easier to reconcile after a social fork, because
  61.280 +  all that's involved from the perspective of the revision control
  61.281 +  software is just another merge.
  61.282 +\end{itemize}
  61.283 +
  61.284 +Some people resist distributed tools because they want to retain tight
  61.285 +control over their projects, and they believe that centralised tools
  61.286 +give them this control.  However, if you're of this belief, and you
  61.287 +publish your CVS or Subversion repositories publically, there are
  61.288 +plenty of tools available that can pull out your entire project's
  61.289 +history (albeit slowly) and recreate it somewhere that you don't
  61.290 +control.  So while your control in this case is illusory, you are
  61.291 +forgoing the ability to fluidly collaborate with whatever people feel
  61.292 +compelled to mirror and fork your history.
  61.293 +
  61.294 +\subsection{Advantages for commercial projects}
  61.295 +
  61.296 +Many commercial projects are undertaken by teams that are scattered
  61.297 +across the globe.  Contributors who are far from a central server will
  61.298 +see slower command execution and perhaps less reliability.  Commercial
  61.299 +revision control systems attempt to ameliorate these problems with
  61.300 +remote-site replication add-ons that are typically expensive to buy
  61.301 +and cantankerous to administer.  A distributed system doesn't suffer
  61.302 +from these problems in the first place.  Better yet, you can easily
  61.303 +set up multiple authoritative servers, say one per site, so that
  61.304 +there's no redundant communication between repositories over expensive
  61.305 +long-haul network links.
  61.306 +
  61.307 +Centralised revision control systems tend to have relatively low
  61.308 +scalability.  It's not unusual for an expensive centralised system to
  61.309 +fall over under the combined load of just a few dozen concurrent
  61.310 +users.  Once again, the typical response tends to be an expensive and
  61.311 +clunky replication facility.  Since the load on a central server---if
  61.312 +you have one at all---is many times lower with a distributed
  61.313 +tool (because all of the data is replicated everywhere), a single
  61.314 +cheap server can handle the needs of a much larger team, and
  61.315 +replication to balance load becomes a simple matter of scripting.
  61.316 +
  61.317 +If you have an employee in the field, troubleshooting a problem at a
  61.318 +customer's site, they'll benefit from distributed revision control.
  61.319 +The tool will let them generate custom builds, try different fixes in
  61.320 +isolation from each other, and search efficiently through history for
  61.321 +the sources of bugs and regressions in the customer's environment, all
  61.322 +without needing to connect to your company's network.
  61.323 +
  61.324 +\section{Why choose Mercurial?}
  61.325 +
  61.326 +Mercurial has a unique set of properties that make it a particularly
  61.327 +good choice as a revision control system.
  61.328 +\begin{itemize}
  61.329 +\item It is easy to learn and use.
  61.330 +\item It is lightweight.
  61.331 +\item It scales excellently.
  61.332 +\item It is easy to customise.
  61.333 +\end{itemize}
  61.334 +
  61.335 +If you are at all familiar with revision control systems, you should
  61.336 +be able to get up and running with Mercurial in less than five
  61.337 +minutes.  Even if not, it will take no more than a few minutes
  61.338 +longer.  Mercurial's command and feature sets are generally uniform
  61.339 +and consistent, so you can keep track of a few general rules instead
  61.340 +of a host of exceptions.
  61.341 +
  61.342 +On a small project, you can start working with Mercurial in moments.
  61.343 +Creating new changes and branches; transferring changes around
  61.344 +(whether locally or over a network); and history and status operations
  61.345 +are all fast.  Mercurial attempts to stay nimble and largely out of
  61.346 +your way by combining low cognitive overhead with blazingly fast
  61.347 +operations.
  61.348 +
  61.349 +The usefulness of Mercurial is not limited to small projects: it is
  61.350 +used by projects with hundreds to thousands of contributors, each
  61.351 +containing tens of thousands of files and hundreds of megabytes of
  61.352 +source code.
  61.353 +
  61.354 +If the core functionality of Mercurial is not enough for you, it's
  61.355 +easy to build on.  Mercurial is well suited to scripting tasks, and
  61.356 +its clean internals and implementation in Python make it easy to add
  61.357 +features in the form of extensions.  There are a number of popular and
  61.358 +useful extensions already available, ranging from helping to identify
  61.359 +bugs to improving performance.
  61.360 +
  61.361 +\section{Mercurial compared with other tools}
  61.362 +
  61.363 +Before you read on, please understand that this section necessarily
  61.364 +reflects my own experiences, interests, and (dare I say it) biases.  I
  61.365 +have used every one of the revision control tools listed below, in
  61.366 +most cases for several years at a time.
  61.367 +
  61.368 +
  61.369 +\subsection{Subversion}
  61.370 +
  61.371 +Subversion is a popular revision control tool, developed to replace
  61.372 +CVS.  It has a centralised client/server architecture.
  61.373 +
  61.374 +Subversion and Mercurial have similarly named commands for performing
  61.375 +the same operations, so if you're familiar with one, it is easy to
  61.376 +learn to use the other.  Both tools are portable to all popular
  61.377 +operating systems.
  61.378 +
  61.379 +Prior to version 1.5, Subversion had no useful support for merges.
  61.380 +At the time of writing, its merge tracking capability is new, and known to be
  61.381 +\href{http://svnbook.red-bean.com/nightly/en/svn.branchmerge.advanced.html#svn.branchmerge.advanced.finalword}{complicated
  61.382 +  and buggy}.
  61.383 +
  61.384 +Mercurial has a substantial performance advantage over Subversion on
  61.385 +every revision control operation I have benchmarked.  I have measured
  61.386 +its advantage as ranging from a factor of two to a factor of six when
  61.387 +compared with Subversion~1.4.3's \emph{ra\_local} file store, which is
  61.388 +the fastest access method available.  In more realistic deployments
  61.389 +involving a network-based store, Subversion will be at a substantially
  61.390 +larger disadvantage.  Because many Subversion commands must talk to
  61.391 +the server and Subversion does not have useful replication facilities,
  61.392 +server capacity and network bandwidth become bottlenecks for modestly
  61.393 +large projects.
  61.394 +
  61.395 +Additionally, Subversion incurs substantial storage overhead to avoid
  61.396 +network transactions for a few common operations, such as finding
  61.397 +modified files (\texttt{status}) and displaying modifications against
  61.398 +the current revision (\texttt{diff}).  As a result, a Subversion
  61.399 +working copy is often the same size as, or larger than, a Mercurial
  61.400 +repository and working directory, even though the Mercurial repository
  61.401 +contains a complete history of the project.
  61.402 +
  61.403 +Subversion is widely supported by third party tools.  Mercurial
  61.404 +currently lags considerably in this area.  This gap is closing,
  61.405 +however, and indeed some of Mercurial's GUI tools now outshine their
  61.406 +Subversion equivalents.  Like Mercurial, Subversion has an excellent
  61.407 +user manual.
  61.408 +
  61.409 +Because Subversion doesn't store revision history on the client, it is
  61.410 +well suited to managing projects that deal with lots of large, opaque
  61.411 +binary files.  If you check in fifty revisions to an incompressible
  61.412 +10MB file, Subversion's client-side space usage stays constant The
  61.413 +space used by any distributed SCM will grow rapidly in proportion to
  61.414 +the number of revisions, because the differences between each revision
  61.415 +are large.
  61.416 +
  61.417 +In addition, it's often difficult or, more usually, impossible to
  61.418 +merge different versions of a binary file.  Subversion's ability to
  61.419 +let a user lock a file, so that they temporarily have the exclusive
  61.420 +right to commit changes to it, can be a significant advantage to a
  61.421 +project where binary files are widely used.
  61.422 +
  61.423 +Mercurial can import revision history from a Subversion repository.
  61.424 +It can also export revision history to a Subversion repository.  This
  61.425 +makes it easy to ``test the waters'' and use Mercurial and Subversion
  61.426 +in parallel before deciding to switch.  History conversion is
  61.427 +incremental, so you can perform an initial conversion, then small
  61.428 +additional conversions afterwards to bring in new changes.
  61.429 +
  61.430 +
  61.431 +\subsection{Git}
  61.432 +
  61.433 +Git is a distributed revision control tool that was developed for
  61.434 +managing the Linux kernel source tree.  Like Mercurial, its early
  61.435 +design was somewhat influenced by Monotone.
  61.436 +
  61.437 +Git has a very large command set, with version~1.5.0 providing~139
  61.438 +individual commands.  It has something of a reputation for being
  61.439 +difficult to learn.  Compared to Git, Mercurial has a strong focus on
  61.440 +simplicity.
  61.441 +
  61.442 +In terms of performance, Git is extremely fast.  In several cases, it
  61.443 +is faster than Mercurial, at least on Linux, while Mercurial performs
  61.444 +better on other operations.  However, on Windows, the performance and
  61.445 +general level of support that Git provides is, at the time of writing,
  61.446 +far behind that of Mercurial.
  61.447 +
  61.448 +While a Mercurial repository needs no maintenance, a Git repository
  61.449 +requires frequent manual ``repacks'' of its metadata.  Without these,
  61.450 +performance degrades, while space usage grows rapidly.  A server that
  61.451 +contains many Git repositories that are not rigorously and frequently
  61.452 +repacked will become heavily disk-bound during backups, and there have
  61.453 +been instances of daily backups taking far longer than~24 hours as a
  61.454 +result.  A freshly packed Git repository is slightly smaller than a
  61.455 +Mercurial repository, but an unpacked repository is several orders of
  61.456 +magnitude larger.
  61.457 +
  61.458 +The core of Git is written in C.  Many Git commands are implemented as
  61.459 +shell or Perl scripts, and the quality of these scripts varies widely.
  61.460 +I have encountered several instances where scripts charged along
  61.461 +blindly in the presence of errors that should have been fatal.
  61.462 +
  61.463 +Mercurial can import revision history from a Git repository.
  61.464 +
  61.465 +
  61.466 +\subsection{CVS}
  61.467 +
  61.468 +CVS is probably the most widely used revision control tool in the
  61.469 +world.  Due to its age and internal untidiness, it has been only
  61.470 +lightly maintained for many years.
  61.471 +
  61.472 +It has a centralised client/server architecture.  It does not group
  61.473 +related file changes into atomic commits, making it easy for people to
  61.474 +``break the build'': one person can successfully commit part of a
  61.475 +change and then be blocked by the need for a merge, causing other
  61.476 +people to see only a portion of the work they intended to do.  This
  61.477 +also affects how you work with project history.  If you want to see
  61.478 +all of the modifications someone made as part of a task, you will need
  61.479 +to manually inspect the descriptions and timestamps of the changes
  61.480 +made to each file involved (if you even know what those files were).
  61.481 +
  61.482 +CVS has a muddled notion of tags and branches that I will not attempt
  61.483 +to even describe.  It does not support renaming of files or
  61.484 +directories well, making it easy to corrupt a repository.  It has
  61.485 +almost no internal consistency checking capabilities, so it is usually
  61.486 +not even possible to tell whether or how a repository is corrupt.  I
  61.487 +would not recommend CVS for any project, existing or new.
  61.488 +
  61.489 +Mercurial can import CVS revision history.  However, there are a few
  61.490 +caveats that apply; these are true of every other revision control
  61.491 +tool's CVS importer, too.  Due to CVS's lack of atomic changes and
  61.492 +unversioned filesystem hierarchy, it is not possible to reconstruct
  61.493 +CVS history completely accurately; some guesswork is involved, and
  61.494 +renames will usually not show up.  Because a lot of advanced CVS
  61.495 +administration has to be done by hand and is hence error-prone, it's
  61.496 +common for CVS importers to run into multiple problems with corrupted
  61.497 +repositories (completely bogus revision timestamps and files that have
  61.498 +remained locked for over a decade are just two of the less interesting
  61.499 +problems I can recall from personal experience).
  61.500 +
  61.501 +Mercurial can import revision history from a CVS repository.
  61.502 +
  61.503 +
  61.504 +\subsection{Commercial tools}
  61.505 +
  61.506 +Perforce has a centralised client/server architecture, with no
  61.507 +client-side caching of any data.  Unlike modern revision control
  61.508 +tools, Perforce requires that a user run a command to inform the
  61.509 +server about every file they intend to edit.
  61.510 +
  61.511 +The performance of Perforce is quite good for small teams, but it
  61.512 +falls off rapidly as the number of users grows beyond a few dozen.
  61.513 +Modestly large Perforce installations require the deployment of
  61.514 +proxies to cope with the load their users generate.
  61.515 +
  61.516 +
  61.517 +\subsection{Choosing a revision control tool}
  61.518 +
  61.519 +With the exception of CVS, all of the tools listed above have unique
  61.520 +strengths that suit them to particular styles of work.  There is no
  61.521 +single revision control tool that is best in all situations.
  61.522 +
  61.523 +As an example, Subversion is a good choice for working with frequently
  61.524 +edited binary files, due to its centralised nature and support for
  61.525 +file locking.
  61.526 +
  61.527 +I personally find Mercurial's properties of simplicity, performance,
  61.528 +and good merge support to be a compelling combination that has served
  61.529 +me well for several years.
  61.530 +
  61.531 +
  61.532 +\section{Switching from another tool to Mercurial}
  61.533 +
  61.534 +Mercurial is bundled with an extension named \hgext{convert}, which
  61.535 +can incrementally import revision history from several other revision
  61.536 +control tools.  By ``incremental'', I mean that you can convert all of
  61.537 +a project's history to date in one go, then rerun the conversion later
  61.538 +to obtain new changes that happened after the initial conversion.
  61.539 +
  61.540 +The revision control tools supported by \hgext{convert} are as
  61.541 +follows:
  61.542 +\begin{itemize}
  61.543 +\item Subversion
  61.544 +\item CVS
  61.545 +\item Git
  61.546 +\item Darcs
  61.547 +\end{itemize}
  61.548 +
  61.549 +In addition, \hgext{convert} can export changes from Mercurial to
  61.550 +Subversion.  This makes it possible to try Subversion and Mercurial in
  61.551 +parallel before committing to a switchover, without risking the loss
  61.552 +of any work.
  61.553 +
  61.554 +The \hgxcmd{conver}{convert} command is easy to use.  Simply point it
  61.555 +at the path or URL of the source repository, optionally give it the
  61.556 +name of the destination repository, and it will start working.  After
  61.557 +the initial conversion, just run the same command again to import new
  61.558 +changes.
  61.559 +
  61.560 +
  61.561 +%%% Local Variables: 
  61.562 +%%% mode: latex
  61.563 +%%% TeX-master: "00book"
  61.564 +%%% End: 
    62.1 Binary file fr/kdiff3.png has changed
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/fr/license.tex	Thu Feb 05 12:37:03 2009 +0100
    63.3 @@ -0,0 +1,138 @@
    63.4 +\chapter{Open Publication License}
    63.5 +\label{cha:opl}
    63.6 +
    63.7 +Version 1.0, 8 June 1999
    63.8 +
    63.9 +\section{Requirements on both unmodified and modified versions}
   63.10 +
   63.11 +The Open Publication works may be reproduced and distributed in whole
   63.12 +or in part, in any medium physical or electronic, provided that the
   63.13 +terms of this license are adhered to, and that this license or an
   63.14 +incorporation of it by reference (with any options elected by the
   63.15 +author(s) and/or publisher) is displayed in the reproduction.
   63.16 +
   63.17 +Proper form for an incorporation by reference is as follows:
   63.18 +
   63.19 +\begin{quote}
   63.20 +  Copyright (c) \emph{year} by \emph{author's name or designee}. This
   63.21 +  material may be distributed only subject to the terms and conditions
   63.22 +  set forth in the Open Publication License, v\emph{x.y} or later (the
   63.23 +  latest version is presently available at
   63.24 +  \url{http://www.opencontent.org/openpub/}).
   63.25 +\end{quote}
   63.26 +
   63.27 +The reference must be immediately followed with any options elected by
   63.28 +the author(s) and/or publisher of the document (see
   63.29 +section~\ref{sec:opl:options}).
   63.30 +
   63.31 +Commercial redistribution of Open Publication-licensed material is
   63.32 +permitted.
   63.33 +
   63.34 +Any publication in standard (paper) book form shall require the
   63.35 +citation of the original publisher and author. The publisher and
   63.36 +author's names shall appear on all outer surfaces of the book. On all
   63.37 +outer surfaces of the book the original publisher's name shall be as
   63.38 +large as the title of the work and cited as possessive with respect to
   63.39 +the title.
   63.40 +
   63.41 +\section{Copyright}
   63.42 +
   63.43 +The copyright to each Open Publication is owned by its author(s) or
   63.44 +designee.
   63.45 +
   63.46 +\section{Scope of license}
   63.47 +
   63.48 +The following license terms apply to all Open Publication works,
   63.49 +unless otherwise explicitly stated in the document.
   63.50 +
   63.51 +Mere aggregation of Open Publication works or a portion of an Open
   63.52 +Publication work with other works or programs on the same media shall
   63.53 +not cause this license to apply to those other works. The aggregate
   63.54 +work shall contain a notice specifying the inclusion of the Open
   63.55 +Publication material and appropriate copyright notice.
   63.56 +
   63.57 +\textbf{Severability}. If any part of this license is found to be
   63.58 +unenforceable in any jurisdiction, the remaining portions of the
   63.59 +license remain in force.
   63.60 +
   63.61 +\textbf{No warranty}. Open Publication works are licensed and provided
   63.62 +``as is'' without warranty of any kind, express or implied, including,
   63.63 +but not limited to, the implied warranties of merchantability and
   63.64 +fitness for a particular purpose or a warranty of non-infringement.
   63.65 +
   63.66 +\section{Requirements on modified works}
   63.67 +
   63.68 +All modified versions of documents covered by this license, including
   63.69 +translations, anthologies, compilations and partial documents, must
   63.70 +meet the following requirements:
   63.71 +
   63.72 +\begin{enumerate}
   63.73 +\item The modified version must be labeled as such.
   63.74 +\item The person making the modifications must be identified and the
   63.75 +  modifications dated.
   63.76 +\item Acknowledgement of the original author and publisher if
   63.77 +  applicable must be retained according to normal academic citation
   63.78 +  practices.
   63.79 +\item The location of the original unmodified document must be
   63.80 +  identified.
   63.81 +\item The original author's (or authors') name(s) may not be used to
   63.82 +  assert or imply endorsement of the resulting document without the
   63.83 +  original author's (or authors') permission.
   63.84 +\end{enumerate}
   63.85 +
   63.86 +\section{Good-practice recommendations}
   63.87 +
   63.88 +In addition to the requirements of this license, it is requested from
   63.89 +and strongly recommended of redistributors that:
   63.90 +
   63.91 +\begin{enumerate}
   63.92 +\item If you are distributing Open Publication works on hardcopy or
   63.93 +  CD-ROM, you provide email notification to the authors of your intent
   63.94 +  to redistribute at least thirty days before your manuscript or media
   63.95 +  freeze, to give the authors time to provide updated documents. This
   63.96 +  notification should describe modifications, if any, made to the
   63.97 +  document.
   63.98 +\item All substantive modifications (including deletions) be either
   63.99 +  clearly marked up in the document or else described in an attachment
  63.100 +  to the document.
  63.101 +\item Finally, while it is not mandatory under this license, it is
  63.102 +  considered good form to offer a free copy of any hardcopy and CD-ROM
  63.103 +  expression of an Open Publication-licensed work to its author(s).
  63.104 +\end{enumerate}
  63.105 +
  63.106 +\section{License options}
  63.107 +\label{sec:opl:options}
  63.108 +
  63.109 +The author(s) and/or publisher of an Open Publication-licensed
  63.110 +document may elect certain options by appending language to the
  63.111 +reference to or copy of the license. These options are considered part
  63.112 +of the license instance and must be included with the license (or its
  63.113 +incorporation by reference) in derived works.
  63.114 +
  63.115 +\begin{enumerate}[A]
  63.116 +\item To prohibit distribution of substantively modified versions
  63.117 +  without the explicit permission of the author(s). ``Substantive
  63.118 +  modification'' is defined as a change to the semantic content of the
  63.119 +  document, and excludes mere changes in format or typographical
  63.120 +  corrections.
  63.121 +
  63.122 +  To accomplish this, add the phrase ``Distribution of substantively
  63.123 +  modified versions of this document is prohibited without the
  63.124 +  explicit permission of the copyright holder.'' to the license
  63.125 +  reference or copy.
  63.126 +
  63.127 +\item To prohibit any publication of this work or derivative works in
  63.128 +  whole or in part in standard (paper) book form for commercial
  63.129 +  purposes is prohibited unless prior permission is obtained from the
  63.130 +  copyright holder.
  63.131 +
  63.132 +  To accomplish this, add the phrase ``Distribution of the work or
  63.133 +  derivative of the work in any standard (paper) book form is
  63.134 +  prohibited unless prior permission is obtained from the copyright
  63.135 +  holder.'' to the license reference or copy.
  63.136 +\end{enumerate}
  63.137 +
  63.138 +%%% Local Variables: 
  63.139 +%%% mode: latex
  63.140 +%%% TeX-master: "00book"
  63.141 +%%% End: 
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/fr/metadata.svg	Thu Feb 05 12:37:03 2009 +0100
    64.3 @@ -0,0 +1,328 @@
    64.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    64.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    64.6 +<svg
    64.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    64.8 +   xmlns:cc="http://web.resource.org/cc/"
    64.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   64.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   64.11 +   xmlns="http://www.w3.org/2000/svg"
   64.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   64.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   64.14 +   width="744.09448819"
   64.15 +   height="1052.3622047"
   64.16 +   id="svg2"
   64.17 +   sodipodi:version="0.32"
   64.18 +   inkscape:version="0.44.1"
   64.19 +   sodipodi:docname="metadata.svg"
   64.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en">
   64.21 +  <defs
   64.22 +     id="defs4">
   64.23 +    <marker
   64.24 +       inkscape:stockid="Arrow1Mend"
   64.25 +       orient="auto"
   64.26 +       refY="0.0"
   64.27 +       refX="0.0"
   64.28 +       id="Arrow1Mend"
   64.29 +       style="overflow:visible;">
   64.30 +      <path
   64.31 +         id="path2944"
   64.32 +         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 "
   64.33 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   64.34 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   64.35 +    </marker>
   64.36 +  </defs>
   64.37 +  <sodipodi:namedview
   64.38 +     id="base"
   64.39 +     pagecolor="#ffffff"
   64.40 +     bordercolor="#666666"
   64.41 +     borderopacity="1.0"
   64.42 +     gridtolerance="10000"
   64.43 +     guidetolerance="10"
   64.44 +     objecttolerance="10"
   64.45 +     inkscape:pageopacity="0.0"
   64.46 +     inkscape:pageshadow="2"
   64.47 +     inkscape:zoom="1.4"
   64.48 +     inkscape:cx="232.14286"
   64.49 +     inkscape:cy="490.68696"
   64.50 +     inkscape:document-units="px"
   64.51 +     inkscape:current-layer="layer1"
   64.52 +     inkscape:window-width="906"
   64.53 +     inkscape:window-height="620"
   64.54 +     inkscape:window-x="181"
   64.55 +     inkscape:window-y="58" />
   64.56 +  <metadata
   64.57 +     id="metadata7">
   64.58 +    <rdf:RDF>
   64.59 +      <cc:Work
   64.60 +         rdf:about="">
   64.61 +        <dc:format>image/svg+xml</dc:format>
   64.62 +        <dc:type
   64.63 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   64.64 +      </cc:Work>
   64.65 +    </rdf:RDF>
   64.66 +  </metadata>
   64.67 +  <g
   64.68 +     inkscape:label="Layer 1"
   64.69 +     inkscape:groupmode="layer"
   64.70 +     id="layer1">
   64.71 +    <path
   64.72 +       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"
   64.73 +       d="M 326.94646,467.18359 L 326.94646,510.98123"
   64.74 +       id="path1910"
   64.75 +       inkscape:connector-type="polyline"
   64.76 +       inkscape:connection-end="#rect2962"
   64.77 +       inkscape:connection-start="#rect2764" />
   64.78 +    <path
   64.79 +       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"
   64.80 +       d="M 326.94646,531.98123 L 326.94646,591.77887"
   64.81 +       id="path1912"
   64.82 +       inkscape:connector-type="polyline"
   64.83 +       inkscape:connection-start="#rect2962"
   64.84 +       inkscape:connection-end="#rect3000" />
   64.85 +    <path
   64.86 +       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"
   64.87 +       d="M 316.1622,531.98123 L 192.30212,652.57648"
   64.88 +       id="path1916"
   64.89 +       inkscape:connector-type="polyline"
   64.90 +       inkscape:connection-end="#rect3038"
   64.91 +       inkscape:connection-start="#rect2962" />
   64.92 +    <path
   64.93 +       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"
   64.94 +       d="M 254.23217,467.18359 L 254.23216,510.98123"
   64.95 +       id="path3088"
   64.96 +       inkscape:connector-type="polyline"
   64.97 +       inkscape:connection-start="#rect1872"
   64.98 +       inkscape:connection-end="#rect2960" />
   64.99 +    <path
  64.100 +       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"
  64.101 +       d="M 254.23215,531.98123 L 254.23215,591.77887"
  64.102 +       id="path3090"
  64.103 +       inkscape:connector-type="polyline"
  64.104 +       inkscape:connection-start="#rect2960"
  64.105 +       inkscape:connection-end="#rect2998" />
  64.106 +    <path
  64.107 +       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"
  64.108 +       d="M 248.84002,531.98123 L 186.90999,652.57648"
  64.109 +       id="path3092"
  64.110 +       inkscape:connector-type="polyline"
  64.111 +       inkscape:connection-start="#rect2960"
  64.112 +       inkscape:connection-end="#rect3038" />
  64.113 +    <rect
  64.114 +       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"
  64.115 +       id="rect1872"
  64.116 +       width="51.42857"
  64.117 +       height="20"
  64.118 +       x="228.51788"
  64.119 +       y="446.68359" />
  64.120 +    <rect
  64.121 +       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"
  64.122 +       id="rect2764"
  64.123 +       width="51.42857"
  64.124 +       height="20"
  64.125 +       x="301.23218"
  64.126 +       y="446.68359" />
  64.127 +    <rect
  64.128 +       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"
  64.129 +       id="rect2766"
  64.130 +       width="51.42857"
  64.131 +       height="20"
  64.132 +       x="155.80359"
  64.133 +       y="446.68359" />
  64.134 +    <rect
  64.135 +       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"
  64.136 +       id="rect2768"
  64.137 +       width="51.42857"
  64.138 +       height="20"
  64.139 +       x="83.089294"
  64.140 +       y="446.68359" />
  64.141 +    <path
  64.142 +       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"
  64.143 +       d="M 135.01786,456.68359 L 155.30359,456.68359"
  64.144 +       id="path2770"
  64.145 +       inkscape:connector-type="polyline"
  64.146 +       inkscape:connection-start="#rect2768"
  64.147 +       inkscape:connection-end="#rect2766" />
  64.148 +    <path
  64.149 +       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"
  64.150 +       d="M 207.73216,456.68359 L 228.01788,456.68359"
  64.151 +       id="path2772"
  64.152 +       inkscape:connector-type="polyline"
  64.153 +       inkscape:connection-start="#rect2766"
  64.154 +       inkscape:connection-end="#rect1872" />
  64.155 +    <path
  64.156 +       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"
  64.157 +       d="M 280.44645,456.68359 L 300.73218,456.68359"
  64.158 +       id="path2774"
  64.159 +       inkscape:connector-type="polyline"
  64.160 +       inkscape:connection-start="#rect1872"
  64.161 +       inkscape:connection-end="#rect2764" />
  64.162 +    <path
  64.163 +       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"
  64.164 +       d="M 62.303571,456.68359 L 82.589294,456.68359"
  64.165 +       id="path2778"
  64.166 +       inkscape:connector-type="polyline"
  64.167 +       inkscape:connection-end="#rect2768" />
  64.168 +    <rect
  64.169 +       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"
  64.170 +       id="rect2960"
  64.171 +       width="51.42857"
  64.172 +       height="20"
  64.173 +       x="228.51787"
  64.174 +       y="511.48123" />
  64.175 +    <rect
  64.176 +       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"
  64.177 +       id="rect2962"
  64.178 +       width="51.42857"
  64.179 +       height="20"
  64.180 +       x="301.23218"
  64.181 +       y="511.48123" />
  64.182 +    <rect
  64.183 +       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"
  64.184 +       id="rect2964"
  64.185 +       width="51.42857"
  64.186 +       height="20"
  64.187 +       x="155.80357"
  64.188 +       y="511.48123" />
  64.189 +    <rect
  64.190 +       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"
  64.191 +       id="rect2966"
  64.192 +       width="51.42857"
  64.193 +       height="20"
  64.194 +       x="83.089287"
  64.195 +       y="511.48123" />
  64.196 +    <path
  64.197 +       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"
  64.198 +       d="M 135.01786,521.48121 L 155.30359,521.48121"
  64.199 +       id="path2968"
  64.200 +       inkscape:connector-type="polyline" />
  64.201 +    <path
  64.202 +       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"
  64.203 +       d="M 207.73216,521.48121 L 228.01788,521.48121"
  64.204 +       id="path2970"
  64.205 +       inkscape:connector-type="polyline" />
  64.206 +    <path
  64.207 +       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"
  64.208 +       d="M 280.44645,521.48121 L 300.73218,521.48121"
  64.209 +       id="path2972"
  64.210 +       inkscape:connector-type="polyline" />
  64.211 +    <path
  64.212 +       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"
  64.213 +       d="M 62.30358,521.48121 L 82.5893,521.48121"
  64.214 +       id="path2974"
  64.215 +       inkscape:connector-type="polyline" />
  64.216 +    <rect
  64.217 +       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"
  64.218 +       id="rect2998"
  64.219 +       width="51.42857"
  64.220 +       height="20"
  64.221 +       x="228.51787"
  64.222 +       y="592.27887" />
  64.223 +    <rect
  64.224 +       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"
  64.225 +       id="rect3000"
  64.226 +       width="51.42857"
  64.227 +       height="20"
  64.228 +       x="301.23218"
  64.229 +       y="592.27887" />
  64.230 +    <rect
  64.231 +       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"
  64.232 +       id="rect3002"
  64.233 +       width="51.42857"
  64.234 +       height="20"
  64.235 +       x="155.80357"
  64.236 +       y="592.27887" />
  64.237 +    <rect
  64.238 +       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"
  64.239 +       id="rect3004"
  64.240 +       width="51.42857"
  64.241 +       height="20"
  64.242 +       x="83.089287"
  64.243 +       y="592.27887" />
  64.244 +    <path
  64.245 +       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"
  64.246 +       d="M 135.01786,602.27884 L 155.30359,602.27884"
  64.247 +       id="path3006"
  64.248 +       inkscape:connector-type="polyline" />
  64.249 +    <path
  64.250 +       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"
  64.251 +       d="M 207.73216,602.27884 L 228.01788,602.27884"
  64.252 +       id="path3008"
  64.253 +       inkscape:connector-type="polyline" />
  64.254 +    <path
  64.255 +       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"
  64.256 +       d="M 280.44645,602.27884 L 300.73218,602.27884"
  64.257 +       id="path3010"
  64.258 +       inkscape:connector-type="polyline" />
  64.259 +    <path
  64.260 +       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"
  64.261 +       d="M 62.30358,602.27884 L 82.5893,602.27884"
  64.262 +       id="path3012"
  64.263 +       inkscape:connector-type="polyline" />
  64.264 +    <rect
  64.265 +       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"
  64.266 +       id="rect3034"
  64.267 +       width="51.42857"
  64.268 +       height="20"
  64.269 +       x="228.51787"
  64.270 +       y="653.07648" />
  64.271 +    <rect
  64.272 +       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"
  64.273 +       id="rect3038"
  64.274 +       width="51.42857"
  64.275 +       height="20"
  64.276 +       x="155.80357"
  64.277 +       y="653.07648" />
  64.278 +    <rect
  64.279 +       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"
  64.280 +       id="rect3040"
  64.281 +       width="51.42857"
  64.282 +       height="20"
  64.283 +       x="83.089287"
  64.284 +       y="653.07648" />
  64.285 +    <path
  64.286 +       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"
  64.287 +       d="M 135.01786,663.07646 L 155.30359,663.07646"
  64.288 +       id="path3042"
  64.289 +       inkscape:connector-type="polyline" />
  64.290 +    <path
  64.291 +       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"
  64.292 +       d="M 207.73216,663.07646 L 228.01788,663.07646"
  64.293 +       id="path3044"
  64.294 +       inkscape:connector-type="polyline" />
  64.295 +    <path
  64.296 +       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"
  64.297 +       d="M 62.30358,663.07646 L 82.5893,663.07646"
  64.298 +       id="path3048"
  64.299 +       inkscape:connector-type="polyline" />
  64.300 +    <text
  64.301 +       xml:space="preserve"
  64.302 +       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"
  64.303 +       x="82.072548"
  64.304 +       y="432.64789"
  64.305 +       id="text3094"><tspan
  64.306 +         sodipodi:role="line"
  64.307 +         id="tspan3096"
  64.308 +         x="82.072548"
  64.309 +         y="432.64789">Changelog</tspan></text>
  64.310 +    <text
  64.311 +       xml:space="preserve"
  64.312 +       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"
  64.313 +       x="82.306923"
  64.314 +       y="498.97327"
  64.315 +       id="text3098"><tspan
  64.316 +         sodipodi:role="line"
  64.317 +         id="tspan3100"
  64.318 +         x="82.306923"
  64.319 +         y="498.97327">Manifest</tspan></text>
  64.320 +    <text
  64.321 +       xml:space="preserve"
  64.322 +       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"
  64.323 +       x="82.14286"
  64.324 +       y="580.08569"
  64.325 +       id="text3102"><tspan
  64.326 +         sodipodi:role="line"
  64.327 +         id="tspan3104"
  64.328 +         x="82.14286"
  64.329 +         y="580.08569">Filelogs</tspan></text>
  64.330 +  </g>
  64.331 +</svg>
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/fr/mq-collab.tex	Thu Feb 05 12:37:03 2009 +0100
    65.3 @@ -0,0 +1,393 @@
    65.4 +\chapter{Advanced uses of Mercurial Queues}
    65.5 +\label{chap:mq-collab}
    65.6 +
    65.7 +While it's easy to pick up straightforward uses of Mercurial Queues,
    65.8 +use of a little discipline and some of MQ's less frequently used
    65.9 +capabilities makes it possible to work in complicated development
   65.10 +environments.
   65.11 +
   65.12 +In this chapter, I will use as an example a technique I have used to
   65.13 +manage the development of an Infiniband device driver for the Linux
   65.14 +kernel.  The driver in question is large (at least as drivers go),
   65.15 +with 25,000 lines of code spread across 35 source files.  It is
   65.16 +maintained by a small team of developers.
   65.17 +
   65.18 +While much of the material in this chapter is specific to Linux, the
   65.19 +same principles apply to any code base for which you're not the
   65.20 +primary owner, and upon which you need to do a lot of development.
   65.21 +
   65.22 +\section{The problem of many targets}
   65.23 +
   65.24 +The Linux kernel changes rapidly, and has never been internally
   65.25 +stable; developers frequently make drastic changes between releases.
   65.26 +This means that a version of the driver that works well with a
   65.27 +particular released version of the kernel will not even \emph{compile}
   65.28 +correctly against, typically, any other version.
   65.29 +
   65.30 +To maintain a driver, we have to keep a number of distinct versions of
   65.31 +Linux in mind.
   65.32 +\begin{itemize}
   65.33 +\item One target is the main Linux kernel development tree.
   65.34 +  Maintenance of the code is in this case partly shared by other
   65.35 +  developers in the kernel community, who make ``drive-by''
   65.36 +  modifications to the driver as they develop and refine kernel
   65.37 +  subsystems.
   65.38 +\item We also maintain a number of ``backports'' to older versions of
   65.39 +  the Linux kernel, to support the needs of customers who are running
   65.40 +  older Linux distributions that do not incorporate our drivers.  (To
   65.41 +  \emph{backport} a piece of code is to modify it to work in an older
   65.42 +  version of its target environment than the version it was developed
   65.43 +  for.)
   65.44 +\item Finally, we make software releases on a schedule that is
   65.45 +  necessarily not aligned with those used by Linux distributors and
   65.46 +  kernel developers, so that we can deliver new features to customers
   65.47 +  without forcing them to upgrade their entire kernels or
   65.48 +  distributions.
   65.49 +\end{itemize}
   65.50 +
   65.51 +\subsection{Tempting approaches that don't work well}
   65.52 +
   65.53 +There are two ``standard'' ways to maintain a piece of software that
   65.54 +has to target many different environments.
   65.55 +
   65.56 +The first is to maintain a number of branches, each intended for a
   65.57 +single target.  The trouble with this approach is that you must
   65.58 +maintain iron discipline in the flow of changes between repositories.
   65.59 +A new feature or bug fix must start life in a ``pristine'' repository,
   65.60 +then percolate out to every backport repository.  Backport changes are
   65.61 +more limited in the branches they should propagate to; a backport
   65.62 +change that is applied to a branch where it doesn't belong will
   65.63 +probably stop the driver from compiling.
   65.64 +
   65.65 +The second is to maintain a single source tree filled with conditional
   65.66 +statements that turn chunks of code on or off depending on the
   65.67 +intended target.  Because these ``ifdefs'' are not allowed in the
   65.68 +Linux kernel tree, a manual or automatic process must be followed to
   65.69 +strip them out and yield a clean tree.  A code base maintained in this
   65.70 +fashion rapidly becomes a rat's nest of conditional blocks that are
   65.71 +difficult to understand and maintain.
   65.72 +
   65.73 +Neither of these approaches is well suited to a situation where you
   65.74 +don't ``own'' the canonical copy of a source tree.  In the case of a
   65.75 +Linux driver that is distributed with the standard kernel, Linus's
   65.76 +tree contains the copy of the code that will be treated by the world
   65.77 +as canonical.  The upstream version of ``my'' driver can be modified
   65.78 +by people I don't know, without me even finding out about it until
   65.79 +after the changes show up in Linus's tree.  
   65.80 +
   65.81 +These approaches have the added weakness of making it difficult to
   65.82 +generate well-formed patches to submit upstream.
   65.83 +
   65.84 +In principle, Mercurial Queues seems like a good candidate to manage a
   65.85 +development scenario such as the above.  While this is indeed the
   65.86 +case, MQ contains a few added features that make the job more
   65.87 +pleasant.
   65.88 +
   65.89 +\section{Conditionally applying patches with 
   65.90 +  guards}
   65.91 +
   65.92 +Perhaps the best way to maintain sanity with so many targets is to be
   65.93 +able to choose specific patches to apply for a given situation.  MQ
   65.94 +provides a feature called ``guards'' (which originates with quilt's
   65.95 +\texttt{guards} command) that does just this.  To start off, let's
   65.96 +create a simple repository for experimenting in.
   65.97 +\interaction{mq.guards.init}
   65.98 +This gives us a tiny repository that contains two patches that don't
   65.99 +have any dependencies on each other, because they touch different files.
  65.100 +
  65.101 +The idea behind conditional application is that you can ``tag'' a
  65.102 +patch with a \emph{guard}, which is simply a text string of your
  65.103 +choosing, then tell MQ to select specific guards to use when applying
  65.104 +patches.  MQ will then either apply, or skip over, a guarded patch,
  65.105 +depending on the guards that you have selected.
  65.106 +
  65.107 +A patch can have an arbitrary number of guards;
  65.108 +each one is \emph{positive} (``apply this patch if this guard is
  65.109 +selected'') or \emph{negative} (``skip this patch if this guard is
  65.110 +selected'').  A patch with no guards is always applied.
  65.111 +
  65.112 +\section{Controlling the guards on a patch}
  65.113 +
  65.114 +The \hgxcmd{mq}{qguard} command lets you determine which guards should
  65.115 +apply to a patch, or display the guards that are already in effect.
  65.116 +Without any arguments, it displays the guards on the current topmost
  65.117 +patch.
  65.118 +\interaction{mq.guards.qguard}
  65.119 +To set a positive guard on a patch, prefix the name of the guard with
  65.120 +a ``\texttt{+}''.
  65.121 +\interaction{mq.guards.qguard.pos}
  65.122 +To set a negative guard on a patch, prefix the name of the guard with
  65.123 +a ``\texttt{-}''.
  65.124 +\interaction{mq.guards.qguard.neg}
  65.125 +
  65.126 +\begin{note}
  65.127 +  The \hgxcmd{mq}{qguard} command \emph{sets} the guards on a patch; it
  65.128 +  doesn't \emph{modify} them.  What this means is that if you run
  65.129 +  \hgcmdargs{qguard}{+a +b} on a patch, then \hgcmdargs{qguard}{+c} on
  65.130 +  the same patch, the \emph{only} guard that will be set on it
  65.131 +  afterwards is \texttt{+c}.
  65.132 +\end{note}
  65.133 +
  65.134 +Mercurial stores guards in the \sfilename{series} file; the form in
  65.135 +which they are stored is easy both to understand and to edit by hand.
  65.136 +(In other words, you don't have to use the \hgxcmd{mq}{qguard} command if
  65.137 +you don't want to; it's okay to simply edit the \sfilename{series}
  65.138 +file.)
  65.139 +\interaction{mq.guards.series}
  65.140 +
  65.141 +\section{Selecting the guards to use}
  65.142 +
  65.143 +The \hgxcmd{mq}{qselect} command determines which guards are active at a
  65.144 +given time.  The effect of this is to determine which patches MQ will
  65.145 +apply the next time you run \hgxcmd{mq}{qpush}.  It has no other effect; in
  65.146 +particular, it doesn't do anything to patches that are already
  65.147 +applied.
  65.148 +
  65.149 +With no arguments, the \hgxcmd{mq}{qselect} command lists the guards
  65.150 +currently in effect, one per line of output.  Each argument is treated
  65.151 +as the name of a guard to apply.
  65.152 +\interaction{mq.guards.qselect.foo}
  65.153 +In case you're interested, the currently selected guards are stored in
  65.154 +the \sfilename{guards} file.
  65.155 +\interaction{mq.guards.qselect.cat}
  65.156 +We can see the effect the selected guards have when we run
  65.157 +\hgxcmd{mq}{qpush}.
  65.158 +\interaction{mq.guards.qselect.qpush}
  65.159 +
  65.160 +A guard cannot start with a ``\texttt{+}'' or ``\texttt{-}''
  65.161 +character.  The name of a guard must not contain white space, but most
  65.162 +other characters are acceptable.  If you try to use a guard with an
  65.163 +invalid name, MQ will complain:
  65.164 +\interaction{mq.guards.qselect.error} 
  65.165 +Changing the selected guards changes the patches that are applied.
  65.166 +\interaction{mq.guards.qselect.quux} 
  65.167 +You can see in the example below that negative guards take precedence
  65.168 +over positive guards.
  65.169 +\interaction{mq.guards.qselect.foobar}
  65.170 +
  65.171 +\section{MQ's rules for applying patches}
  65.172 +
  65.173 +The rules that MQ uses when deciding whether to apply a patch
  65.174 +are as follows.
  65.175 +\begin{itemize}
  65.176 +\item A patch that has no guards is always applied.
  65.177 +\item If the patch has any negative guard that matches any currently
  65.178 +  selected guard, the patch is skipped.
  65.179 +\item If the patch has any positive guard that matches any currently
  65.180 +  selected guard, the patch is applied.
  65.181 +\item If the patch has positive or negative guards, but none matches
  65.182 +  any currently selected guard, the patch is skipped.
  65.183 +\end{itemize}
  65.184 +
  65.185 +\section{Trimming the work environment}
  65.186 +
  65.187 +In working on the device driver I mentioned earlier, I don't apply the
  65.188 +patches to a normal Linux kernel tree.  Instead, I use a repository
  65.189 +that contains only a snapshot of the source files and headers that are
  65.190 +relevant to Infiniband development.  This repository is~1\% the size
  65.191 +of a kernel repository, so it's easier to work with.
  65.192 +
  65.193 +I then choose a ``base'' version on top of which the patches are
  65.194 +applied.  This is a snapshot of the Linux kernel tree as of a revision
  65.195 +of my choosing.  When I take the snapshot, I record the changeset ID
  65.196 +from the kernel repository in the commit message.  Since the snapshot
  65.197 +preserves the ``shape'' and content of the relevant parts of the
  65.198 +kernel tree, I can apply my patches on top of either my tiny
  65.199 +repository or a normal kernel tree.
  65.200 +
  65.201 +Normally, the base tree atop which the patches apply should be a
  65.202 +snapshot of a very recent upstream tree.  This best facilitates the
  65.203 +development of patches that can easily be submitted upstream with few
  65.204 +or no modifications.
  65.205 +
  65.206 +\section{Dividing up the \sfilename{series} file}
  65.207 +
  65.208 +I categorise the patches in the \sfilename{series} file into a number
  65.209 +of logical groups.  Each section of like patches begins with a block
  65.210 +of comments that describes the purpose of the patches that follow.
  65.211 +
  65.212 +The sequence of patch groups that I maintain follows.  The ordering of
  65.213 +these groups is important; I'll describe why after I introduce the
  65.214 +groups.
  65.215 +\begin{itemize}
  65.216 +\item The ``accepted'' group.  Patches that the development team has
  65.217 +  submitted to the maintainer of the Infiniband subsystem, and which
  65.218 +  he has accepted, but which are not present in the snapshot that the
  65.219 +  tiny repository is based on.  These are ``read only'' patches,
  65.220 +  present only to transform the tree into a similar state as it is in
  65.221 +  the upstream maintainer's repository.
  65.222 +\item The ``rework'' group.  Patches that I have submitted, but that
  65.223 +  the upstream maintainer has requested modifications to before he
  65.224 +  will accept them.
  65.225 +\item The ``pending'' group.  Patches that I have not yet submitted to
  65.226 +  the upstream maintainer, but which we have finished working on.
  65.227 +  These will be ``read only'' for a while.  If the upstream maintainer
  65.228 +  accepts them upon submission, I'll move them to the end of the
  65.229 +  ``accepted'' group.  If he requests that I modify any, I'll move
  65.230 +  them to the beginning of the ``rework'' group.
  65.231 +\item The ``in progress'' group.  Patches that are actively being
  65.232 +  developed, and should not be submitted anywhere yet.
  65.233 +\item The ``backport'' group.  Patches that adapt the source tree to
  65.234 +  older versions of the kernel tree.
  65.235 +\item The ``do not ship'' group.  Patches that for some reason should
  65.236 +  never be submitted upstream.  For example, one such patch might
  65.237 +  change embedded driver identification strings to make it easier to
  65.238 +  distinguish, in the field, between an out-of-tree version of the
  65.239 +  driver and a version shipped by a distribution vendor.
  65.240 +\end{itemize}
  65.241 +
  65.242 +Now to return to the reasons for ordering groups of patches in this
  65.243 +way.  We would like the lowest patches in the stack to be as stable as
  65.244 +possible, so that we will not need to rework higher patches due to
  65.245 +changes in context.  Putting patches that will never be changed first
  65.246 +in the \sfilename{series} file serves this purpose.
  65.247 +
  65.248 +We would also like the patches that we know we'll need to modify to be
  65.249 +applied on top of a source tree that resembles the upstream tree as
  65.250 +closely as possible.  This is why we keep accepted patches around for
  65.251 +a while.
  65.252 +
  65.253 +The ``backport'' and ``do not ship'' patches float at the end of the
  65.254 +\sfilename{series} file.  The backport patches must be applied on top
  65.255 +of all other patches, and the ``do not ship'' patches might as well
  65.256 +stay out of harm's way.
  65.257 +
  65.258 +\section{Maintaining the patch series}
  65.259 +
  65.260 +In my work, I use a number of guards to control which patches are to
  65.261 +be applied.
  65.262 +
  65.263 +\begin{itemize}
  65.264 +\item ``Accepted'' patches are guarded with \texttt{accepted}.  I
  65.265 +  enable this guard most of the time.  When I'm applying the patches
  65.266 +  on top of a tree where the patches are already present, I can turn
  65.267 +  this patch off, and the patches that follow it will apply cleanly.
  65.268 +\item Patches that are ``finished'', but not yet submitted, have no
  65.269 +  guards.  If I'm applying the patch stack to a copy of the upstream
  65.270 +  tree, I don't need to enable any guards in order to get a reasonably
  65.271 +  safe source tree.
  65.272 +\item Those patches that need reworking before being resubmitted are
  65.273 +  guarded with \texttt{rework}.
  65.274 +\item For those patches that are still under development, I use
  65.275 +  \texttt{devel}.
  65.276 +\item A backport patch may have several guards, one for each version
  65.277 +  of the kernel to which it applies.  For example, a patch that
  65.278 +  backports a piece of code to~2.6.9 will have a~\texttt{2.6.9} guard.
  65.279 +\end{itemize}
  65.280 +This variety of guards gives me considerable flexibility in
  65.281 +determining what kind of source tree I want to end up with.  For most
  65.282 +situations, the selection of appropriate guards is automated during
  65.283 +the build process, but I can manually tune the guards to use for less
  65.284 +common circumstances.
  65.285 +
  65.286 +\subsection{The art of writing backport patches}
  65.287 +
  65.288 +Using MQ, writing a backport patch is a simple process.  All such a
  65.289 +patch has to do is modify a piece of code that uses a kernel feature
  65.290 +not present in the older version of the kernel, so that the driver
  65.291 +continues to work correctly under that older version.
  65.292 +
  65.293 +A useful goal when writing a good backport patch is to make your code
  65.294 +look as if it was written for the older version of the kernel you're
  65.295 +targeting.  The less obtrusive the patch, the easier it will be to
  65.296 +understand and maintain.  If you're writing a collection of backport
  65.297 +patches to avoid the ``rat's nest'' effect of lots of
  65.298 +\texttt{\#ifdef}s (hunks of source code that are only used
  65.299 +conditionally) in your code, don't introduce version-dependent
  65.300 +\texttt{\#ifdef}s into the patches.  Instead, write several patches,
  65.301 +each of which makes unconditional changes, and control their
  65.302 +application using guards.
  65.303 +
  65.304 +There are two reasons to divide backport patches into a distinct
  65.305 +group, away from the ``regular'' patches whose effects they modify.
  65.306 +The first is that intermingling the two makes it more difficult to use
  65.307 +a tool like the \hgext{patchbomb} extension to automate the process of
  65.308 +submitting the patches to an upstream maintainer.  The second is that
  65.309 +a backport patch could perturb the context in which a subsequent
  65.310 +regular patch is applied, making it impossible to apply the regular
  65.311 +patch cleanly \emph{without} the earlier backport patch already being
  65.312 +applied.
  65.313 +
  65.314 +\section{Useful tips for developing with MQ}
  65.315 +
  65.316 +\subsection{Organising patches in directories}
  65.317 +
  65.318 +If you're working on a substantial project with MQ, it's not difficult
  65.319 +to accumulate a large number of patches.  For example, I have one
  65.320 +patch repository that contains over 250 patches.
  65.321 +
  65.322 +If you can group these patches into separate logical categories, you
  65.323 +can if you like store them in different directories; MQ has no
  65.324 +problems with patch names that contain path separators.
  65.325 +
  65.326 +\subsection{Viewing the history of a patch}
  65.327 +\label{mq-collab:tips:interdiff}
  65.328 +
  65.329 +If you're developing a set of patches over a long time, it's a good
  65.330 +idea to maintain them in a repository, as discussed in
  65.331 +section~\ref{sec:mq:repo}.  If you do so, you'll quickly discover that
  65.332 +using the \hgcmd{diff} command to look at the history of changes to a
  65.333 +patch is unworkable.  This is in part because you're looking at the
  65.334 +second derivative of the real code (a diff of a diff), but also
  65.335 +because MQ adds noise to the process by modifying time stamps and
  65.336 +directory names when it updates a patch.
  65.337 +
  65.338 +However, you can use the \hgext{extdiff} extension, which is bundled
  65.339 +with Mercurial, to turn a diff of two versions of a patch into
  65.340 +something readable.  To do this, you will need a third-party package
  65.341 +called \package{patchutils}~\cite{web:patchutils}.  This provides a
  65.342 +command named \command{interdiff}, which shows the differences between
  65.343 +two diffs as a diff.  Used on two versions of the same diff, it
  65.344 +generates a diff that represents the diff from the first to the second
  65.345 +version.
  65.346 +
  65.347 +You can enable the \hgext{extdiff} extension in the usual way, by
  65.348 +adding a line to the \rcsection{extensions} section of your \hgrc.
  65.349 +\begin{codesample2}
  65.350 +  [extensions]
  65.351 +  extdiff =
  65.352 +\end{codesample2}
  65.353 +The \command{interdiff} command expects to be passed the names of two
  65.354 +files, but the \hgext{extdiff} extension passes the program it runs a
  65.355 +pair of directories, each of which can contain an arbitrary number of
  65.356 +files.  We thus need a small program that will run \command{interdiff}
  65.357 +on each pair of files in these two directories.  This program is
  65.358 +available as \sfilename{hg-interdiff} in the \dirname{examples}
  65.359 +directory of the source code repository that accompanies this book.
  65.360 +\excode{hg-interdiff}
  65.361 +
  65.362 +With the \sfilename{hg-interdiff} program in your shell's search path,
  65.363 +you can run it as follows, from inside an MQ patch directory:
  65.364 +\begin{codesample2}
  65.365 +  hg extdiff -p hg-interdiff -r A:B my-change.patch
  65.366 +\end{codesample2}
  65.367 +Since you'll probably want to use this long-winded command a lot, you
  65.368 +can get \hgext{hgext} to make it available as a normal Mercurial
  65.369 +command, again by editing your \hgrc.
  65.370 +\begin{codesample2}
  65.371 +  [extdiff]
  65.372 +  cmd.interdiff = hg-interdiff
  65.373 +\end{codesample2}
  65.374 +This directs \hgext{hgext} to make an \texttt{interdiff} command
  65.375 +available, so you can now shorten the previous invocation of
  65.376 +\hgxcmd{extdiff}{extdiff} to something a little more wieldy.
  65.377 +\begin{codesample2}
  65.378 +  hg interdiff -r A:B my-change.patch
  65.379 +\end{codesample2}
  65.380 +
  65.381 +\begin{note}
  65.382 +  The \command{interdiff} command works well only if the underlying
  65.383 +  files against which versions of a patch are generated remain the
  65.384 +  same.  If you create a patch, modify the underlying files, and then
  65.385 +  regenerate the patch, \command{interdiff} may not produce useful
  65.386 +  output.
  65.387 +\end{note}
  65.388 +
  65.389 +The \hgext{extdiff} extension is useful for more than merely improving
  65.390 +the presentation of MQ~patches.  To read more about it, go to
  65.391 +section~\ref{sec:hgext:extdiff}.
  65.392 +
  65.393 +%%% Local Variables: 
  65.394 +%%% mode: latex
  65.395 +%%% TeX-master: "00book"
  65.396 +%%% End: 
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/fr/mq-ref.tex	Thu Feb 05 12:37:03 2009 +0100
    66.3 @@ -0,0 +1,349 @@
    66.4 +\chapter{Mercurial Queues reference}
    66.5 +\label{chap:mqref}
    66.6 +
    66.7 +\section{MQ command reference}
    66.8 +\label{sec:mqref:cmdref}
    66.9 +
   66.10 +For an overview of the commands provided by MQ, use the command
   66.11 +\hgcmdargs{help}{mq}.
   66.12 +
   66.13 +\subsection{\hgxcmd{mq}{qapplied}---print applied patches}
   66.14 +
   66.15 +The \hgxcmd{mq}{qapplied} command prints the current stack of applied
   66.16 +patches.  Patches are printed in oldest-to-newest order, so the last
   66.17 +patch in the list is the ``top'' patch.
   66.18 +
   66.19 +\subsection{\hgxcmd{mq}{qcommit}---commit changes in the queue repository}
   66.20 +
   66.21 +The \hgxcmd{mq}{qcommit} command commits any outstanding changes in the
   66.22 +\sdirname{.hg/patches} repository.  This command only works if the
   66.23 +\sdirname{.hg/patches} directory is a repository, i.e.~you created the
   66.24 +directory using \hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} or ran
   66.25 +\hgcmd{init} in the directory after running \hgxcmd{mq}{qinit}.
   66.26 +
   66.27 +This command is shorthand for \hgcmdargs{commit}{--cwd .hg/patches}.
   66.28 +
   66.29 +\subsection{\hgxcmd{mq}{qdelete}---delete a patch from the
   66.30 +  \sfilename{series} file}
   66.31 +
   66.32 +The \hgxcmd{mq}{qdelete} command removes the entry for a patch from the
   66.33 +\sfilename{series} file in the \sdirname{.hg/patches} directory.  It
   66.34 +does not pop the patch if the patch is already applied.  By default,
   66.35 +it does not delete the patch file; use the \hgxopt{mq}{qdel}{-f} option to
   66.36 +do that.
   66.37 +
   66.38 +Options:
   66.39 +\begin{itemize}
   66.40 +\item[\hgxopt{mq}{qdel}{-f}] Delete the patch file.
   66.41 +\end{itemize}
   66.42 +
   66.43 +\subsection{\hgxcmd{mq}{qdiff}---print a diff of the topmost applied patch}
   66.44 +
   66.45 +The \hgxcmd{mq}{qdiff} command prints a diff of the topmost applied patch.
   66.46 +It is equivalent to \hgcmdargs{diff}{-r-2:-1}.
   66.47 +
   66.48 +\subsection{\hgxcmd{mq}{qfold}---merge (``fold'') several patches into one}
   66.49 +
   66.50 +The \hgxcmd{mq}{qfold} command merges multiple patches into the topmost
   66.51 +applied patch, so that the topmost applied patch makes the union of
   66.52 +all of the changes in the patches in question.
   66.53 +
   66.54 +The patches to fold must not be applied; \hgxcmd{mq}{qfold} will exit with
   66.55 +an error if any is.  The order in which patches are folded is
   66.56 +significant; \hgcmdargs{qfold}{a b} means ``apply the current topmost
   66.57 +patch, followed by \texttt{a}, followed by \texttt{b}''.
   66.58 +
   66.59 +The comments from the folded patches are appended to the comments of
   66.60 +the destination patch, with each block of comments separated by three
   66.61 +asterisk (``\texttt{*}'') characters.  Use the \hgxopt{mq}{qfold}{-e}
   66.62 +option to edit the commit message for the combined patch/changeset
   66.63 +after the folding has completed.
   66.64 +
   66.65 +Options:
   66.66 +\begin{itemize}
   66.67 +\item[\hgxopt{mq}{qfold}{-e}] Edit the commit message and patch description
   66.68 +  for the newly folded patch.
   66.69 +\item[\hgxopt{mq}{qfold}{-l}] Use the contents of the given file as the new
   66.70 +  commit message and patch description for the folded patch.
   66.71 +\item[\hgxopt{mq}{qfold}{-m}] Use the given text as the new commit message
   66.72 +  and patch description for the folded patch.
   66.73 +\end{itemize}
   66.74 +
   66.75 +\subsection{\hgxcmd{mq}{qheader}---display the header/description of a patch}
   66.76 +
   66.77 +The \hgxcmd{mq}{qheader} command prints the header, or description, of a
   66.78 +patch.  By default, it prints the header of the topmost applied patch.
   66.79 +Given an argument, it prints the header of the named patch.
   66.80 +
   66.81 +\subsection{\hgxcmd{mq}{qimport}---import a third-party patch into the queue}
   66.82 +
   66.83 +The \hgxcmd{mq}{qimport} command adds an entry for an external patch to the
   66.84 +\sfilename{series} file, and copies the patch into the
   66.85 +\sdirname{.hg/patches} directory.  It adds the entry immediately after
   66.86 +the topmost applied patch, but does not push the patch.
   66.87 +
   66.88 +If the \sdirname{.hg/patches} directory is a repository,
   66.89 +\hgxcmd{mq}{qimport} automatically does an \hgcmd{add} of the imported
   66.90 +patch.
   66.91 +
   66.92 +\subsection{\hgxcmd{mq}{qinit}---prepare a repository to work with MQ}
   66.93 +
   66.94 +The \hgxcmd{mq}{qinit} command prepares a repository to work with MQ.  It
   66.95 +creates a directory called \sdirname{.hg/patches}.
   66.96 +
   66.97 +Options:
   66.98 +\begin{itemize}
   66.99 +\item[\hgxopt{mq}{qinit}{-c}] Create \sdirname{.hg/patches} as a repository
  66.100 +  in its own right.  Also creates a \sfilename{.hgignore} file that
  66.101 +  will ignore the \sfilename{status} file.
  66.102 +\end{itemize}
  66.103 +
  66.104 +When the \sdirname{.hg/patches} directory is a repository, the
  66.105 +\hgxcmd{mq}{qimport} and \hgxcmd{mq}{qnew} commands automatically \hgcmd{add}
  66.106 +new patches.
  66.107 +
  66.108 +\subsection{\hgxcmd{mq}{qnew}---create a new patch}
  66.109 +
  66.110 +The \hgxcmd{mq}{qnew} command creates a new patch.  It takes one mandatory
  66.111 +argument, the name to use for the patch file.  The newly created patch
  66.112 +is created empty by default.  It is added to the \sfilename{series}
  66.113 +file after the current topmost applied patch, and is immediately
  66.114 +pushed on top of that patch.
  66.115 +
  66.116 +If \hgxcmd{mq}{qnew} finds modified files in the working directory, it will
  66.117 +refuse to create a new patch unless the \hgxopt{mq}{qnew}{-f} option is
  66.118 +used (see below).  This behaviour allows you to \hgxcmd{mq}{qrefresh} your
  66.119 +topmost applied patch before you apply a new patch on top of it.
  66.120 +
  66.121 +Options:
  66.122 +\begin{itemize}
  66.123 +\item[\hgxopt{mq}{qnew}{-f}] Create a new patch if the contents of the
  66.124 +  working directory are modified.  Any outstanding modifications are
  66.125 +  added to the newly created patch, so after this command completes,
  66.126 +  the working directory will no longer be modified.
  66.127 +\item[\hgxopt{mq}{qnew}{-m}] Use the given text as the commit message.
  66.128 +  This text will be stored at the beginning of the patch file, before
  66.129 +  the patch data.
  66.130 +\end{itemize}
  66.131 +
  66.132 +\subsection{\hgxcmd{mq}{qnext}---print the name of the next patch}
  66.133 +
  66.134 +The \hgxcmd{mq}{qnext} command prints the name name of the next patch in
  66.135 +the \sfilename{series} file after the topmost applied patch.  This
  66.136 +patch will become the topmost applied patch if you run \hgxcmd{mq}{qpush}.
  66.137 +
  66.138 +\subsection{\hgxcmd{mq}{qpop}---pop patches off the stack}
  66.139 +
  66.140 +The \hgxcmd{mq}{qpop} command removes applied patches from the top of the
  66.141 +stack of applied patches.  By default, it removes only one patch.
  66.142 +
  66.143 +This command removes the changesets that represent the popped patches
  66.144 +from the repository, and updates the working directory to undo the
  66.145 +effects of the patches.
  66.146 +
  66.147 +This command takes an optional argument, which it uses as the name or
  66.148 +index of the patch to pop to.  If given a name, it will pop patches
  66.149 +until the named patch is the topmost applied patch.  If given a
  66.150 +number, \hgxcmd{mq}{qpop} treats the number as an index into the entries in
  66.151 +the series file, counting from zero (empty lines and lines containing
  66.152 +only comments do not count).  It pops patches until the patch
  66.153 +identified by the given index is the topmost applied patch.
  66.154 +
  66.155 +The \hgxcmd{mq}{qpop} command does not read or write patches or the
  66.156 +\sfilename{series} file.  It is thus safe to \hgxcmd{mq}{qpop} a patch that
  66.157 +you have removed from the \sfilename{series} file, or a patch that you
  66.158 +have renamed or deleted entirely.  In the latter two cases, use the
  66.159 +name of the patch as it was when you applied it.
  66.160 +
  66.161 +By default, the \hgxcmd{mq}{qpop} command will not pop any patches if the
  66.162 +working directory has been modified.  You can override this behaviour
  66.163 +using the \hgxopt{mq}{qpop}{-f} option, which reverts all modifications in
  66.164 +the working directory.
  66.165 +
  66.166 +Options:
  66.167 +\begin{itemize}
  66.168 +\item[\hgxopt{mq}{qpop}{-a}] Pop all applied patches.  This returns the
  66.169 +  repository to its state before you applied any patches.
  66.170 +\item[\hgxopt{mq}{qpop}{-f}] Forcibly revert any modifications to the
  66.171 +  working directory when popping.
  66.172 +\item[\hgxopt{mq}{qpop}{-n}] Pop a patch from the named queue.
  66.173 +\end{itemize}
  66.174 +
  66.175 +The \hgxcmd{mq}{qpop} command removes one line from the end of the
  66.176 +\sfilename{status} file for each patch that it pops.
  66.177 +
  66.178 +\subsection{\hgxcmd{mq}{qprev}---print the name of the previous patch}
  66.179 +
  66.180 +The \hgxcmd{mq}{qprev} command prints the name of the patch in the
  66.181 +\sfilename{series} file that comes before the topmost applied patch.
  66.182 +This will become the topmost applied patch if you run \hgxcmd{mq}{qpop}.
  66.183 +
  66.184 +\subsection{\hgxcmd{mq}{qpush}---push patches onto the stack}
  66.185 +\label{sec:mqref:cmd:qpush}
  66.186 +
  66.187 +The \hgxcmd{mq}{qpush} command adds patches onto the applied stack.  By
  66.188 +default, it adds only one patch.
  66.189 +
  66.190 +This command creates a new changeset to represent each applied patch,
  66.191 +and updates the working directory to apply the effects of the patches.
  66.192 +
  66.193 +The default data used when creating a changeset are as follows:
  66.194 +\begin{itemize}
  66.195 +\item The commit date and time zone are the current date and time
  66.196 +  zone.  Because these data are used to compute the identity of a
  66.197 +  changeset, this means that if you \hgxcmd{mq}{qpop} a patch and
  66.198 +  \hgxcmd{mq}{qpush} it again, the changeset that you push will have a
  66.199 +  different identity than the changeset you popped.
  66.200 +\item The author is the same as the default used by the \hgcmd{commit}
  66.201 +  command.
  66.202 +\item The commit message is any text from the patch file that comes
  66.203 +  before the first diff header.  If there is no such text, a default
  66.204 +  commit message is used that identifies the name of the patch.
  66.205 +\end{itemize}
  66.206 +If a patch contains a Mercurial patch header (XXX add link), the
  66.207 +information in the patch header overrides these defaults.
  66.208 +
  66.209 +Options:
  66.210 +\begin{itemize}
  66.211 +\item[\hgxopt{mq}{qpush}{-a}] Push all unapplied patches from the
  66.212 +  \sfilename{series} file until there are none left to push.
  66.213 +\item[\hgxopt{mq}{qpush}{-l}] Add the name of the patch to the end
  66.214 +  of the commit message.
  66.215 +\item[\hgxopt{mq}{qpush}{-m}] If a patch fails to apply cleanly, use the
  66.216 +  entry for the patch in another saved queue to compute the parameters
  66.217 +  for a three-way merge, and perform a three-way merge using the
  66.218 +  normal Mercurial merge machinery.  Use the resolution of the merge
  66.219 +  as the new patch content.
  66.220 +\item[\hgxopt{mq}{qpush}{-n}] Use the named queue if merging while pushing.
  66.221 +\end{itemize}
  66.222 +
  66.223 +The \hgxcmd{mq}{qpush} command reads, but does not modify, the
  66.224 +\sfilename{series} file.  It appends one line to the \hgcmd{status}
  66.225 +file for each patch that it pushes.
  66.226 +
  66.227 +\subsection{\hgxcmd{mq}{qrefresh}---update the topmost applied patch}
  66.228 +
  66.229 +The \hgxcmd{mq}{qrefresh} command updates the topmost applied patch.  It
  66.230 +modifies the patch, removes the old changeset that represented the
  66.231 +patch, and creates a new changeset to represent the modified patch.
  66.232 +
  66.233 +The \hgxcmd{mq}{qrefresh} command looks for the following modifications:
  66.234 +\begin{itemize}
  66.235 +\item Changes to the commit message, i.e.~the text before the first
  66.236 +  diff header in the patch file, are reflected in the new changeset
  66.237 +  that represents the patch.
  66.238 +\item Modifications to tracked files in the working directory are
  66.239 +  added to the patch.
  66.240 +\item Changes to the files tracked using \hgcmd{add}, \hgcmd{copy},
  66.241 +  \hgcmd{remove}, or \hgcmd{rename}.  Added files and copy and rename
  66.242 +  destinations are added to the patch, while removed files and rename
  66.243 +  sources are removed.
  66.244 +\end{itemize}
  66.245 +
  66.246 +Even if \hgxcmd{mq}{qrefresh} detects no changes, it still recreates the
  66.247 +changeset that represents the patch.  This causes the identity of the
  66.248 +changeset to differ from the previous changeset that identified the
  66.249 +patch.
  66.250 +
  66.251 +Options:
  66.252 +\begin{itemize}
  66.253 +\item[\hgxopt{mq}{qrefresh}{-e}] Modify the commit and patch description,
  66.254 +  using the preferred text editor.
  66.255 +\item[\hgxopt{mq}{qrefresh}{-m}] Modify the commit message and patch
  66.256 +  description, using the given text.
  66.257 +\item[\hgxopt{mq}{qrefresh}{-l}] Modify the commit message and patch
  66.258 +  description, using text from the given file.
  66.259 +\end{itemize}
  66.260 +
  66.261 +\subsection{\hgxcmd{mq}{qrename}---rename a patch}
  66.262 +
  66.263 +The \hgxcmd{mq}{qrename} command renames a patch, and changes the entry for
  66.264 +the patch in the \sfilename{series} file.
  66.265 +
  66.266 +With a single argument, \hgxcmd{mq}{qrename} renames the topmost applied
  66.267 +patch.  With two arguments, it renames its first argument to its
  66.268 +second.
  66.269 +
  66.270 +\subsection{\hgxcmd{mq}{qrestore}---restore saved queue state}
  66.271 +
  66.272 +XXX No idea what this does.
  66.273 +
  66.274 +\subsection{\hgxcmd{mq}{qsave}---save current queue state}
  66.275 +
  66.276 +XXX Likewise.
  66.277 +
  66.278 +\subsection{\hgxcmd{mq}{qseries}---print the entire patch series}
  66.279 +
  66.280 +The \hgxcmd{mq}{qseries} command prints the entire patch series from the
  66.281 +\sfilename{series} file.  It prints only patch names, not empty lines
  66.282 +or comments.  It prints in order from first to be applied to last.
  66.283 +
  66.284 +\subsection{\hgxcmd{mq}{qtop}---print the name of the current patch}
  66.285 +
  66.286 +The \hgxcmd{mq}{qtop} prints the name of the topmost currently applied
  66.287 +patch.
  66.288 +
  66.289 +\subsection{\hgxcmd{mq}{qunapplied}---print patches not yet applied}
  66.290 +
  66.291 +The \hgxcmd{mq}{qunapplied} command prints the names of patches from the
  66.292 +\sfilename{series} file that are not yet applied.  It prints them in
  66.293 +order from the next patch that will be pushed to the last.
  66.294 +
  66.295 +\subsection{\hgcmd{strip}---remove a revision and descendants}
  66.296 +
  66.297 +The \hgcmd{strip} command removes a revision, and all of its
  66.298 +descendants, from the repository.  It undoes the effects of the
  66.299 +removed revisions from the repository, and updates the working
  66.300 +directory to the first parent of the removed revision.
  66.301 +
  66.302 +The \hgcmd{strip} command saves a backup of the removed changesets in
  66.303 +a bundle, so that they can be reapplied if removed in error.
  66.304 +
  66.305 +Options:
  66.306 +\begin{itemize}
  66.307 +\item[\hgopt{strip}{-b}] Save unrelated changesets that are intermixed
  66.308 +  with the stripped changesets in the backup bundle.
  66.309 +\item[\hgopt{strip}{-f}] If a branch has multiple heads, remove all
  66.310 +  heads. XXX This should be renamed, and use \texttt{-f} to strip revs
  66.311 +  when there are pending changes.
  66.312 +\item[\hgopt{strip}{-n}] Do not save a backup bundle.
  66.313 +\end{itemize}
  66.314 +
  66.315 +\section{MQ file reference}
  66.316 +
  66.317 +\subsection{The \sfilename{series} file}
  66.318 +
  66.319 +The \sfilename{series} file contains a list of the names of all
  66.320 +patches that MQ can apply.  It is represented as a list of names, with
  66.321 +one name saved per line.  Leading and trailing white space in each
  66.322 +line are ignored.
  66.323 +
  66.324 +Lines may contain comments.  A comment begins with the ``\texttt{\#}''
  66.325 +character, and extends to the end of the line.  Empty lines, and lines
  66.326 +that contain only comments, are ignored.
  66.327 +
  66.328 +You will often need to edit the \sfilename{series} file by hand, hence
  66.329 +the support for comments and empty lines noted above.  For example,
  66.330 +you can comment out a patch temporarily, and \hgxcmd{mq}{qpush} will skip
  66.331 +over that patch when applying patches.  You can also change the order
  66.332 +in which patches are applied by reordering their entries in the
  66.333 +\sfilename{series} file.
  66.334 +
  66.335 +Placing the \sfilename{series} file under revision control is also
  66.336 +supported; it is a good idea to place all of the patches that it
  66.337 +refers to under revision control, as well.  If you create a patch
  66.338 +directory using the \hgxopt{mq}{qinit}{-c} option to \hgxcmd{mq}{qinit}, this
  66.339 +will be done for you automatically.
  66.340 +
  66.341 +\subsection{The \sfilename{status} file}
  66.342 +
  66.343 +The \sfilename{status} file contains the names and changeset hashes of
  66.344 +all patches that MQ currently has applied.  Unlike the
  66.345 +\sfilename{series} file, this file is not intended for editing.  You
  66.346 +should not place this file under revision control, or modify it in any
  66.347 +way.  It is used by MQ strictly for internal book-keeping.
  66.348 +
  66.349 +%%% Local Variables: 
  66.350 +%%% mode: latex
  66.351 +%%% TeX-master: "00book"
  66.352 +%%% End: 
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/fr/mq-stack.svg	Thu Feb 05 12:37:03 2009 +0100
    67.3 @@ -0,0 +1,270 @@
    67.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    67.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    67.6 +<svg
    67.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    67.8 +   xmlns:cc="http://web.resource.org/cc/"
    67.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   67.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   67.11 +   xmlns="http://www.w3.org/2000/svg"
   67.12 +   xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
   67.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   67.14 +   width="744.09448819"
   67.15 +   height="1052.3622047"
   67.16 +   id="svg2"
   67.17 +   sodipodi:version="0.32"
   67.18 +   inkscape:version="0.43"
   67.19 +   sodipodi:docname="mq-stack.svg"
   67.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en">
   67.21 +  <defs
   67.22 +     id="defs4" />
   67.23 +  <sodipodi:namedview
   67.24 +     id="base"
   67.25 +     pagecolor="#ffffff"
   67.26 +     bordercolor="#666666"
   67.27 +     borderopacity="1.0"
   67.28 +     inkscape:pageopacity="0.0"
   67.29 +     inkscape:pageshadow="2"
   67.30 +     inkscape:zoom="1.4142136"
   67.31 +     inkscape:cx="299.33323"
   67.32 +     inkscape:cy="815.646"
   67.33 +     inkscape:document-units="px"
   67.34 +     inkscape:current-layer="layer1"
   67.35 +     inkscape:window-width="1014"
   67.36 +     inkscape:window-height="689"
   67.37 +     inkscape:window-x="0"
   67.38 +     inkscape:window-y="25" />
   67.39 +  <metadata
   67.40 +     id="metadata7">
   67.41 +    <rdf:RDF>
   67.42 +      <cc:Work
   67.43 +         rdf:about="">
   67.44 +        <dc:format>image/svg+xml</dc:format>
   67.45 +        <dc:type
   67.46 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   67.47 +      </cc:Work>
   67.48 +    </rdf:RDF>
   67.49 +  </metadata>
   67.50 +  <g
   67.51 +     inkscape:label="Layer 1"
   67.52 +     inkscape:groupmode="layer"
   67.53 +     id="layer1">
   67.54 +    <rect
   67.55 +       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"
   67.56 +       id="rect1307"
   67.57 +       width="202.93683"
   67.58 +       height="24.243662"
   67.59 +       x="230.01944"
   67.60 +       y="221.70146" />
   67.61 +    <text
   67.62 +       xml:space="preserve"
   67.63 +       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"
   67.64 +       x="237.89606"
   67.65 +       y="237.13383"
   67.66 +       id="text1309"><tspan
   67.67 +         sodipodi:role="line"
   67.68 +         id="tspan1311"
   67.69 +         x="237.89606"
   67.70 +         y="237.13383">prevent-compiler-reorder.patch</tspan></text>
   67.71 +    <rect
   67.72 +       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"
   67.73 +       id="rect1320"
   67.74 +       width="202.93683"
   67.75 +       height="24.243662"
   67.76 +       x="230.01936"
   67.77 +       y="251.34325" />
   67.78 +    <text
   67.79 +       xml:space="preserve"
   67.80 +       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"
   67.81 +       x="237.89598"
   67.82 +       y="266.77563"
   67.83 +       id="text1322"><tspan
   67.84 +         sodipodi:role="line"
   67.85 +         id="tspan1324"
   67.86 +         x="237.89598"
   67.87 +         y="266.77563">namespace-cleanup.patch</tspan></text>
   67.88 +    <rect
   67.89 +       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"
   67.90 +       id="rect2217"
   67.91 +       width="202.93683"
   67.92 +       height="24.243662"
   67.93 +       x="230.01936"
   67.94 +       y="280.98505" />
   67.95 +    <text
   67.96 +       xml:space="preserve"
   67.97 +       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"
   67.98 +       x="237.89598"
   67.99 +       y="296.41742"
  67.100 +       id="text2219"><tspan
  67.101 +         sodipodi:role="line"
  67.102 +         id="tspan2221"
  67.103 +         x="237.89598"
  67.104 +         y="296.41742">powerpc-port-fixes.patch</tspan></text>
  67.105 +    <rect
  67.106 +       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"
  67.107 +       id="rect3114"
  67.108 +       width="202.93683"
  67.109 +       height="24.243662"
  67.110 +       x="230.01936"
  67.111 +       y="310.6268" />
  67.112 +    <text
  67.113 +       xml:space="preserve"
  67.114 +       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"
  67.115 +       x="237.89598"
  67.116 +       y="326.05917"
  67.117 +       id="text3116"><tspan
  67.118 +         sodipodi:role="line"
  67.119 +         id="tspan3118"
  67.120 +         x="237.89598"
  67.121 +         y="326.05917">report-devinfo-correctly.patch</tspan></text>
  67.122 +    <text
  67.123 +       xml:space="preserve"
  67.124 +       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"
  67.125 +       x="200.01021"
  67.126 +       y="191.68094"
  67.127 +       id="text3170"
  67.128 +       sodipodi:linespacing="125%"><tspan
  67.129 +         sodipodi:role="line"
  67.130 +         id="tspan3172"
  67.131 +         x="200.01021"
  67.132 +         y="191.68094"
  67.133 +         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>
  67.134 +    <text
  67.135 +       xml:space="preserve"
  67.136 +       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"
  67.137 +       x="255.26627"
  67.138 +       y="248.79449"
  67.139 +       id="text3190"
  67.140 +       sodipodi:linespacing="125%"
  67.141 +       transform="scale(0.786716,1.271107)"><tspan
  67.142 +         sodipodi:role="line"
  67.143 +         id="tspan3192"
  67.144 +         x="255.26627"
  67.145 +         y="248.79449"
  67.146 +         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>
  67.147 +    <text
  67.148 +       xml:space="preserve"
  67.149 +       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"
  67.150 +       x="195.86807"
  67.151 +       y="173.17117"
  67.152 +       id="text4085"
  67.153 +       sodipodi:linespacing="125%"><tspan
  67.154 +         sodipodi:role="line"
  67.155 +         id="tspan4087"
  67.156 +         x="195.86807"
  67.157 +         y="173.17117"
  67.158 +         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">present in series,</tspan><tspan
  67.159 +         sodipodi:role="line"
  67.160 +         x="195.86807"
  67.161 +         y="188.17117"
  67.162 +         id="tspan4089"
  67.163 +         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">but not applied</tspan></text>
  67.164 +    <text
  67.165 +       xml:space="preserve"
  67.166 +       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"
  67.167 +       x="195.0712"
  67.168 +       y="288.91745"
  67.169 +       id="text4091"
  67.170 +       sodipodi:linespacing="125%"><tspan
  67.171 +         sodipodi:role="line"
  67.172 +         id="tspan4093"
  67.173 +         x="195.0712"
  67.174 +         y="288.91745"
  67.175 +         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">patches applied,</tspan><tspan
  67.176 +         sodipodi:role="line"
  67.177 +         x="195.0712"
  67.178 +         y="303.91745"
  67.179 +         id="tspan4111"
  67.180 +         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">changesets present</tspan></text>
  67.181 +    <text
  67.182 +       xml:space="preserve"
  67.183 +       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"
  67.184 +       x="195.0712"
  67.185 +       y="229.28813"
  67.186 +       id="text4095"
  67.187 +       sodipodi:linespacing="125%"><tspan
  67.188 +         sodipodi:role="line"
  67.189 +         id="tspan4097"
  67.190 +         x="195.0712"
  67.191 +         y="229.28813"
  67.192 +         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">topmost</tspan><tspan
  67.193 +         sodipodi:role="line"
  67.194 +         x="195.0712"
  67.195 +         y="244.28813"
  67.196 +         id="tspan4109"
  67.197 +         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">applied patch</tspan></text>
  67.198 +    <text
  67.199 +       xml:space="preserve"
  67.200 +       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"
  67.201 +       x="450.4975"
  67.202 +       y="238.29692"
  67.203 +       id="text4137"><tspan
  67.204 +         sodipodi:role="line"
  67.205 +         id="tspan4139"
  67.206 +         x="450.4975"
  67.207 +         y="238.29692">201ad3209902</tspan></text>
  67.208 +    <text
  67.209 +       xml:space="preserve"
  67.210 +       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"
  67.211 +       x="450.05804"
  67.212 +       y="267.93872"
  67.213 +       id="text4141"><tspan
  67.214 +         sodipodi:role="line"
  67.215 +         id="tspan4143"
  67.216 +         x="450.05804"
  67.217 +         y="267.93872">126b84e593ae</tspan></text>
  67.218 +    <text
  67.219 +       xml:space="preserve"
  67.220 +       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"
  67.221 +       x="450.6557"
  67.222 +       y="297.58051"
  67.223 +       id="text4145"><tspan
  67.224 +         sodipodi:role="line"
  67.225 +         id="tspan4147"
  67.226 +         x="450.6557"
  67.227 +         y="297.58051">a655daf15409</tspan></text>
  67.228 +    <text
  67.229 +       xml:space="preserve"
  67.230 +       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"
  67.231 +       x="450.71429"
  67.232 +       y="327.22226"
  67.233 +       id="text4149"><tspan
  67.234 +         sodipodi:role="line"
  67.235 +         id="tspan4151"
  67.236 +         x="450.71429"
  67.237 +         y="327.22226">e50d59aaea3a</tspan></text>
  67.238 +    <rect
  67.239 +       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"
  67.240 +       id="rect3106"
  67.241 +       width="202.93683"
  67.242 +       height="24.243662"
  67.243 +       x="230.01936"
  67.244 +       y="150.41792" />
  67.245 +    <text
  67.246 +       xml:space="preserve"
  67.247 +       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"
  67.248 +       x="237.89598"
  67.249 +       y="165.8503"
  67.250 +       id="text3108"><tspan
  67.251 +         sodipodi:role="line"
  67.252 +         id="tspan3110"
  67.253 +         x="237.89598"
  67.254 +         y="165.8503">forbid-illegal-params.patch</tspan></text>
  67.255 +    <rect
  67.256 +       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"
  67.257 +       id="rect2241"
  67.258 +       width="202.93683"
  67.259 +       height="24.243662"
  67.260 +       x="230.16466"
  67.261 +       y="180.05968" />
  67.262 +    <text
  67.263 +       xml:space="preserve"
  67.264 +       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"
  67.265 +       x="238.04128"
  67.266 +       y="195.49205"
  67.267 +       id="text2243"><tspan
  67.268 +         sodipodi:role="line"
  67.269 +         id="tspan2245"
  67.270 +         x="238.04128"
  67.271 +         y="195.49205">fix-memory-leak.patch</tspan></text>
  67.272 +  </g>
  67.273 +</svg>
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/fr/mq.tex	Thu Feb 05 12:37:03 2009 +0100
    68.3 @@ -0,0 +1,1043 @@
    68.4 +\chapter{Managing change with Mercurial Queues}
    68.5 +\label{chap:mq}
    68.6 +
    68.7 +\section{The patch management problem}
    68.8 +\label{sec:mq:patch-mgmt}
    68.9 +
   68.10 +Here is a common scenario: you need to install a software package from
   68.11 +source, but you find a bug that you must fix in the source before you
   68.12 +can start using the package.  You make your changes, forget about the
   68.13 +package for a while, and a few months later you need to upgrade to a
   68.14 +newer version of the package.  If the newer version of the package
   68.15 +still has the bug, you must extract your fix from the older source
   68.16 +tree and apply it against the newer version.  This is a tedious task,
   68.17 +and it's easy to make mistakes.
   68.18 +
   68.19 +This is a simple case of the ``patch management'' problem.  You have
   68.20 +an ``upstream'' source tree that you can't change; you need to make
   68.21 +some local changes on top of the upstream tree; and you'd like to be
   68.22 +able to keep those changes separate, so that you can apply them to
   68.23 +newer versions of the upstream source.
   68.24 +
   68.25 +The patch management problem arises in many situations.  Probably the
   68.26 +most visible is that a user of an open source software project will
   68.27 +contribute a bug fix or new feature to the project's maintainers in the
   68.28 +form of a patch.
   68.29 +
   68.30 +Distributors of operating systems that include open source software
   68.31 +often need to make changes to the packages they distribute so that
   68.32 +they will build properly in their environments.
   68.33 +
   68.34 +When you have few changes to maintain, it is easy to manage a single
   68.35 +patch using the standard \command{diff} and \command{patch} programs
   68.36 +(see section~\ref{sec:mq:patch} for a discussion of these tools).
   68.37 +Once the number of changes grows, it starts to make sense to maintain
   68.38 +patches as discrete ``chunks of work,'' so that for example a single
   68.39 +patch will contain only one bug fix (the patch might modify several
   68.40 +files, but it's doing ``only one thing''), and you may have a number
   68.41 +of such patches for different bugs you need fixed and local changes
   68.42 +you require.  In this situation, if you submit a bug fix patch to the
   68.43 +upstream maintainers of a package and they include your fix in a
   68.44 +subsequent release, you can simply drop that single patch when you're
   68.45 +updating to the newer release.
   68.46 +
   68.47 +Maintaining a single patch against an upstream tree is a little
   68.48 +tedious and error-prone, but not difficult.  However, the complexity
   68.49 +of the problem grows rapidly as the number of patches you have to
   68.50 +maintain increases.  With more than a tiny number of patches in hand,
   68.51 +understanding which ones you have applied and maintaining them moves
   68.52 +from messy to overwhelming.
   68.53 +
   68.54 +Fortunately, Mercurial includes a powerful extension, Mercurial Queues
   68.55 +(or simply ``MQ''), that massively simplifies the patch management
   68.56 +problem.
   68.57 +
   68.58 +\section{The prehistory of Mercurial Queues}
   68.59 +\label{sec:mq:history}
   68.60 +
   68.61 +During the late 1990s, several Linux kernel developers started to
   68.62 +maintain ``patch series'' that modified the behaviour of the Linux
   68.63 +kernel.  Some of these series were focused on stability, some on
   68.64 +feature coverage, and others were more speculative.
   68.65 +
   68.66 +The sizes of these patch series grew rapidly.  In 2002, Andrew Morton
   68.67 +published some shell scripts he had been using to automate the task of
   68.68 +managing his patch queues.  Andrew was successfully using these
   68.69 +scripts to manage hundreds (sometimes thousands) of patches on top of
   68.70 +the Linux kernel.
   68.71 +
   68.72 +\subsection{A patchwork quilt}
   68.73 +\label{sec:mq:quilt}
   68.74 +
   68.75 +In early 2003, Andreas Gruenbacher and Martin Quinson borrowed the
   68.76 +approach of Andrew's scripts and published a tool called ``patchwork
   68.77 +quilt''~\cite{web:quilt}, or simply ``quilt''
   68.78 +(see~\cite{gruenbacher:2005} for a paper describing it).  Because
   68.79 +quilt substantially automated patch management, it rapidly gained a
   68.80 +large following among open source software developers.
   68.81 +
   68.82 +Quilt manages a \emph{stack of patches} on top of a directory tree.
   68.83 +To begin, you tell quilt to manage a directory tree, and tell it which
   68.84 +files you want to manage; it stores away the names and contents of
   68.85 +those files.  To fix a bug, you create a new patch (using a single
   68.86 +command), edit the files you need to fix, then ``refresh'' the patch.
   68.87 +
   68.88 +The refresh step causes quilt to scan the directory tree; it updates
   68.89 +the patch with all of the changes you have made.  You can create
   68.90 +another patch on top of the first, which will track the changes
   68.91 +required to modify the tree from ``tree with one patch applied'' to
   68.92 +``tree with two patches applied''.
   68.93 +
   68.94 +You can \emph{change} which patches are applied to the tree.  If you
   68.95 +``pop'' a patch, the changes made by that patch will vanish from the
   68.96 +directory tree.  Quilt remembers which patches you have popped,
   68.97 +though, so you can ``push'' a popped patch again, and the directory
   68.98 +tree will be restored to contain the modifications in the patch.  Most
   68.99 +importantly, you can run the ``refresh'' command at any time, and the
  68.100 +topmost applied patch will be updated.  This means that you can, at
  68.101 +any time, change both which patches are applied and what
  68.102 +modifications those patches make.
  68.103 +
  68.104 +Quilt knows nothing about revision control tools, so it works equally
  68.105 +well on top of an unpacked tarball or a Subversion working copy.
  68.106 +
  68.107 +\subsection{From patchwork quilt to Mercurial Queues}
  68.108 +\label{sec:mq:quilt-mq}
  68.109 +
  68.110 +In mid-2005, Chris Mason took the features of quilt and wrote an
  68.111 +extension that he called Mercurial Queues, which added quilt-like
  68.112 +behaviour to Mercurial.
  68.113 +
  68.114 +The key difference between quilt and MQ is that quilt knows nothing
  68.115 +about revision control systems, while MQ is \emph{integrated} into
  68.116 +Mercurial.  Each patch that you push is represented as a Mercurial
  68.117 +changeset.  Pop a patch, and the changeset goes away.
  68.118 +
  68.119 +Because quilt does not care about revision control tools, it is still
  68.120 +a tremendously useful piece of software to know about for situations
  68.121 +where you cannot use Mercurial and MQ.
  68.122 +
  68.123 +\section{The huge advantage of MQ}
  68.124 +
  68.125 +I cannot overstate the value that MQ offers through the unification of
  68.126 +patches and revision control.
  68.127 +
  68.128 +A major reason that patches have persisted in the free software and
  68.129 +open source world---in spite of the availability of increasingly
  68.130 +capable revision control tools over the years---is the \emph{agility}
  68.131 +they offer.  
  68.132 +
  68.133 +Traditional revision control tools make a permanent, irreversible
  68.134 +record of everything that you do.  While this has great value, it's
  68.135 +also somewhat stifling.  If you want to perform a wild-eyed
  68.136 +experiment, you have to be careful in how you go about it, or you risk
  68.137 +leaving unneeded---or worse, misleading or destabilising---traces of
  68.138 +your missteps and errors in the permanent revision record.
  68.139 +
  68.140 +By contrast, MQ's marriage of distributed revision control with
  68.141 +patches makes it much easier to isolate your work.  Your patches live
  68.142 +on top of normal revision history, and you can make them disappear or
  68.143 +reappear at will.  If you don't like a patch, you can drop it.  If a
  68.144 +patch isn't quite as you want it to be, simply fix it---as many times
  68.145 +as you need to, until you have refined it into the form you desire.
  68.146 +
  68.147 +As an example, the integration of patches with revision control makes
  68.148 +understanding patches and debugging their effects---and their
  68.149 +interplay with the code they're based on---\emph{enormously} easier.
  68.150 +Since every applied patch has an associated changeset, you can use
  68.151 +\hgcmdargs{log}{\emph{filename}} to see which changesets and patches
  68.152 +affected a file.  You can use the \hgext{bisect} command to
  68.153 +binary-search through all changesets and applied patches to see where
  68.154 +a bug got introduced or fixed.  You can use the \hgcmd{annotate}
  68.155 +command to see which changeset or patch modified a particular line of
  68.156 +a source file.  And so on.
  68.157 +
  68.158 +\section{Understanding patches}
  68.159 +\label{sec:mq:patch}
  68.160 +
  68.161 +Because MQ doesn't hide its patch-oriented nature, it is helpful to
  68.162 +understand what patches are, and a little about the tools that work
  68.163 +with them.
  68.164 +
  68.165 +The traditional Unix \command{diff} command compares two files, and
  68.166 +prints a list of differences between them. The \command{patch} command
  68.167 +understands these differences as \emph{modifications} to make to a
  68.168 +file.  Take a look at figure~\ref{ex:mq:diff} for a simple example of
  68.169 +these commands in action.
  68.170 +
  68.171 +\begin{figure}[ht]
  68.172 +  \interaction{mq.dodiff.diff}
  68.173 +  \caption{Simple uses of the \command{diff} and \command{patch} commands}
  68.174 +  \label{ex:mq:diff}
  68.175 +\end{figure}
  68.176 +
  68.177 +The type of file that \command{diff} generates (and \command{patch}
  68.178 +takes as input) is called a ``patch'' or a ``diff''; there is no
  68.179 +difference between a patch and a diff.  (We'll use the term ``patch'',
  68.180 +since it's more commonly used.)
  68.181 +
  68.182 +A patch file can start with arbitrary text; the \command{patch}
  68.183 +command ignores this text, but MQ uses it as the commit message when
  68.184 +creating changesets.  To find the beginning of the patch content,
  68.185 +\command{patch} searches for the first line that starts with the
  68.186 +string ``\texttt{diff~-}''.
  68.187 +
  68.188 +MQ works with \emph{unified} diffs (\command{patch} can accept several
  68.189 +other diff formats, but MQ doesn't).  A unified diff contains two
  68.190 +kinds of header.  The \emph{file header} describes the file being
  68.191 +modified; it contains the name of the file to modify.  When
  68.192 +\command{patch} sees a new file header, it looks for a file with that
  68.193 +name to start modifying.
  68.194 +
  68.195 +After the file header comes a series of \emph{hunks}.  Each hunk
  68.196 +starts with a header; this identifies the range of line numbers within
  68.197 +the file that the hunk should modify.  Following the header, a hunk
  68.198 +starts and ends with a few (usually three) lines of text from the
  68.199 +unmodified file; these are called the \emph{context} for the hunk.  If
  68.200 +there's only a small amount of context between successive hunks,
  68.201 +\command{diff} doesn't print a new hunk header; it just runs the hunks
  68.202 +together, with a few lines of context between modifications.
  68.203 +
  68.204 +Each line of context begins with a space character.  Within the hunk,
  68.205 +a line that begins with ``\texttt{-}'' means ``remove this line,''
  68.206 +while a line that begins with ``\texttt{+}'' means ``insert this
  68.207 +line.''  For example, a line that is modified is represented by one
  68.208 +deletion and one insertion.
  68.209 +
  68.210 +We will return to some of the more subtle aspects of patches later (in
  68.211 +section~\ref{sec:mq:adv-patch}), but you should have enough information
  68.212 +now to use MQ.
  68.213 +
  68.214 +\section{Getting started with Mercurial Queues}
  68.215 +\label{sec:mq:start}
  68.216 +
  68.217 +Because MQ is implemented as an extension, you must explicitly enable
  68.218 +before you can use it.  (You don't need to download anything; MQ ships
  68.219 +with the standard Mercurial distribution.)  To enable MQ, edit your
  68.220 +\tildefile{.hgrc} file, and add the lines in figure~\ref{ex:mq:config}.
  68.221 +
  68.222 +\begin{figure}[ht]
  68.223 +  \begin{codesample4}
  68.224 +    [extensions]
  68.225 +    hgext.mq =
  68.226 +  \end{codesample4}
  68.227 +  \label{ex:mq:config}
  68.228 +  \caption{Contents to add to \tildefile{.hgrc} to enable the MQ extension}
  68.229 +\end{figure}
  68.230 +
  68.231 +Once the extension is enabled, it will make a number of new commands
  68.232 +available.  To verify that the extension is working, you can use
  68.233 +\hgcmd{help} to see if the \hgxcmd{mq}{qinit} command is now available; see
  68.234 +the example in figure~\ref{ex:mq:enabled}.
  68.235 +
  68.236 +\begin{figure}[ht]
  68.237 +  \interaction{mq.qinit-help.help}
  68.238 +  \caption{How to verify that MQ is enabled}
  68.239 +  \label{ex:mq:enabled}
  68.240 +\end{figure}
  68.241 +
  68.242 +You can use MQ with \emph{any} Mercurial repository, and its commands
  68.243 +only operate within that repository.  To get started, simply prepare
  68.244 +the repository using the \hgxcmd{mq}{qinit} command (see
  68.245 +figure~\ref{ex:mq:qinit}).  This command creates an empty directory
  68.246 +called \sdirname{.hg/patches}, where MQ will keep its metadata.  As
  68.247 +with many Mercurial commands, the \hgxcmd{mq}{qinit} command prints nothing
  68.248 +if it succeeds.
  68.249 +
  68.250 +\begin{figure}[ht]
  68.251 +  \interaction{mq.tutorial.qinit}
  68.252 +  \caption{Preparing a repository for use with MQ}
  68.253 +  \label{ex:mq:qinit}
  68.254 +\end{figure}
  68.255 +
  68.256 +\begin{figure}[ht]
  68.257 +  \interaction{mq.tutorial.qnew}
  68.258 +  \caption{Creating a new patch}
  68.259 +  \label{ex:mq:qnew}
  68.260 +\end{figure}
  68.261 +
  68.262 +\subsection{Creating a new patch}
  68.263 +
  68.264 +To begin work on a new patch, use the \hgxcmd{mq}{qnew} command.  This
  68.265 +command takes one argument, the name of the patch to create.  MQ will
  68.266 +use this as the name of an actual file in the \sdirname{.hg/patches}
  68.267 +directory, as you can see in figure~\ref{ex:mq:qnew}.
  68.268 +
  68.269 +Also newly present in the \sdirname{.hg/patches} directory are two
  68.270 +other files, \sfilename{series} and \sfilename{status}.  The
  68.271 +\sfilename{series} file lists all of the patches that MQ knows about
  68.272 +for this repository, with one patch per line.  Mercurial uses the
  68.273 +\sfilename{status} file for internal book-keeping; it tracks all of the
  68.274 +patches that MQ has \emph{applied} in this repository.
  68.275 +
  68.276 +\begin{note}
  68.277 +  You may sometimes want to edit the \sfilename{series} file by hand;
  68.278 +  for example, to change the sequence in which some patches are
  68.279 +  applied.  However, manually editing the \sfilename{status} file is
  68.280 +  almost always a bad idea, as it's easy to corrupt MQ's idea of what
  68.281 +  is happening.
  68.282 +\end{note}
  68.283 +
  68.284 +Once you have created your new patch, you can edit files in the
  68.285 +working directory as you usually would.  All of the normal Mercurial
  68.286 +commands, such as \hgcmd{diff} and \hgcmd{annotate}, work exactly as
  68.287 +they did before.
  68.288 +
  68.289 +\subsection{Refreshing a patch}
  68.290 +
  68.291 +When you reach a point where you want to save your work, use the
  68.292 +\hgxcmd{mq}{qrefresh} command (figure~\ref{ex:mq:qnew}) to update the patch
  68.293 +you are working on.  This command folds the changes you have made in
  68.294 +the working directory into your patch, and updates its corresponding
  68.295 +changeset to contain those changes.
  68.296 +
  68.297 +\begin{figure}[ht]
  68.298 +  \interaction{mq.tutorial.qrefresh}
  68.299 +  \caption{Refreshing a patch}
  68.300 +  \label{ex:mq:qrefresh}
  68.301 +\end{figure}
  68.302 +
  68.303 +You can run \hgxcmd{mq}{qrefresh} as often as you like, so it's a good way
  68.304 +to ``checkpoint'' your work.  Refresh your patch at an opportune
  68.305 +time; try an experiment; and if the experiment doesn't work out,
  68.306 +\hgcmd{revert} your modifications back to the last time you refreshed.
  68.307 +
  68.308 +\begin{figure}[ht]
  68.309 +  \interaction{mq.tutorial.qrefresh2}
  68.310 +  \caption{Refresh a patch many times to accumulate changes}
  68.311 +  \label{ex:mq:qrefresh2}
  68.312 +\end{figure}
  68.313 +
  68.314 +\subsection{Stacking and tracking patches}
  68.315 +
  68.316 +Once you have finished working on a patch, or need to work on another,
  68.317 +you can use the \hgxcmd{mq}{qnew} command again to create a new patch.
  68.318 +Mercurial will apply this patch on top of your existing patch.  See
  68.319 +figure~\ref{ex:mq:qnew2} for an example.  Notice that the patch
  68.320 +contains the changes in our prior patch as part of its context (you
  68.321 +can see this more clearly in the output of \hgcmd{annotate}).
  68.322 +
  68.323 +\begin{figure}[ht]
  68.324 +  \interaction{mq.tutorial.qnew2}
  68.325 +  \caption{Stacking a second patch on top of the first}
  68.326 +  \label{ex:mq:qnew2}
  68.327 +\end{figure}
  68.328 +
  68.329 +So far, with the exception of \hgxcmd{mq}{qnew} and \hgxcmd{mq}{qrefresh}, we've
  68.330 +been careful to only use regular Mercurial commands.  However, MQ
  68.331 +provides many commands that are easier to use when you are thinking
  68.332 +about patches, as illustrated in figure~\ref{ex:mq:qseries}:
  68.333 +
  68.334 +\begin{itemize}
  68.335 +\item The \hgxcmd{mq}{qseries} command lists every patch that MQ knows
  68.336 +  about in this repository, from oldest to newest (most recently
  68.337 +  \emph{created}).
  68.338 +\item The \hgxcmd{mq}{qapplied} command lists every patch that MQ has
  68.339 +  \emph{applied} in this repository, again from oldest to newest (most
  68.340 +  recently applied).
  68.341 +\end{itemize}
  68.342 +
  68.343 +\begin{figure}[ht]
  68.344 +  \interaction{mq.tutorial.qseries}
  68.345 +  \caption{Understanding the patch stack with \hgxcmd{mq}{qseries} and
  68.346 +    \hgxcmd{mq}{qapplied}}
  68.347 +  \label{ex:mq:qseries}
  68.348 +\end{figure}
  68.349 +
  68.350 +\subsection{Manipulating the patch stack}
  68.351 +
  68.352 +The previous discussion implied that there must be a difference
  68.353 +between ``known'' and ``applied'' patches, and there is.  MQ can
  68.354 +manage a patch without it being applied in the repository.
  68.355 +
  68.356 +An \emph{applied} patch has a corresponding changeset in the
  68.357 +repository, and the effects of the patch and changeset are visible in
  68.358 +the working directory.  You can undo the application of a patch using
  68.359 +the \hgxcmd{mq}{qpop} command.  MQ still \emph{knows about}, or manages, a
  68.360 +popped patch, but the patch no longer has a corresponding changeset in
  68.361 +the repository, and the working directory does not contain the changes
  68.362 +made by the patch.  Figure~\ref{fig:mq:stack} illustrates the
  68.363 +difference between applied and tracked patches.
  68.364 +
  68.365 +\begin{figure}[ht]
  68.366 +  \centering
  68.367 +  \grafix{mq-stack}
  68.368 +  \caption{Applied and unapplied patches in the MQ patch stack}
  68.369 +  \label{fig:mq:stack}
  68.370 +\end{figure}
  68.371 +
  68.372 +You can reapply an unapplied, or popped, patch using the \hgxcmd{mq}{qpush}
  68.373 +command.  This creates a new changeset to correspond to the patch, and
  68.374 +the patch's changes once again become present in the working
  68.375 +directory.  See figure~\ref{ex:mq:qpop} for examples of \hgxcmd{mq}{qpop}
  68.376 +and \hgxcmd{mq}{qpush} in action.  Notice that once we have popped a patch
  68.377 +or two patches, the output of \hgxcmd{mq}{qseries} remains the same, while
  68.378 +that of \hgxcmd{mq}{qapplied} has changed.
  68.379 +
  68.380 +\begin{figure}[ht]
  68.381 +  \interaction{mq.tutorial.qpop}
  68.382 +  \caption{Modifying the stack of applied patches}
  68.383 +  \label{ex:mq:qpop}
  68.384 +\end{figure}
  68.385 +
  68.386 +\subsection{Pushing and popping many patches}
  68.387 +
  68.388 +While \hgxcmd{mq}{qpush} and \hgxcmd{mq}{qpop} each operate on a single patch at
  68.389 +a time by default, you can push and pop many patches in one go.  The
  68.390 +\hgxopt{mq}{qpush}{-a} option to \hgxcmd{mq}{qpush} causes it to push all
  68.391 +unapplied patches, while the \hgxopt{mq}{qpop}{-a} option to \hgxcmd{mq}{qpop}
  68.392 +causes it to pop all applied patches.  (For some more ways to push and
  68.393 +pop many patches, see section~\ref{sec:mq:perf} below.)
  68.394 +
  68.395 +\begin{figure}[ht]
  68.396 +  \interaction{mq.tutorial.qpush-a}
  68.397 +  \caption{Pushing all unapplied patches}
  68.398 +  \label{ex:mq:qpush-a}
  68.399 +\end{figure}
  68.400 +
  68.401 +\subsection{Safety checks, and overriding them}
  68.402 +
  68.403 +Several MQ commands check the working directory before they do
  68.404 +anything, and fail if they find any modifications.  They do this to
  68.405 +ensure that you won't lose any changes that you have made, but not yet
  68.406 +incorporated into a patch.  Figure~\ref{ex:mq:add} illustrates this;
  68.407 +the \hgxcmd{mq}{qnew} command will not create a new patch if there are
  68.408 +outstanding changes, caused in this case by the \hgcmd{add} of
  68.409 +\filename{file3}.
  68.410 +
  68.411 +\begin{figure}[ht]
  68.412 +  \interaction{mq.tutorial.add}
  68.413 +  \caption{Forcibly creating a patch}
  68.414 +  \label{ex:mq:add}
  68.415 +\end{figure}
  68.416 +
  68.417 +Commands that check the working directory all take an ``I know what
  68.418 +I'm doing'' option, which is always named \option{-f}.  The exact
  68.419 +meaning of \option{-f} depends on the command.  For example,
  68.420 +\hgcmdargs{qnew}{\hgxopt{mq}{qnew}{-f}} will incorporate any outstanding
  68.421 +changes into the new patch it creates, but
  68.422 +\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-f}} will revert modifications to any
  68.423 +files affected by the patch that it is popping.  Be sure to read the
  68.424 +documentation for a command's \option{-f} option before you use it!
  68.425 +
  68.426 +\subsection{Working on several patches at once}
  68.427 +
  68.428 +The \hgxcmd{mq}{qrefresh} command always refreshes the \emph{topmost}
  68.429 +applied patch.  This means that you can suspend work on one patch (by
  68.430 +refreshing it), pop or push to make a different patch the top, and
  68.431 +work on \emph{that} patch for a while.
  68.432 +
  68.433 +Here's an example that illustrates how you can use this ability.
  68.434 +Let's say you're developing a new feature as two patches.  The first
  68.435 +is a change to the core of your software, and the second---layered on
  68.436 +top of the first---changes the user interface to use the code you just
  68.437 +added to the core.  If you notice a bug in the core while you're
  68.438 +working on the UI patch, it's easy to fix the core.  Simply
  68.439 +\hgxcmd{mq}{qrefresh} the UI patch to save your in-progress changes, and
  68.440 +\hgxcmd{mq}{qpop} down to the core patch.  Fix the core bug,
  68.441 +\hgxcmd{mq}{qrefresh} the core patch, and \hgxcmd{mq}{qpush} back to the UI
  68.442 +patch to continue where you left off.
  68.443 +
  68.444 +\section{More about patches}
  68.445 +\label{sec:mq:adv-patch}
  68.446 +
  68.447 +MQ uses the GNU \command{patch} command to apply patches, so it's
  68.448 +helpful to know a few more detailed aspects of how \command{patch}
  68.449 +works, and about patches themselves.
  68.450 +
  68.451 +\subsection{The strip count}
  68.452 +
  68.453 +If you look at the file headers in a patch, you will notice that the
  68.454 +pathnames usually have an extra component on the front that isn't
  68.455 +present in the actual path name.  This is a holdover from the way that
  68.456 +people used to generate patches (people still do this, but it's
  68.457 +somewhat rare with modern revision control tools).  
  68.458 +
  68.459 +Alice would unpack a tarball, edit her files, then decide that she
  68.460 +wanted to create a patch.  So she'd rename her working directory,
  68.461 +unpack the tarball again (hence the need for the rename), and use the
  68.462 +\cmdopt{diff}{-r} and \cmdopt{diff}{-N} options to \command{diff} to
  68.463 +recursively generate a patch between the unmodified directory and the
  68.464 +modified one.  The result would be that the name of the unmodified
  68.465 +directory would be at the front of the left-hand path in every file
  68.466 +header, and the name of the modified directory would be at the front
  68.467 +of the right-hand path.
  68.468 +
  68.469 +Since someone receiving a patch from the Alices of the net would be
  68.470 +unlikely to have unmodified and modified directories with exactly the
  68.471 +same names, the \command{patch} command has a \cmdopt{patch}{-p}
  68.472 +option that indicates the number of leading path name components to
  68.473 +strip when trying to apply a patch.  This number is called the
  68.474 +\emph{strip count}.
  68.475 +
  68.476 +An option of ``\texttt{-p1}'' means ``use a strip count of one''.  If
  68.477 +\command{patch} sees a file name \filename{foo/bar/baz} in a file
  68.478 +header, it will strip \filename{foo} and try to patch a file named
  68.479 +\filename{bar/baz}.  (Strictly speaking, the strip count refers to the
  68.480 +number of \emph{path separators} (and the components that go with them
  68.481 +) to strip.  A strip count of one will turn \filename{foo/bar} into
  68.482 +\filename{bar}, but \filename{/foo/bar} (notice the extra leading
  68.483 +slash) into \filename{foo/bar}.)
  68.484 +
  68.485 +The ``standard'' strip count for patches is one; almost all patches
  68.486 +contain one leading path name component that needs to be stripped.
  68.487 +Mercurial's \hgcmd{diff} command generates path names in this form,
  68.488 +and the \hgcmd{import} command and MQ expect patches to have a strip
  68.489 +count of one.
  68.490 +
  68.491 +If you receive a patch from someone that you want to add to your patch
  68.492 +queue, and the patch needs a strip count other than one, you cannot
  68.493 +just \hgxcmd{mq}{qimport} the patch, because \hgxcmd{mq}{qimport} does not yet
  68.494 +have a \texttt{-p} option (see~\bug{311}).  Your best bet is to
  68.495 +\hgxcmd{mq}{qnew} a patch of your own, then use \cmdargs{patch}{-p\emph{N}}
  68.496 +to apply their patch, followed by \hgcmd{addremove} to pick up any
  68.497 +files added or removed by the patch, followed by \hgxcmd{mq}{qrefresh}.
  68.498 +This complexity may become unnecessary; see~\bug{311} for details.
  68.499 +\subsection{Strategies for applying a patch}
  68.500 +
  68.501 +When \command{patch} applies a hunk, it tries a handful of
  68.502 +successively less accurate strategies to try to make the hunk apply.
  68.503 +This falling-back technique often makes it possible to take a patch
  68.504 +that was generated against an old version of a file, and apply it
  68.505 +against a newer version of that file.
  68.506 +
  68.507 +First, \command{patch} tries an exact match, where the line numbers,
  68.508 +the context, and the text to be modified must apply exactly.  If it
  68.509 +cannot make an exact match, it tries to find an exact match for the
  68.510 +context, without honouring the line numbering information.  If this
  68.511 +succeeds, it prints a line of output saying that the hunk was applied,
  68.512 +but at some \emph{offset} from the original line number.
  68.513 +
  68.514 +If a context-only match fails, \command{patch} removes the first and
  68.515 +last lines of the context, and tries a \emph{reduced} context-only
  68.516 +match.  If the hunk with reduced context succeeds, it prints a message
  68.517 +saying that it applied the hunk with a \emph{fuzz factor} (the number
  68.518 +after the fuzz factor indicates how many lines of context
  68.519 +\command{patch} had to trim before the patch applied).
  68.520 +
  68.521 +When neither of these techniques works, \command{patch} prints a
  68.522 +message saying that the hunk in question was rejected.  It saves
  68.523 +rejected hunks (also simply called ``rejects'') to a file with the
  68.524 +same name, and an added \sfilename{.rej} extension.  It also saves an
  68.525 +unmodified copy of the file with a \sfilename{.orig} extension; the
  68.526 +copy of the file without any extensions will contain any changes made
  68.527 +by hunks that \emph{did} apply cleanly.  If you have a patch that
  68.528 +modifies \filename{foo} with six hunks, and one of them fails to
  68.529 +apply, you will have: an unmodified \filename{foo.orig}, a
  68.530 +\filename{foo.rej} containing one hunk, and \filename{foo}, containing
  68.531 +the changes made by the five successful hunks.
  68.532 +
  68.533 +\subsection{Some quirks of patch representation}
  68.534 +
  68.535 +There are a few useful things to know about how \command{patch} works
  68.536 +with files.
  68.537 +\begin{itemize}
  68.538 +\item This should already be obvious, but \command{patch} cannot
  68.539 +  handle binary files.
  68.540 +\item Neither does it care about the executable bit; it creates new
  68.541 +  files as readable, but not executable.
  68.542 +\item \command{patch} treats the removal of a file as a diff between
  68.543 +  the file to be removed and the empty file.  So your idea of ``I
  68.544 +  deleted this file'' looks like ``every line of this file was
  68.545 +  deleted'' in a patch.
  68.546 +\item It treats the addition of a file as a diff between the empty
  68.547 +  file and the file to be added.  So in a patch, your idea of ``I
  68.548 +  added this file'' looks like ``every line of this file was added''.
  68.549 +\item It treats a renamed file as the removal of the old name, and the
  68.550 +  addition of the new name.  This means that renamed files have a big
  68.551 +  footprint in patches.  (Note also that Mercurial does not currently
  68.552 +  try to infer when files have been renamed or copied in a patch.)
  68.553 +\item \command{patch} cannot represent empty files, so you cannot use
  68.554 +  a patch to represent the notion ``I added this empty file to the
  68.555 +  tree''.
  68.556 +\end{itemize}
  68.557 +\subsection{Beware the fuzz}
  68.558 +
  68.559 +While applying a hunk at an offset, or with a fuzz factor, will often
  68.560 +be completely successful, these inexact techniques naturally leave
  68.561 +open the possibility of corrupting the patched file.  The most common
  68.562 +cases typically involve applying a patch twice, or at an incorrect
  68.563 +location in the file.  If \command{patch} or \hgxcmd{mq}{qpush} ever
  68.564 +mentions an offset or fuzz factor, you should make sure that the
  68.565 +modified files are correct afterwards.  
  68.566 +
  68.567 +It's often a good idea to refresh a patch that has applied with an
  68.568 +offset or fuzz factor; refreshing the patch generates new context
  68.569 +information that will make it apply cleanly.  I say ``often,'' not
  68.570 +``always,'' because sometimes refreshing a patch will make it fail to
  68.571 +apply against a different revision of the underlying files.  In some
  68.572 +cases, such as when you're maintaining a patch that must sit on top of
  68.573 +multiple versions of a source tree, it's acceptable to have a patch
  68.574 +apply with some fuzz, provided you've verified the results of the
  68.575 +patching process in such cases.
  68.576 +
  68.577 +\subsection{Handling rejection}
  68.578 +
  68.579 +If \hgxcmd{mq}{qpush} fails to apply a patch, it will print an error
  68.580 +message and exit.  If it has left \sfilename{.rej} files behind, it is
  68.581 +usually best to fix up the rejected hunks before you push more patches
  68.582 +or do any further work.
  68.583 +
  68.584 +If your patch \emph{used to} apply cleanly, and no longer does because
  68.585 +you've changed the underlying code that your patches are based on,
  68.586 +Mercurial Queues can help; see section~\ref{sec:mq:merge} for details.
  68.587 +
  68.588 +Unfortunately, there aren't any great techniques for dealing with
  68.589 +rejected hunks.  Most often, you'll need to view the \sfilename{.rej}
  68.590 +file and edit the target file, applying the rejected hunks by hand.
  68.591 +
  68.592 +If you're feeling adventurous, Neil Brown, a Linux kernel hacker,
  68.593 +wrote a tool called \command{wiggle}~\cite{web:wiggle}, which is more
  68.594 +vigorous than \command{patch} in its attempts to make a patch apply.
  68.595 +
  68.596 +Another Linux kernel hacker, Chris Mason (the author of Mercurial
  68.597 +Queues), wrote a similar tool called
  68.598 +\command{mpatch}~\cite{web:mpatch}, which takes a simple approach to
  68.599 +automating the application of hunks rejected by \command{patch}.  The
  68.600 +\command{mpatch} command can help with four common reasons that a hunk
  68.601 +may be rejected:
  68.602 +
  68.603 +\begin{itemize}
  68.604 +\item The context in the middle of a hunk has changed.
  68.605 +\item A hunk is missing some context at the beginning or end.
  68.606 +\item A large hunk might apply better---either entirely or in
  68.607 +  part---if it was broken up into smaller hunks.
  68.608 +\item A hunk removes lines with slightly different content than those
  68.609 +  currently present in the file.
  68.610 +\end{itemize}
  68.611 +
  68.612 +If you use \command{wiggle} or \command{mpatch}, you should be doubly
  68.613 +careful to check your results when you're done.  In fact,
  68.614 +\command{mpatch} enforces this method of double-checking the tool's
  68.615 +output, by automatically dropping you into a merge program when it has
  68.616 +done its job, so that you can verify its work and finish off any
  68.617 +remaining merges.
  68.618 +
  68.619 +\section{Getting the best performance out of MQ}
  68.620 +\label{sec:mq:perf}
  68.621 +
  68.622 +MQ is very efficient at handling a large number of patches.  I ran
  68.623 +some performance experiments in mid-2006 for a talk that I gave at the
  68.624 +2006 EuroPython conference~\cite{web:europython}.  I used as my data
  68.625 +set the Linux 2.6.17-mm1 patch series, which consists of 1,738
  68.626 +patches.  I applied these on top of a Linux kernel repository
  68.627 +containing all 27,472 revisions between Linux 2.6.12-rc2 and Linux
  68.628 +2.6.17.
  68.629 +
  68.630 +On my old, slow laptop, I was able to
  68.631 +\hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} all 1,738 patches in 3.5 minutes,
  68.632 +and \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} them all in 30 seconds.  (On a
  68.633 +newer laptop, the time to push all patches dropped to two minutes.)  I
  68.634 +could \hgxcmd{mq}{qrefresh} one of the biggest patches (which made 22,779
  68.635 +lines of changes to 287 files) in 6.6 seconds.
  68.636 +
  68.637 +Clearly, MQ is well suited to working in large trees, but there are a
  68.638 +few tricks you can use to get the best performance of it.
  68.639 +
  68.640 +First of all, try to ``batch'' operations together.  Every time you
  68.641 +run \hgxcmd{mq}{qpush} or \hgxcmd{mq}{qpop}, these commands scan the working
  68.642 +directory once to make sure you haven't made some changes and then
  68.643 +forgotten to run \hgxcmd{mq}{qrefresh}.  On a small tree, the time that
  68.644 +this scan takes is unnoticeable.  However, on a medium-sized tree
  68.645 +(containing tens of thousands of files), it can take a second or more.
  68.646 +
  68.647 +The \hgxcmd{mq}{qpush} and \hgxcmd{mq}{qpop} commands allow you to push and pop
  68.648 +multiple patches at a time.  You can identify the ``destination
  68.649 +patch'' that you want to end up at.  When you \hgxcmd{mq}{qpush} with a
  68.650 +destination specified, it will push patches until that patch is at the
  68.651 +top of the applied stack.  When you \hgxcmd{mq}{qpop} to a destination, MQ
  68.652 +will pop patches until the destination patch is at the top.
  68.653 +
  68.654 +You can identify a destination patch using either the name of the
  68.655 +patch, or by number.  If you use numeric addressing, patches are
  68.656 +counted from zero; this means that the first patch is zero, the second
  68.657 +is one, and so on.
  68.658 +
  68.659 +\section{Updating your patches when the underlying code changes}
  68.660 +\label{sec:mq:merge}
  68.661 +
  68.662 +It's common to have a stack of patches on top of an underlying
  68.663 +repository that you don't modify directly.  If you're working on
  68.664 +changes to third-party code, or on a feature that is taking longer to
  68.665 +develop than the rate of change of the code beneath, you will often
  68.666 +need to sync up with the underlying code, and fix up any hunks in your
  68.667 +patches that no longer apply.  This is called \emph{rebasing} your
  68.668 +patch series.
  68.669 +
  68.670 +The simplest way to do this is to \hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}}
  68.671 +your patches, then \hgcmd{pull} changes into the underlying
  68.672 +repository, and finally \hgcmdargs{qpush}{\hgxopt{mq}{qpop}{-a}} your
  68.673 +patches again.  MQ will stop pushing any time it runs across a patch
  68.674 +that fails to apply during conflicts, allowing you to fix your
  68.675 +conflicts, \hgxcmd{mq}{qrefresh} the affected patch, and continue pushing
  68.676 +until you have fixed your entire stack.
  68.677 +
  68.678 +This approach is easy to use and works well if you don't expect
  68.679 +changes to the underlying code to affect how well your patches apply.
  68.680 +If your patch stack touches code that is modified frequently or
  68.681 +invasively in the underlying repository, however, fixing up rejected
  68.682 +hunks by hand quickly becomes tiresome.
  68.683 +
  68.684 +It's possible to partially automate the rebasing process.  If your
  68.685 +patches apply cleanly against some revision of the underlying repo, MQ
  68.686 +can use this information to help you to resolve conflicts between your
  68.687 +patches and a different revision.
  68.688 +
  68.689 +The process is a little involved.
  68.690 +\begin{enumerate}
  68.691 +\item To begin, \hgcmdargs{qpush}{-a} all of your patches on top of
  68.692 +  the revision where you know that they apply cleanly.
  68.693 +\item Save a backup copy of your patch directory using
  68.694 +  \hgcmdargs{qsave}{\hgxopt{mq}{qsave}{-e} \hgxopt{mq}{qsave}{-c}}.  This prints
  68.695 +  the name of the directory that it has saved the patches in.  It will
  68.696 +  save the patches to a directory called
  68.697 +  \sdirname{.hg/patches.\emph{N}}, where \texttt{\emph{N}} is a small
  68.698 +  integer.  It also commits a ``save changeset'' on top of your
  68.699 +  applied patches; this is for internal book-keeping, and records the
  68.700 +  states of the \sfilename{series} and \sfilename{status} files.
  68.701 +\item Use \hgcmd{pull} to bring new changes into the underlying
  68.702 +  repository.  (Don't run \hgcmdargs{pull}{-u}; see below for why.)
  68.703 +\item Update to the new tip revision, using
  68.704 +  \hgcmdargs{update}{\hgopt{update}{-C}} to override the patches you
  68.705 +  have pushed.
  68.706 +\item Merge all patches using \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}
  68.707 +    \hgxopt{mq}{qpush}{-a}}.  The \hgxopt{mq}{qpush}{-m} option to \hgxcmd{mq}{qpush}
  68.708 +  tells MQ to perform a three-way merge if the patch fails to apply.
  68.709 +\end{enumerate}
  68.710 +
  68.711 +During the \hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-m}}, each patch in the
  68.712 +\sfilename{series} file is applied normally.  If a patch applies with
  68.713 +fuzz or rejects, MQ looks at the queue you \hgxcmd{mq}{qsave}d, and
  68.714 +performs a three-way merge with the corresponding changeset.  This
  68.715 +merge uses Mercurial's normal merge machinery, so it may pop up a GUI
  68.716 +merge tool to help you to resolve problems.
  68.717 +
  68.718 +When you finish resolving the effects of a patch, MQ refreshes your
  68.719 +patch based on the result of the merge.
  68.720 +
  68.721 +At the end of this process, your repository will have one extra head
  68.722 +from the old patch queue, and a copy of the old patch queue will be in
  68.723 +\sdirname{.hg/patches.\emph{N}}. You can remove the extra head using
  68.724 +\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a} \hgxopt{mq}{qpop}{-n} patches.\emph{N}}
  68.725 +or \hgcmd{strip}.  You can delete \sdirname{.hg/patches.\emph{N}} once
  68.726 +you are sure that you no longer need it as a backup.
  68.727 +
  68.728 +\section{Identifying patches}
  68.729 +
  68.730 +MQ commands that work with patches let you refer to a patch either by
  68.731 +using its name or by a number.  By name is obvious enough; pass the
  68.732 +name \filename{foo.patch} to \hgxcmd{mq}{qpush}, for example, and it will
  68.733 +push patches until \filename{foo.patch} is applied.  
  68.734 +
  68.735 +As a shortcut, you can refer to a patch using both a name and a
  68.736 +numeric offset; \texttt{foo.patch-2} means ``two patches before
  68.737 +\texttt{foo.patch}'', while \texttt{bar.patch+4} means ``four patches
  68.738 +after \texttt{bar.patch}''.
  68.739 +
  68.740 +Referring to a patch by index isn't much different.  The first patch
  68.741 +printed in the output of \hgxcmd{mq}{qseries} is patch zero (yes, it's one
  68.742 +of those start-at-zero counting systems); the second is patch one; and
  68.743 +so on.
  68.744 +
  68.745 +MQ also makes it easy to work with patches when you are using normal
  68.746 +Mercurial commands.  Every command that accepts a changeset ID will
  68.747 +also accept the name of an applied patch.  MQ augments the tags
  68.748 +normally in the repository with an eponymous one for each applied
  68.749 +patch.  In addition, the special tags \index{tags!special tag
  68.750 +  names!\texttt{qbase}}\texttt{qbase} and \index{tags!special tag
  68.751 +  names!\texttt{qtip}}\texttt{qtip} identify the ``bottom-most'' and
  68.752 +topmost applied patches, respectively.
  68.753 +
  68.754 +These additions to Mercurial's normal tagging capabilities make
  68.755 +dealing with patches even more of a breeze.
  68.756 +\begin{itemize}
  68.757 +\item Want to patchbomb a mailing list with your latest series of
  68.758 +  changes?
  68.759 +  \begin{codesample4}
  68.760 +    hg email qbase:qtip
  68.761 +  \end{codesample4}
  68.762 +  (Don't know what ``patchbombing'' is?  See
  68.763 +  section~\ref{sec:hgext:patchbomb}.)
  68.764 +\item Need to see all of the patches since \texttt{foo.patch} that
  68.765 +  have touched files in a subdirectory of your tree?
  68.766 +  \begin{codesample4}
  68.767 +    hg log -r foo.patch:qtip \emph{subdir}
  68.768 +  \end{codesample4}
  68.769 +\end{itemize}
  68.770 +
  68.771 +Because MQ makes the names of patches available to the rest of
  68.772 +Mercurial through its normal internal tag machinery, you don't need to
  68.773 +type in the entire name of a patch when you want to identify it by
  68.774 +name.
  68.775 +
  68.776 +\begin{figure}[ht]
  68.777 +  \interaction{mq.id.output}
  68.778 +  \caption{Using MQ's tag features to work with patches}
  68.779 +  \label{ex:mq:id}
  68.780 +\end{figure}
  68.781 +
  68.782 +Another nice consequence of representing patch names as tags is that
  68.783 +when you run the \hgcmd{log} command, it will display a patch's name
  68.784 +as a tag, simply as part of its normal output.  This makes it easy to
  68.785 +visually distinguish applied patches from underlying ``normal''
  68.786 +revisions.  Figure~\ref{ex:mq:id} shows a few normal Mercurial
  68.787 +commands in use with applied patches.
  68.788 +
  68.789 +\section{Useful things to know about}
  68.790 +
  68.791 +There are a number of aspects of MQ usage that don't fit tidily into
  68.792 +sections of their own, but that are good to know.  Here they are, in
  68.793 +one place.
  68.794 +
  68.795 +\begin{itemize}
  68.796 +\item Normally, when you \hgxcmd{mq}{qpop} a patch and \hgxcmd{mq}{qpush} it
  68.797 +  again, the changeset that represents the patch after the pop/push
  68.798 +  will have a \emph{different identity} than the changeset that
  68.799 +  represented the hash beforehand.  See
  68.800 +  section~\ref{sec:mqref:cmd:qpush} for information as to why this is.
  68.801 +\item It's not a good idea to \hgcmd{merge} changes from another
  68.802 +  branch with a patch changeset, at least if you want to maintain the
  68.803 +  ``patchiness'' of that changeset and changesets below it on the
  68.804 +  patch stack.  If you try to do this, it will appear to succeed, but
  68.805 +  MQ will become confused.
  68.806 +\end{itemize}
  68.807 +
  68.808 +\section{Managing patches in a repository}
  68.809 +\label{sec:mq:repo}
  68.810 +
  68.811 +Because MQ's \sdirname{.hg/patches} directory resides outside a
  68.812 +Mercurial repository's working directory, the ``underlying'' Mercurial
  68.813 +repository knows nothing about the management or presence of patches.
  68.814 +
  68.815 +This presents the interesting possibility of managing the contents of
  68.816 +the patch directory as a Mercurial repository in its own right.  This
  68.817 +can be a useful way to work.  For example, you can work on a patch for
  68.818 +a while, \hgxcmd{mq}{qrefresh} it, then \hgcmd{commit} the current state of
  68.819 +the patch.  This lets you ``roll back'' to that version of the patch
  68.820 +later on.
  68.821 +
  68.822 +You can then share different versions of the same patch stack among
  68.823 +multiple underlying repositories.  I use this when I am developing a
  68.824 +Linux kernel feature.  I have a pristine copy of my kernel sources for
  68.825 +each of several CPU architectures, and a cloned repository under each
  68.826 +that contains the patches I am working on.  When I want to test a
  68.827 +change on a different architecture, I push my current patches to the
  68.828 +patch repository associated with that kernel tree, pop and push all of
  68.829 +my patches, and build and test that kernel.
  68.830 +
  68.831 +Managing patches in a repository makes it possible for multiple
  68.832 +developers to work on the same patch series without colliding with
  68.833 +each other, all on top of an underlying source base that they may or
  68.834 +may not control.
  68.835 +
  68.836 +\subsection{MQ support for patch repositories}
  68.837 +
  68.838 +MQ helps you to work with the \sdirname{.hg/patches} directory as a
  68.839 +repository; when you prepare a repository for working with patches
  68.840 +using \hgxcmd{mq}{qinit}, you can pass the \hgxopt{mq}{qinit}{-c} option to
  68.841 +create the \sdirname{.hg/patches} directory as a Mercurial repository.
  68.842 +
  68.843 +\begin{note}
  68.844 +  If you forget to use the \hgxopt{mq}{qinit}{-c} option, you can simply go
  68.845 +  into the \sdirname{.hg/patches} directory at any time and run
  68.846 +  \hgcmd{init}.  Don't forget to add an entry for the
  68.847 +  \sfilename{status} file to the \sfilename{.hgignore} file, though
  68.848 +
  68.849 +  (\hgcmdargs{qinit}{\hgxopt{mq}{qinit}{-c}} does this for you
  68.850 +  automatically); you \emph{really} don't want to manage the
  68.851 +  \sfilename{status} file.
  68.852 +\end{note}
  68.853 +
  68.854 +As a convenience, if MQ notices that the \dirname{.hg/patches}
  68.855 +directory is a repository, it will automatically \hgcmd{add} every
  68.856 +patch that you create and import.
  68.857 +
  68.858 +MQ provides a shortcut command, \hgxcmd{mq}{qcommit}, that runs
  68.859 +\hgcmd{commit} in the \sdirname{.hg/patches} directory.  This saves
  68.860 +some bothersome typing.
  68.861 +
  68.862 +Finally, as a convenience to manage the patch directory, you can
  68.863 +define the alias \command{mq} on Unix systems. For example, on Linux
  68.864 +systems using the \command{bash} shell, you can include the following
  68.865 +snippet in your \tildefile{.bashrc}.
  68.866 +
  68.867 +\begin{codesample2}
  68.868 +  alias mq=`hg -R \$(hg root)/.hg/patches'
  68.869 +\end{codesample2}
  68.870 +
  68.871 +You can then issue commands of the form \cmdargs{mq}{pull} from
  68.872 +the main repository.
  68.873 +
  68.874 +\subsection{A few things to watch out for}
  68.875 +
  68.876 +MQ's support for working with a repository full of patches is limited
  68.877 +in a few small respects.
  68.878 +
  68.879 +MQ cannot automatically detect changes that you make to the patch
  68.880 +directory.  If you \hgcmd{pull}, manually edit, or \hgcmd{update}
  68.881 +changes to patches or the \sfilename{series} file, you will have to
  68.882 +\hgcmdargs{qpop}{\hgxopt{mq}{qpop}{-a}} and then
  68.883 +\hgcmdargs{qpush}{\hgxopt{mq}{qpush}{-a}} in the underlying repository to
  68.884 +see those changes show up there.  If you forget to do this, you can
  68.885 +confuse MQ's idea of which patches are applied.
  68.886 +
  68.887 +\section{Third party tools for working with patches}
  68.888 +\label{sec:mq:tools}
  68.889 +
  68.890 +Once you've been working with patches for a while, you'll find
  68.891 +yourself hungry for tools that will help you to understand and
  68.892 +manipulate the patches you're dealing with.
  68.893 +
  68.894 +The \command{diffstat} command~\cite{web:diffstat} generates a
  68.895 +histogram of the modifications made to each file in a patch.  It
  68.896 +provides a good way to ``get a sense of'' a patch---which files it
  68.897 +affects, and how much change it introduces to each file and as a
  68.898 +whole.  (I find that it's a good idea to use \command{diffstat}'s
  68.899 +\cmdopt{diffstat}{-p} option as a matter of course, as otherwise it
  68.900 +will try to do clever things with prefixes of file names that
  68.901 +inevitably confuse at least me.)
  68.902 +
  68.903 +\begin{figure}[ht]
  68.904 +  \interaction{mq.tools.tools}
  68.905 +  \caption{The \command{diffstat}, \command{filterdiff}, and \command{lsdiff} commands}
  68.906 +  \label{ex:mq:tools}
  68.907 +\end{figure}
  68.908 +
  68.909 +The \package{patchutils} package~\cite{web:patchutils} is invaluable.
  68.910 +It provides a set of small utilities that follow the ``Unix
  68.911 +philosophy;'' each does one useful thing with a patch.  The
  68.912 +\package{patchutils} command I use most is \command{filterdiff}, which
  68.913 +extracts subsets from a patch file.  For example, given a patch that
  68.914 +modifies hundreds of files across dozens of directories, a single
  68.915 +invocation of \command{filterdiff} can generate a smaller patch that
  68.916 +only touches files whose names match a particular glob pattern.  See
  68.917 +section~\ref{mq-collab:tips:interdiff} for another example.
  68.918 +
  68.919 +\section{Good ways to work with patches}
  68.920 +
  68.921 +Whether you are working on a patch series to submit to a free software
  68.922 +or open source project, or a series that you intend to treat as a
  68.923 +sequence of regular changesets when you're done, you can use some
  68.924 +simple techniques to keep your work well organised.
  68.925 +
  68.926 +Give your patches descriptive names.  A good name for a patch might be
  68.927 +\filename{rework-device-alloc.patch}, because it will immediately give
  68.928 +you a hint what the purpose of the patch is.  Long names shouldn't be
  68.929 +a problem; you won't be typing the names often, but you \emph{will} be
  68.930 +running commands like \hgxcmd{mq}{qapplied} and \hgxcmd{mq}{qtop} over and over.
  68.931 +Good naming becomes especially important when you have a number of
  68.932 +patches to work with, or if you are juggling a number of different
  68.933 +tasks and your patches only get a fraction of your attention.
  68.934 +
  68.935 +Be aware of what patch you're working on.  Use the \hgxcmd{mq}{qtop}
  68.936 +command and skim over the text of your patches frequently---for
  68.937 +example, using \hgcmdargs{tip}{\hgopt{tip}{-p}})---to be sure of where
  68.938 +you stand.  I have several times worked on and \hgxcmd{mq}{qrefresh}ed a
  68.939 +patch other than the one I intended, and it's often tricky to migrate
  68.940 +changes into the right patch after making them in the wrong one.
  68.941 +
  68.942 +For this reason, it is very much worth investing a little time to
  68.943 +learn how to use some of the third-party tools I described in
  68.944 +section~\ref{sec:mq:tools}, particularly \command{diffstat} and
  68.945 +\command{filterdiff}.  The former will give you a quick idea of what
  68.946 +changes your patch is making, while the latter makes it easy to splice
  68.947 +hunks selectively out of one patch and into another.
  68.948 +
  68.949 +\section{MQ cookbook}
  68.950 +
  68.951 +\subsection{Manage ``trivial'' patches}
  68.952 +
  68.953 +Because the overhead of dropping files into a new Mercurial repository
  68.954 +is so low, it makes a lot of sense to manage patches this way even if
  68.955 +you simply want to make a few changes to a source tarball that you
  68.956 +downloaded.
  68.957 +
  68.958 +Begin by downloading and unpacking the source tarball,
  68.959 +and turning it into a Mercurial repository.
  68.960 +\interaction{mq.tarball.download}
  68.961 +
  68.962 +Continue by creating a patch stack and making your changes.
  68.963 +\interaction{mq.tarball.qinit}
  68.964 +
  68.965 +Let's say a few weeks or months pass, and your package author releases
  68.966 +a new version.  First, bring their changes into the repository.
  68.967 +\interaction{mq.tarball.newsource}
  68.968 +The pipeline starting with \hgcmd{locate} above deletes all files in
  68.969 +the working directory, so that \hgcmd{commit}'s
  68.970 +\hgopt{commit}{--addremove} option can actually tell which files have
  68.971 +really been removed in the newer version of the source.
  68.972 +
  68.973 +Finally, you can apply your patches on top of the new tree.
  68.974 +\interaction{mq.tarball.repush}
  68.975 +
  68.976 +\subsection{Combining entire patches}
  68.977 +\label{sec:mq:combine}
  68.978 +
  68.979 +MQ provides a command, \hgxcmd{mq}{qfold} that lets you combine entire
  68.980 +patches.  This ``folds'' the patches you name, in the order you name
  68.981 +them, into the topmost applied patch, and concatenates their
  68.982 +descriptions onto the end of its description.  The patches that you
  68.983 +fold must be unapplied before you fold them.
  68.984 +
  68.985 +The order in which you fold patches matters.  If your topmost applied
  68.986 +patch is \texttt{foo}, and you \hgxcmd{mq}{qfold} \texttt{bar} and
  68.987 +\texttt{quux} into it, you will end up with a patch that has the same
  68.988 +effect as if you applied first \texttt{foo}, then \texttt{bar},
  68.989 +followed by \texttt{quux}.
  68.990 +
  68.991 +\subsection{Merging part of one patch into another}
  68.992 +
  68.993 +Merging \emph{part} of one patch into another is more difficult than
  68.994 +combining entire patches.
  68.995 +
  68.996 +If you want to move changes to entire files, you can use
  68.997 +\command{filterdiff}'s \cmdopt{filterdiff}{-i} and
  68.998 +\cmdopt{filterdiff}{-x} options to choose the modifications to snip
  68.999 +out of one patch, concatenating its output onto the end of the patch
 68.1000 +you want to merge into.  You usually won't need to modify the patch
 68.1001 +you've merged the changes from.  Instead, MQ will report some rejected
 68.1002 +hunks when you \hgxcmd{mq}{qpush} it (from the hunks you moved into the
 68.1003 +other patch), and you can simply \hgxcmd{mq}{qrefresh} the patch to drop
 68.1004 +the duplicate hunks.
 68.1005 +
 68.1006 +If you have a patch that has multiple hunks modifying a file, and you
 68.1007 +only want to move a few of those hunks, the job becomes more messy,
 68.1008 +but you can still partly automate it.  Use \cmdargs{lsdiff}{-nvv} to
 68.1009 +print some metadata about the patch.
 68.1010 +\interaction{mq.tools.lsdiff}
 68.1011 +
 68.1012 +This command prints three different kinds of number:
 68.1013 +\begin{itemize}
 68.1014 +\item (in the first column) a \emph{file number} to identify each file
 68.1015 +  modified in the patch;
 68.1016 +\item (on the next line, indented) the line number within a modified
 68.1017 +  file where a hunk starts; and
 68.1018 +\item (on the same line) a \emph{hunk number} to identify that hunk.
 68.1019 +\end{itemize}
 68.1020 +
 68.1021 +You'll have to use some visual inspection, and reading of the patch,
 68.1022 +to identify the file and hunk numbers you'll want, but you can then
 68.1023 +pass them to to \command{filterdiff}'s \cmdopt{filterdiff}{--files}
 68.1024 +and \cmdopt{filterdiff}{--hunks} options, to select exactly the file
 68.1025 +and hunk you want to extract.
 68.1026 +
 68.1027 +Once you have this hunk, you can concatenate it onto the end of your
 68.1028 +destination patch and continue with the remainder of
 68.1029 +section~\ref{sec:mq:combine}.
 68.1030 +
 68.1031 +\section{Differences between quilt and MQ}
 68.1032 +
 68.1033 +If you are already familiar with quilt, MQ provides a similar command
 68.1034 +set.  There are a few differences in the way that it works.
 68.1035 +
 68.1036 +You will already have noticed that most quilt commands have MQ
 68.1037 +counterparts that simply begin with a ``\texttt{q}''.  The exceptions
 68.1038 +are quilt's \texttt{add} and \texttt{remove} commands, the
 68.1039 +counterparts for which are the normal Mercurial \hgcmd{add} and
 68.1040 +\hgcmd{remove} commands.  There is no MQ equivalent of the quilt
 68.1041 +\texttt{edit} command.
 68.1042 +
 68.1043 +%%% Local Variables: 
 68.1044 +%%% mode: latex
 68.1045 +%%% TeX-master: "00book"
 68.1046 +%%% End: 
    69.1 Binary file fr/note.png has changed
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/fr/preface.tex	Thu Feb 05 12:37:03 2009 +0100
    70.3 @@ -0,0 +1,69 @@
    70.4 +\chapter*{Préface}
    70.5 +\addcontentsline{toc}{chapter}{Preface}
    70.6 +\label{chap:preface}
    70.7 +
    70.8 +La gestion de source distribué est encore un territoire peu exploré
    70.9 +et par conséquent a grandis très rapidement grâce à la volonté de
   70.10 +ses explorateurs.
   70.11 +
   70.12 +Je rédige un libre sur ce sujet car je crois que c'est un sujet 
   70.13 +important qui mérite bien un guide du ``terrain''. J'ai choisi d'écrire
   70.14 +un livre sur Mercurial car c'est l'outil le plus simple pour découvrir
   70.15 +ce nouveau monde et que, en outre, il répond très bien au besoin de
   70.16 +réels environements, là où d'autres outils de gestion de source n'y
   70.17 +parviennent pas.
   70.18 +
   70.19 +\section{Cet ouvrage est un travail en cours}
   70.20 +
   70.21 +Je publie ce livre tout en continuant à l'écrire, dans l'espoir qu'il
   70.22 +vous sera utile. J'espère aussi que les lecteurs pourront ainsi contribuer
   70.23 +si ils souhaitent.
   70.24 +
   70.25 +\section{A propros des exemples de ce livre}
   70.26 +
   70.27 +Ce livre a une approche particulière des extrait de code. Ceci sont 
   70.28 +toujours ``dynamique''---chacun est le résultat d'un script shell qui
   70.29 +exécute les commandes mercurial que vous voyez. Chaque fois qu'une 
   70.30 +image du livre est construite tout les scripts d'exemple sont exécutés
   70.31 +automatiquement, et les résultats comparés à ceux attendus.
   70.32 +
   70.33 +Cette approche a l'avantage de garantir que les exemples sont toujours
   70.34 +juste; ils montrent \emph{exactement} le comportement de la version de
   70.35 +Mercurial spécifié dans la couverture de ce livre. Si je met à jour cette
   70.36 +version, et que les commandes changent, la génération du livre échouera.
   70.37 +
   70.38 +Il y a un petit désavantage à cette approche, qui que les dates et les
   70.39 +temps onl
   70.40 +
   70.41 +There is a small disadvantage to this approach, which is that the
   70.42 +dates and times you'll see in examples tend to be ``squashed''
   70.43 +together in a way that they wouldn't be if the same commands were
   70.44 +being typed by a human.  Where a human can issue no more than one
   70.45 +command every few seconds, with any resulting timestamps
   70.46 +correspondingly spread out, my automated example scripts run many
   70.47 +commands in one second.
   70.48 +
   70.49 +As an instance of this, several consecutive commits in an example can
   70.50 +show up as having occurred during the same second.  You can see this
   70.51 +occur in the \hgext{bisect} example in section~\ref{sec:undo:bisect},
   70.52 +for instance.
   70.53 +
   70.54 +So when you're reading examples, don't place too much weight on the
   70.55 +dates or times you see in the output of commands.  But \emph{do} be
   70.56 +confident that the behaviour you're seeing is consistent and
   70.57 +reproducible.
   70.58 +
   70.59 +\section{Colophon---this book is Free}
   70.60 +
   70.61 +This book is licensed under the Open Publication License, and is
   70.62 +produced entirely using Free Software tools.  It is typeset with
   70.63 +\LaTeX{}; illustrations are drawn and rendered with
   70.64 +\href{http://www.inkscape.org/}{Inkscape}.
   70.65 +
   70.66 +The complete source code for this book is published as a Mercurial
   70.67 +repository, at \url{http://hg.serpentine.com/mercurial/book}.
   70.68 +
   70.69 +%%% Local Variables: 
   70.70 +%%% mode: latex
   70.71 +%%% TeX-master: "00book"
   70.72 +%%% End: 
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/fr/revlog.svg	Thu Feb 05 12:37:03 2009 +0100
    71.3 @@ -0,0 +1,1155 @@
    71.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    71.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    71.6 +<svg
    71.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    71.8 +   xmlns:cc="http://web.resource.org/cc/"
    71.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   71.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   71.11 +   xmlns="http://www.w3.org/2000/svg"
   71.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
   71.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   71.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   71.15 +   width="744.09448819"
   71.16 +   height="1052.3622047"
   71.17 +   id="svg2"
   71.18 +   sodipodi:version="0.32"
   71.19 +   inkscape:version="0.44.1"
   71.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
   71.21 +   sodipodi:docname="revlog.svg">
   71.22 +  <defs
   71.23 +     id="defs4">
   71.24 +    <marker
   71.25 +       inkscape:stockid="Arrow1Mend"
   71.26 +       orient="auto"
   71.27 +       refY="0.0"
   71.28 +       refX="0.0"
   71.29 +       id="Arrow1Mend"
   71.30 +       style="overflow:visible;">
   71.31 +      <path
   71.32 +         id="path4852"
   71.33 +         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 "
   71.34 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   71.35 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   71.36 +    </marker>
   71.37 +    <linearGradient
   71.38 +       id="linearGradient3092">
   71.39 +      <stop
   71.40 +         style="stop-color:#44436f;stop-opacity:1;"
   71.41 +         offset="0"
   71.42 +         id="stop3094" />
   71.43 +      <stop
   71.44 +         style="stop-color:#abade5;stop-opacity:1;"
   71.45 +         offset="1"
   71.46 +         id="stop3096" />
   71.47 +    </linearGradient>
   71.48 +    <linearGradient
   71.49 +       inkscape:collect="always"
   71.50 +       xlink:href="#linearGradient3092"
   71.51 +       id="linearGradient3118"
   71.52 +       gradientUnits="userSpaceOnUse"
   71.53 +       x1="176.16635"
   71.54 +       y1="405.21934"
   71.55 +       x2="417.11935"
   71.56 +       y2="405.21934" />
   71.57 +    <linearGradient
   71.58 +       inkscape:collect="always"
   71.59 +       xlink:href="#linearGradient3092"
   71.60 +       id="linearGradient3120"
   71.61 +       gradientUnits="userSpaceOnUse"
   71.62 +       x1="176.16635"
   71.63 +       y1="405.21934"
   71.64 +       x2="417.11935"
   71.65 +       y2="405.21934" />
   71.66 +    <linearGradient
   71.67 +       inkscape:collect="always"
   71.68 +       xlink:href="#linearGradient3092"
   71.69 +       id="linearGradient3129"
   71.70 +       gradientUnits="userSpaceOnUse"
   71.71 +       x1="176.16635"
   71.72 +       y1="405.21934"
   71.73 +       x2="417.11935"
   71.74 +       y2="405.21934"
   71.75 +       gradientTransform="translate(-0.928574,-1.428574)" />
   71.76 +    <linearGradient
   71.77 +       inkscape:collect="always"
   71.78 +       xlink:href="#linearGradient3092"
   71.79 +       id="linearGradient3133"
   71.80 +       gradientUnits="userSpaceOnUse"
   71.81 +       x1="176.16635"
   71.82 +       y1="405.21934"
   71.83 +       x2="417.11935"
   71.84 +       y2="405.21934"
   71.85 +       gradientTransform="translate(-0.928574,-1.428574)" />
   71.86 +    <linearGradient
   71.87 +       inkscape:collect="always"
   71.88 +       xlink:href="#linearGradient3092"
   71.89 +       id="linearGradient3708"
   71.90 +       gradientUnits="userSpaceOnUse"
   71.91 +       gradientTransform="matrix(0.423343,0,0,0.423343,138.874,-67.01732)"
   71.92 +       x1="175.23776"
   71.93 +       y1="509.98154"
   71.94 +       x2="416.29077"
   71.95 +       y2="297.49997" />
   71.96 +    <linearGradient
   71.97 +       inkscape:collect="always"
   71.98 +       xlink:href="#linearGradient3092"
   71.99 +       id="linearGradient5164"
  71.100 +       gradientUnits="userSpaceOnUse"
  71.101 +       gradientTransform="matrix(0.423343,0,0,0.423343,198.249,247.4358)"
  71.102 +       x1="175.23776"
  71.103 +       y1="509.98154"
  71.104 +       x2="416.29077"
  71.105 +       y2="297.49997" />
  71.106 +    <linearGradient
  71.107 +       inkscape:collect="always"
  71.108 +       xlink:href="#linearGradient3092"
  71.109 +       id="linearGradient5584"
  71.110 +       gradientUnits="userSpaceOnUse"
  71.111 +       gradientTransform="matrix(0.423343,0,0,0.423343,143.9081,371.2915)"
  71.112 +       x1="175.23776"
  71.113 +       y1="509.98154"
  71.114 +       x2="416.29077"
  71.115 +       y2="297.49997" />
  71.116 +    <linearGradient
  71.117 +       inkscape:collect="always"
  71.118 +       xlink:href="#linearGradient3092"
  71.119 +       id="linearGradient5784"
  71.120 +       gradientUnits="userSpaceOnUse"
  71.121 +       gradientTransform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
  71.122 +       x1="175.23776"
  71.123 +       y1="509.98154"
  71.124 +       x2="416.29077"
  71.125 +       y2="297.49997" />
  71.126 +    <linearGradient
  71.127 +       inkscape:collect="always"
  71.128 +       xlink:href="#linearGradient3092"
  71.129 +       id="linearGradient5786"
  71.130 +       gradientUnits="userSpaceOnUse"
  71.131 +       gradientTransform="matrix(0.423343,0,0,0.423343,198.249,152.137)"
  71.132 +       x1="175.23776"
  71.133 +       y1="509.98154"
  71.134 +       x2="416.29077"
  71.135 +       y2="297.49997" />
  71.136 +    <linearGradient
  71.137 +       inkscape:collect="always"
  71.138 +       xlink:href="#linearGradient3092"
  71.139 +       id="linearGradient5895"
  71.140 +       gradientUnits="userSpaceOnUse"
  71.141 +       gradientTransform="matrix(0.423343,0,0,0.423343,198.0215,261.7142)"
  71.142 +       x1="175.23776"
  71.143 +       y1="509.98154"
  71.144 +       x2="416.29077"
  71.145 +       y2="297.49997" />
  71.146 +    <linearGradient
  71.147 +       inkscape:collect="always"
  71.148 +       xlink:href="#linearGradient3092"
  71.149 +       id="linearGradient5958"
  71.150 +       gradientUnits="userSpaceOnUse"
  71.151 +       gradientTransform="matrix(0.423343,0,0,0.423343,137.1978,42.55987)"
  71.152 +       x1="175.23776"
  71.153 +       y1="509.98154"
  71.154 +       x2="416.29077"
  71.155 +       y2="297.49997" />
  71.156 +  </defs>
  71.157 +  <sodipodi:namedview
  71.158 +     id="base"
  71.159 +     pagecolor="#ffffff"
  71.160 +     bordercolor="#666666"
  71.161 +     borderopacity="1.0"
  71.162 +     gridtolerance="10000"
  71.163 +     guidetolerance="10"
  71.164 +     objecttolerance="10"
  71.165 +     inkscape:pageopacity="0.0"
  71.166 +     inkscape:pageshadow="2"
  71.167 +     inkscape:zoom="0.64"
  71.168 +     inkscape:cx="566.02368"
  71.169 +     inkscape:cy="688.16826"
  71.170 +     inkscape:document-units="px"
  71.171 +     inkscape:current-layer="layer1"
  71.172 +     inkscape:window-width="906"
  71.173 +     inkscape:window-height="620"
  71.174 +     inkscape:window-x="29"
  71.175 +     inkscape:window-y="79"
  71.176 +     inkscape:connector-spacing="11" />
  71.177 +  <metadata
  71.178 +     id="metadata7">
  71.179 +    <rdf:RDF>
  71.180 +      <cc:Work
  71.181 +         rdf:about="">
  71.182 +        <dc:format>image/svg+xml</dc:format>
  71.183 +        <dc:type
  71.184 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  71.185 +      </cc:Work>
  71.186 +    </rdf:RDF>
  71.187 +  </metadata>
  71.188 +  <g
  71.189 +     inkscape:label="Layer 1"
  71.190 +     inkscape:groupmode="layer"
  71.191 +     id="layer1">
  71.192 +    <rect
  71.193 +       y="168.74846"
  71.194 +       x="211.58516"
  71.195 +       height="89.506805"
  71.196 +       width="101.60232"
  71.197 +       id="rect3068"
  71.198 +       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" />
  71.199 +    <g
  71.200 +       id="g3215"
  71.201 +       transform="matrix(0.423343,0,0,0.423343,137.1977,42.55985)">
  71.202 +      <rect
  71.203 +         y="447.71451"
  71.204 +         x="299.67859"
  71.205 +         height="48.571426"
  71.206 +         width="103.14286"
  71.207 +         id="rect2899"
  71.208 +         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" />
  71.209 +      <text
  71.210 +         id="text2903"
  71.211 +         y="464.8139"
  71.212 +         x="308.89639"
  71.213 +         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"
  71.214 +         xml:space="preserve"><tspan
  71.215 +           y="464.8139"
  71.216 +           x="308.89639"
  71.217 +           sodipodi:role="line"
  71.218 +           id="tspan2905">Second parent</tspan></text>
  71.219 +      <text
  71.220 +         id="text2907"
  71.221 +         y="485.50256"
  71.222 +         x="308.20175"
  71.223 +         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"
  71.224 +         xml:space="preserve"><tspan
  71.225 +           style="font-family:Courier"
  71.226 +           y="485.50256"
  71.227 +           x="308.20175"
  71.228 +           id="tspan2909"
  71.229 +           sodipodi:role="line">32bf9a5f22c0</tspan></text>
  71.230 +    </g>
  71.231 +    <g
  71.232 +       id="g3250"
  71.233 +       transform="matrix(0.423343,0,0,0.423343,137.1977,42.55986)">
  71.234 +      <rect
  71.235 +         y="311.28598"
  71.236 +         x="188.6071"
  71.237 +         height="48.571426"
  71.238 +         width="103.14286"
  71.239 +         id="rect2936"
  71.240 +         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" />
  71.241 +      <text
  71.242 +         id="text2940"
  71.243 +         y="328.38538"
  71.244 +         x="197.82495"
  71.245 +         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"
  71.246 +         xml:space="preserve"><tspan
  71.247 +           y="328.38538"
  71.248 +           x="197.82495"
  71.249 +           sodipodi:role="line"
  71.250 +           id="tspan2942">Revision hash</tspan></text>
  71.251 +      <text
  71.252 +         id="text2944"
  71.253 +         y="349.07404"
  71.254 +         x="197.13031"
  71.255 +         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"
  71.256 +         xml:space="preserve"><tspan
  71.257 +           style="font-family:Courier"
  71.258 +           y="349.07404"
  71.259 +           x="197.13031"
  71.260 +           id="tspan2946"
  71.261 +           sodipodi:role="line">34b8b7a15ea1</tspan></text>
  71.262 +    </g>
  71.263 +    <g
  71.264 +       id="g3243"
  71.265 +       transform="matrix(0.423343,0,0,0.423343,137.6664,43.91853)">
  71.266 +      <rect
  71.267 +         y="363.07654"
  71.268 +         x="187.5"
  71.269 +         height="75"
  71.270 +         width="213.85715"
  71.271 +         id="rect2950"
  71.272 +         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" />
  71.273 +      <text
  71.274 +         id="text2958"
  71.275 +         y="400.86459"
  71.276 +         x="196.02321"
  71.277 +         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"
  71.278 +         xml:space="preserve"><tspan
  71.279 +           style="fill:black;fill-opacity:1;font-family:Courier"
  71.280 +           y="400.86459"
  71.281 +           x="196.02321"
  71.282 +           id="tspan2960"
  71.283 +           sodipodi:role="line">...</tspan></text>
  71.284 +      <text
  71.285 +         id="text2954"
  71.286 +         y="380.17593"
  71.287 +         x="196.71785"
  71.288 +         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"
  71.289 +         xml:space="preserve"><tspan
  71.290 +           y="380.17593"
  71.291 +           x="196.71785"
  71.292 +           sodipodi:role="line"
  71.293 +           id="tspan2956"
  71.294 +           style="fill:black;fill-opacity:1">Revision data (delta or snapshot)</tspan></text>
  71.295 +    </g>
  71.296 +    <g
  71.297 +       id="g5529"
  71.298 +       transform="translate(-6.710312,-8.165836e-6)">
  71.299 +      <rect
  71.300 +         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"
  71.301 +         id="rect3509"
  71.302 +         width="101.60232"
  71.303 +         height="89.506805"
  71.304 +         x="218.29547"
  71.305 +         y="497.4801" />
  71.306 +      <g
  71.307 +         transform="matrix(0.423343,0,0,0.423343,143.908,371.2915)"
  71.308 +         id="g3513">
  71.309 +        <g
  71.310 +           id="g3515">
  71.311 +          <rect
  71.312 +             y="447.72418"
  71.313 +             x="188.6071"
  71.314 +             height="48.571426"
  71.315 +             width="103.14286"
  71.316 +             id="rect3517"
  71.317 +             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" />
  71.318 +          <text
  71.319 +             id="text3519"
  71.320 +             y="464.82358"
  71.321 +             x="197.82495"
  71.322 +             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"
  71.323 +             xml:space="preserve"><tspan
  71.324 +               y="464.82358"
  71.325 +               x="197.82495"
  71.326 +               sodipodi:role="line"
  71.327 +               id="tspan3521">First parent</tspan></text>
  71.328 +          <text
  71.329 +             id="text3523"
  71.330 +             y="485.51224"
  71.331 +             x="197.13031"
  71.332 +             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"
  71.333 +             xml:space="preserve"><tspan
  71.334 +               style="font-family:Courier"
  71.335 +               y="485.51224"
  71.336 +               x="197.13031"
  71.337 +               id="tspan3525"
  71.338 +               sodipodi:role="line">000000000000</tspan></text>
  71.339 +        </g>
  71.340 +        <g
  71.341 +           id="g3527">
  71.342 +          <rect
  71.343 +             y="447.71451"
  71.344 +             x="299.67859"
  71.345 +             height="48.571426"
  71.346 +             width="103.14286"
  71.347 +             id="rect3529"
  71.348 +             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" />
  71.349 +          <text
  71.350 +             id="text3531"
  71.351 +             y="464.8139"
  71.352 +             x="308.89639"
  71.353 +             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"
  71.354 +             xml:space="preserve"><tspan
  71.355 +               y="464.8139"
  71.356 +               x="308.89639"
  71.357 +               sodipodi:role="line"
  71.358 +               id="tspan3533">Second parent</tspan></text>
  71.359 +          <text
  71.360 +             id="text3535"
  71.361 +             y="485.50256"
  71.362 +             x="308.20175"
  71.363 +             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"
  71.364 +             xml:space="preserve"><tspan
  71.365 +               style="font-family:Courier"
  71.366 +               y="485.50256"
  71.367 +               x="308.20175"
  71.368 +               id="tspan3537"
  71.369 +               sodipodi:role="line">000000000000</tspan></text>
  71.370 +        </g>
  71.371 +      </g>
  71.372 +      <g
  71.373 +         transform="matrix(0.423343,0,0,0.423343,143.908,371.2915)"
  71.374 +         id="g3539">
  71.375 +        <rect
  71.376 +           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"
  71.377 +           id="rect3541"
  71.378 +           width="103.14286"
  71.379 +           height="48.571426"
  71.380 +           x="188.6071"
  71.381 +           y="311.28598" />
  71.382 +        <text
  71.383 +           xml:space="preserve"
  71.384 +           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"
  71.385 +           x="197.82495"
  71.386 +           y="328.38538"
  71.387 +           id="text3543"><tspan
  71.388 +             id="tspan3545"
  71.389 +             sodipodi:role="line"
  71.390 +             x="197.82495"
  71.391 +             y="328.38538">Revision hash</tspan></text>
  71.392 +        <text
  71.393 +           xml:space="preserve"
  71.394 +           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"
  71.395 +           x="197.13031"
  71.396 +           y="349.07404"
  71.397 +           id="text3547"><tspan
  71.398 +             sodipodi:role="line"
  71.399 +             id="tspan3549"
  71.400 +             x="197.13031"
  71.401 +             y="349.07404"
  71.402 +             style="font-family:Courier">ff9dc8bc2a8b</tspan></text>
  71.403 +      </g>
  71.404 +      <g
  71.405 +         transform="matrix(0.423343,0,0,0.423343,144.3767,372.6502)"
  71.406 +         id="g3551">
  71.407 +        <rect
  71.408 +           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"
  71.409 +           id="rect3553"
  71.410 +           width="213.85715"
  71.411 +           height="75"
  71.412 +           x="187.5"
  71.413 +           y="363.07654" />
  71.414 +        <text
  71.415 +           xml:space="preserve"
  71.416 +           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"
  71.417 +           x="196.02321"
  71.418 +           y="400.86459"
  71.419 +           id="text3555"><tspan
  71.420 +             sodipodi:role="line"
  71.421 +             id="tspan3557"
  71.422 +             x="196.02321"
  71.423 +             y="400.86459"
  71.424 +             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
  71.425 +        <text
  71.426 +           xml:space="preserve"
  71.427 +           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"
  71.428 +           x="196.71785"
  71.429 +           y="380.17593"
  71.430 +           id="text3559"><tspan
  71.431 +             style="fill:black;fill-opacity:1"
  71.432 +             id="tspan3561"
  71.433 +             sodipodi:role="line"
  71.434 +             x="196.71785"
  71.435 +             y="380.17593">Revision data (delta or snapshot)</tspan></text>
  71.436 +      </g>
  71.437 +    </g>
  71.438 +    <g
  71.439 +       id="g4868"
  71.440 +       transform="translate(-1.676208,-2.342463e-5)">
  71.441 +      <rect
  71.442 +         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"
  71.443 +         id="rect3567"
  71.444 +         width="101.60232"
  71.445 +         height="89.506805"
  71.446 +         x="213.26137"
  71.447 +         y="59.171272" />
  71.448 +      <g
  71.449 +         transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01734)"
  71.450 +         id="g3573">
  71.451 +        <rect
  71.452 +           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"
  71.453 +           id="rect3575"
  71.454 +           width="103.14286"
  71.455 +           height="48.571426"
  71.456 +           x="188.6071"
  71.457 +           y="447.72418" />
  71.458 +        <text
  71.459 +           xml:space="preserve"
  71.460 +           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"
  71.461 +           x="197.82495"
  71.462 +           y="464.82358"
  71.463 +           id="text3577"><tspan
  71.464 +             id="tspan3579"
  71.465 +             sodipodi:role="line"
  71.466 +             x="197.82495"
  71.467 +             y="464.82358">First parent</tspan></text>
  71.468 +        <text
  71.469 +           xml:space="preserve"
  71.470 +           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"
  71.471 +           x="197.13031"
  71.472 +           y="485.51224"
  71.473 +           id="text3581"><tspan
  71.474 +             sodipodi:role="line"
  71.475 +             id="tspan3583"
  71.476 +             x="197.13031"
  71.477 +             y="485.51224"
  71.478 +             style="font-family:Courier">34b8b7a15ea1</tspan></text>
  71.479 +      </g>
  71.480 +      <g
  71.481 +         transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01734)"
  71.482 +         id="g3585">
  71.483 +        <rect
  71.484 +           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"
  71.485 +           id="rect3587"
  71.486 +           width="103.14286"
  71.487 +           height="48.571426"
  71.488 +           x="299.67859"
  71.489 +           y="447.71451" />
  71.490 +        <text
  71.491 +           xml:space="preserve"
  71.492 +           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"
  71.493 +           x="308.89639"
  71.494 +           y="464.8139"
  71.495 +           id="text3589"><tspan
  71.496 +             id="tspan3591"
  71.497 +             sodipodi:role="line"
  71.498 +             x="308.89639"
  71.499 +             y="464.8139">Second parent</tspan></text>
  71.500 +        <text
  71.501 +           xml:space="preserve"
  71.502 +           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"
  71.503 +           x="308.20175"
  71.504 +           y="485.50256"
  71.505 +           id="text3593"><tspan
  71.506 +             sodipodi:role="line"
  71.507 +             id="tspan3595"
  71.508 +             x="308.20175"
  71.509 +             y="485.50256"
  71.510 +             style="font-family:Courier">000000000000</tspan></text>
  71.511 +      </g>
  71.512 +      <g
  71.513 +         transform="matrix(0.423343,0,0,0.423343,138.8739,-67.01733)"
  71.514 +         id="g3597">
  71.515 +        <rect
  71.516 +           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"
  71.517 +           id="rect3599"
  71.518 +           width="103.14286"
  71.519 +           height="48.571426"
  71.520 +           x="188.6071"
  71.521 +           y="311.28598" />
  71.522 +        <text
  71.523 +           xml:space="preserve"
  71.524 +           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"
  71.525 +           x="197.82495"
  71.526 +           y="328.38538"
  71.527 +           id="text3601"><tspan
  71.528 +             id="tspan3603"
  71.529 +             sodipodi:role="line"
  71.530 +             x="197.82495"
  71.531 +             y="328.38538">Revision hash</tspan></text>
  71.532 +        <text
  71.533 +           xml:space="preserve"
  71.534 +           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"
  71.535 +           x="197.13031"
  71.536 +           y="349.07404"
  71.537 +           id="text3605"><tspan
  71.538 +             sodipodi:role="line"
  71.539 +             id="tspan3607"
  71.540 +             x="197.13031"
  71.541 +             y="349.07404"
  71.542 +             style="font-family:Courier">1b67dc96f27a</tspan></text>
  71.543 +      </g>
  71.544 +      <g
  71.545 +         transform="matrix(0.423343,0,0,0.423343,139.3426,-65.65866)"
  71.546 +         id="g3609">
  71.547 +        <rect
  71.548 +           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"
  71.549 +           id="rect3611"
  71.550 +           width="213.85715"
  71.551 +           height="75"
  71.552 +           x="187.5"
  71.553 +           y="363.07654" />
  71.554 +        <text
  71.555 +           xml:space="preserve"
  71.556 +           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"
  71.557 +           x="196.02321"
  71.558 +           y="400.86459"
  71.559 +           id="text3613"><tspan
  71.560 +             sodipodi:role="line"
  71.561 +             id="tspan3615"
  71.562 +             x="196.02321"
  71.563 +             y="400.86459"
  71.564 +             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
  71.565 +        <text
  71.566 +           xml:space="preserve"
  71.567 +           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"
  71.568 +           x="196.71785"
  71.569 +           y="380.17593"
  71.570 +           id="text3617"><tspan
  71.571 +             style="fill:black;fill-opacity:1"
  71.572 +             id="tspan3619"
  71.573 +             sodipodi:role="line"
  71.574 +             x="196.71785"
  71.575 +             y="380.17593">Revision data (delta or snapshot)</tspan></text>
  71.576 +      </g>
  71.577 +    </g>
  71.578 +    <path
  71.579 +       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)"
  71.580 +       d="M 240.78255,143.08593 L 241.42595,171.75349"
  71.581 +       id="path3801"
  71.582 +       inkscape:connector-type="polyline"
  71.583 +       inkscape:connection-start="#g3573"
  71.584 +       inkscape:connection-end="#g3250" />
  71.585 +    <g
  71.586 +       id="g5677">
  71.587 +      <rect
  71.588 +         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"
  71.589 +         id="rect3393"
  71.590 +         width="101.60232"
  71.591 +         height="89.506805"
  71.592 +         x="150.76137"
  71.593 +         y="278.32565" />
  71.594 +      <g
  71.595 +         transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
  71.596 +         id="g3399">
  71.597 +        <rect
  71.598 +           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"
  71.599 +           id="rect3401"
  71.600 +           width="103.14286"
  71.601 +           height="48.571426"
  71.602 +           x="188.6071"
  71.603 +           y="447.72418" />
  71.604 +        <text
  71.605 +           xml:space="preserve"
  71.606 +           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"
  71.607 +           x="197.82495"
  71.608 +           y="464.82358"
  71.609 +           id="text3403"><tspan
  71.610 +             id="tspan3405"
  71.611 +             sodipodi:role="line"
  71.612 +             x="197.82495"
  71.613 +             y="464.82358">First parent</tspan></text>
  71.614 +        <text
  71.615 +           xml:space="preserve"
  71.616 +           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"
  71.617 +           x="197.13031"
  71.618 +           y="485.51224"
  71.619 +           id="text3407"><tspan
  71.620 +             sodipodi:role="line"
  71.621 +             id="tspan3409"
  71.622 +             x="197.13031"
  71.623 +             y="485.51224"
  71.624 +             style="font-family:Courier">ff9dc8bc2a8b</tspan></text>
  71.625 +      </g>
  71.626 +      <g
  71.627 +         transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
  71.628 +         id="g3411">
  71.629 +        <rect
  71.630 +           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"
  71.631 +           id="rect3413"
  71.632 +           width="103.14286"
  71.633 +           height="48.571426"
  71.634 +           x="299.67859"
  71.635 +           y="447.71451" />
  71.636 +        <text
  71.637 +           xml:space="preserve"
  71.638 +           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"
  71.639 +           x="308.89639"
  71.640 +           y="464.8139"
  71.641 +           id="text3415"><tspan
  71.642 +             id="tspan3417"
  71.643 +             sodipodi:role="line"
  71.644 +             x="308.89639"
  71.645 +             y="464.8139">Second parent</tspan></text>
  71.646 +        <text
  71.647 +           xml:space="preserve"
  71.648 +           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"
  71.649 +           x="308.20175"
  71.650 +           y="485.50256"
  71.651 +           id="text3419"><tspan
  71.652 +             sodipodi:role="line"
  71.653 +             id="tspan3421"
  71.654 +             x="308.20175"
  71.655 +             y="485.50256"
  71.656 +             style="font-family:Courier">000000000000</tspan></text>
  71.657 +      </g>
  71.658 +      <g
  71.659 +         transform="matrix(0.423343,0,0,0.423343,76.37397,152.137)"
  71.660 +         id="g3423">
  71.661 +        <rect
  71.662 +           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"
  71.663 +           id="rect3425"
  71.664 +           width="103.14286"
  71.665 +           height="48.571426"
  71.666 +           x="188.6071"
  71.667 +           y="311.28598" />
  71.668 +        <text
  71.669 +           xml:space="preserve"
  71.670 +           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"
  71.671 +           x="197.82495"
  71.672 +           y="328.38538"
  71.673 +           id="text3427"><tspan
  71.674 +             id="tspan3429"
  71.675 +             sodipodi:role="line"
  71.676 +             x="197.82495"
  71.677 +             y="328.38538">Revision hash</tspan></text>
  71.678 +        <text
  71.679 +           xml:space="preserve"
  71.680 +           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"
  71.681 +           x="197.13031"
  71.682 +           y="349.07404"
  71.683 +           id="text3431"><tspan
  71.684 +             sodipodi:role="line"
  71.685 +             id="tspan3433"
  71.686 +             x="197.13031"
  71.687 +             y="349.07404"
  71.688 +             style="font-family:Courier">5b80c922ebdd</tspan></text>
  71.689 +      </g>
  71.690 +      <g
  71.691 +         transform="matrix(0.423343,0,0,0.423343,76.84265,153.4957)"
  71.692 +         id="g3435">
  71.693 +        <rect
  71.694 +           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"
  71.695 +           id="rect3437"
  71.696 +           width="213.85715"
  71.697 +           height="75"
  71.698 +           x="187.5"
  71.699 +           y="363.07654" />
  71.700 +        <text
  71.701 +           xml:space="preserve"
  71.702 +           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"
  71.703 +           x="196.02321"
  71.704 +           y="400.86459"
  71.705 +           id="text3439"><tspan
  71.706 +             sodipodi:role="line"
  71.707 +             id="tspan3441"
  71.708 +             x="196.02321"
  71.709 +             y="400.86459"
  71.710 +             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
  71.711 +        <text
  71.712 +           xml:space="preserve"
  71.713 +           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"
  71.714 +           x="196.71785"
  71.715 +           y="380.17593"
  71.716 +           id="text3443"><tspan
  71.717 +             style="fill:black;fill-opacity:1"
  71.718 +             id="tspan3445"
  71.719 +             sodipodi:role="line"
  71.720 +             x="196.71785"
  71.721 +             y="380.17593">Revision data (delta or snapshot)</tspan></text>
  71.722 +      </g>
  71.723 +    </g>
  71.724 +    <g
  71.725 +       id="g5646"
  71.726 +       transform="translate(-0.227432,0)">
  71.727 +      <rect
  71.728 +         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"
  71.729 +         id="rect3451"
  71.730 +         width="101.60232"
  71.731 +         height="89.506805"
  71.732 +         x="272.63638"
  71.733 +         y="278.32565" />
  71.734 +      <g
  71.735 +         transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)"
  71.736 +         id="g3457">
  71.737 +        <rect
  71.738 +           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"
  71.739 +           id="rect3459"
  71.740 +           width="103.14286"
  71.741 +           height="48.571426"
  71.742 +           x="188.6071"
  71.743 +           y="447.72418" />
  71.744 +        <text
  71.745 +           xml:space="preserve"
  71.746 +           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"
  71.747 +           x="197.82495"
  71.748 +           y="464.82358"
  71.749 +           id="text3461"><tspan
  71.750 +             id="tspan3463"
  71.751 +             sodipodi:role="line"
  71.752 +             x="197.82495"
  71.753 +             y="464.82358">First parent</tspan></text>
  71.754 +        <text
  71.755 +           xml:space="preserve"
  71.756 +           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"
  71.757 +           x="197.13031"
  71.758 +           y="485.51224"
  71.759 +           id="text3465"><tspan
  71.760 +             sodipodi:role="line"
  71.761 +             id="tspan3467"
  71.762 +             x="197.13031"
  71.763 +             y="485.51224"
  71.764 +             style="font-family:Courier">ecacb6b4c9fd</tspan></text>
  71.765 +      </g>
  71.766 +      <g
  71.767 +         transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)"
  71.768 +         id="g3469">
  71.769 +        <rect
  71.770 +           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"
  71.771 +           id="rect3471"
  71.772 +           width="103.14286"
  71.773 +           height="48.571426"
  71.774 +           x="299.67859"
  71.775 +           y="447.71451" />
  71.776 +        <text
  71.777 +           xml:space="preserve"
  71.778 +           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"
  71.779 +           x="308.89639"
  71.780 +           y="464.8139"
  71.781 +           id="text3473"><tspan
  71.782 +             id="tspan3475"
  71.783 +             sodipodi:role="line"
  71.784 +             x="308.89639"
  71.785 +             y="464.8139">Second parent</tspan></text>
  71.786 +        <text
  71.787 +           xml:space="preserve"
  71.788 +           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"
  71.789 +           x="308.20175"
  71.790 +           y="485.50256"
  71.791 +           id="text3477"><tspan
  71.792 +             sodipodi:role="line"
  71.793 +             id="tspan3479"
  71.794 +             x="308.20175"
  71.795 +             y="485.50256"
  71.796 +             style="font-family:Courier">000000000000</tspan></text>
  71.797 +      </g>
  71.798 +      <g
  71.799 +         transform="matrix(0.423343,0,0,0.423343,198.2489,152.137)"
  71.800 +         id="g3481">
  71.801 +        <rect
  71.802 +           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"
  71.803 +           id="rect3483"
  71.804 +           width="103.14286"
  71.805 +           height="48.571426"
  71.806 +           x="188.6071"
  71.807 +           y="311.28598" />
  71.808 +        <text
  71.809 +           xml:space="preserve"
  71.810 +           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"
  71.811 +           x="197.82495"
  71.812 +           y="328.38538"
  71.813 +           id="text3485"><tspan
  71.814 +             id="tspan3487"
  71.815 +             sodipodi:role="line"
  71.816 +             x="197.82495"
  71.817 +             y="328.38538">Revision hash</tspan></text>
  71.818 +        <text
  71.819 +           xml:space="preserve"
  71.820 +           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"
  71.821 +           x="197.13031"
  71.822 +           y="349.07404"
  71.823 +           id="text3489"><tspan
  71.824 +             sodipodi:role="line"
  71.825 +             id="tspan3491"
  71.826 +             x="197.13031"
  71.827 +             y="349.07404"
  71.828 +             style="font-family:Courier">32bf9a5f22c0</tspan></text>
  71.829 +      </g>
  71.830 +      <g
  71.831 +         transform="matrix(0.423343,0,0,0.423343,198.7176,153.4957)"
  71.832 +         id="g3493">
  71.833 +        <rect
  71.834 +           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"
  71.835 +           id="rect3495"
  71.836 +           width="213.85715"
  71.837 +           height="75"
  71.838 +           x="187.5"
  71.839 +           y="363.07654" />
  71.840 +        <text
  71.841 +           xml:space="preserve"
  71.842 +           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"
  71.843 +           x="196.02321"
  71.844 +           y="400.86459"
  71.845 +           id="text3497"><tspan
  71.846 +             sodipodi:role="line"
  71.847 +             id="tspan3499"
  71.848 +             x="196.02321"
  71.849 +             y="400.86459"
  71.850 +             style="fill:black;fill-opacity:1;font-family:Courier">...</tspan></text>
  71.851 +        <text
  71.852 +           xml:space="preserve"
  71.853 +           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"
  71.854 +           x="196.71785"
  71.855 +           y="380.17593"
  71.856 +           id="text3501"><tspan
  71.857 +             style="fill:black;fill-opacity:1"
  71.858 +             id="tspan3503"
  71.859 +             sodipodi:role="line"
  71.860 +             x="196.71785"
  71.861 +             y="380.17593">Revision data (delta or snapshot)</tspan></text>
  71.862 +      </g>
  71.863 +    </g>
  71.864 +    <rect
  71.865 +       y="387.90286"
  71.866 +       x="272.40894"
  71.867 +       height="89.506805"
  71.868 +       width="101.60232"
  71.869 +       id="rect5081"
  71.870 +       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" />
  71.871 +    <g
  71.872 +       id="g5087"
  71.873 +       transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)">
  71.874 +      <rect
  71.875 +         y="447.72418"
  71.876 +         x="188.6071"
  71.877 +         height="48.571426"
  71.878 +         width="103.14286"
  71.879 +         id="rect5089"
  71.880 +         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" />
  71.881 +      <text
  71.882 +         id="text5091"
  71.883 +         y="464.82358"
  71.884 +         x="197.82495"
  71.885 +         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"
  71.886 +         xml:space="preserve"><tspan
  71.887 +           y="464.82358"
  71.888 +           x="197.82495"
  71.889 +           sodipodi:role="line"
  71.890 +           id="tspan5093">First parent</tspan></text>
  71.891 +      <text
  71.892 +         id="text5095"
  71.893 +         y="485.51224"
  71.894 +         x="197.13031"
  71.895 +         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"
  71.896 +         xml:space="preserve"><tspan
  71.897 +           style="font-family:Courier"
  71.898 +           y="485.51224"
  71.899 +           x="197.13031"
  71.900 +           id="tspan5097"
  71.901 +           sodipodi:role="line">ff9dc8bc2a8b</tspan></text>
  71.902 +    </g>
  71.903 +    <g
  71.904 +       id="g5099"
  71.905 +       transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)">
  71.906 +      <rect
  71.907 +         y="447.71451"
  71.908 +         x="299.67859"
  71.909 +         height="48.571426"
  71.910 +         width="103.14286"
  71.911 +         id="rect5101"
  71.912 +         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" />
  71.913 +      <text
  71.914 +         id="text5103"
  71.915 +         y="464.8139"
  71.916 +         x="308.89639"
  71.917 +         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"
  71.918 +         xml:space="preserve"><tspan
  71.919 +           y="464.8139"
  71.920 +           x="308.89639"
  71.921 +           sodipodi:role="line"
  71.922 +           id="tspan5105">Second parent</tspan></text>
  71.923 +      <text
  71.924 +         id="text5107"
  71.925 +         y="485.50256"
  71.926 +         x="308.20175"
  71.927 +         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"
  71.928 +         xml:space="preserve"><tspan
  71.929 +           style="font-family:Courier"
  71.930 +           y="485.50256"
  71.931 +           x="308.20175"
  71.932 +           id="tspan5109"
  71.933 +           sodipodi:role="line">000000000000</tspan></text>
  71.934 +    </g>
  71.935 +    <g
  71.936 +       id="g5111"
  71.937 +       transform="matrix(0.423343,0,0,0.423343,198.0214,261.7142)">
  71.938 +      <rect
  71.939 +         y="311.28598"
  71.940 +         x="188.6071"
  71.941 +         height="48.571426"
  71.942 +         width="103.14286"
  71.943 +         id="rect5113"
  71.944 +         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" />
  71.945 +      <text
  71.946 +         id="text5115"
  71.947 +         y="328.38538"
  71.948 +         x="197.82495"
  71.949 +         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"
  71.950 +         xml:space="preserve"><tspan
  71.951 +           y="328.38538"
  71.952 +           x="197.82495"
  71.953 +           sodipodi:role="line"
  71.954 +           id="tspan5117">Revision hash</tspan></text>
  71.955 +      <text
  71.956 +         id="text5119"
  71.957 +         y="349.07404"
  71.958 +         x="197.13031"
  71.959 +         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"
  71.960 +         xml:space="preserve"><tspan
  71.961 +           style="font-family:Courier"
  71.962 +           y="349.07404"
  71.963 +           x="197.13031"
  71.964 +           id="tspan5121"
  71.965 +           sodipodi:role="line">ecacb6b4c9fd</tspan></text>
  71.966 +    </g>
  71.967 +    <g
  71.968 +       id="g5123"
  71.969 +       transform="matrix(0.423343,0,0,0.423343,198.4901,263.0729)">
  71.970 +      <rect
  71.971 +         y="363.07654"
  71.972 +         x="187.5"
  71.973 +         height="75"
  71.974 +         width="213.85715"
  71.975 +         id="rect5125"
  71.976 +         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" />
  71.977 +      <text
  71.978 +         id="text5127"
  71.979 +         y="400.86459"
  71.980 +         x="196.02321"
  71.981 +         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"
  71.982 +         xml:space="preserve"><tspan
  71.983 +           style="fill:black;fill-opacity:1;font-family:Courier"
  71.984 +           y="400.86459"
  71.985 +           x="196.02321"
  71.986 +           id="tspan5129"
  71.987 +           sodipodi:role="line">...</tspan></text>
  71.988 +      <text
  71.989 +         id="text5131"
  71.990 +         y="380.17593"
  71.991 +         x="196.71785"
  71.992 +         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"
  71.993 +         xml:space="preserve"><tspan
  71.994 +           y="380.17593"
  71.995 +           x="196.71785"
  71.996 +           sodipodi:role="line"
  71.997 +           id="tspan5133"
  71.998 +           style="fill:black;fill-opacity:1">Revision data (delta or snapshot)</tspan></text>
  71.999 +    </g>
 71.1000 +    <path
 71.1001 +       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"
 71.1002 +       d="M 299.69935,362.24027 L 299.69931,393.49494"
 71.1003 +       id="path5203"
 71.1004 +       inkscape:connector-type="polyline"
 71.1005 +       inkscape:connection-start="#g3457"
 71.1006 +       inkscape:connection-end="#g5111" />
 71.1007 +    <path
 71.1008 +       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"
 71.1009 +       d="M 182.35357,362.22647 L 241.2842,503.07224"
 71.1010 +       id="path5271"
 71.1011 +       inkscape:connector-type="polyline"
 71.1012 +       inkscape:connection-start="#g3399"
 71.1013 +       inkscape:connection-end="#g3539" />
 71.1014 +    <path
 71.1015 +       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"
 71.1016 +       d="M 287.63109,471.81747 L 250.9438,503.07223"
 71.1017 +       id="path5285"
 71.1018 +       inkscape:connector-type="polyline"
 71.1019 +       inkscape:connection-start="#g5087"
 71.1020 +       inkscape:connection-end="#g3539" />
 71.1021 +    <path
 71.1022 +       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)"
 71.1023 +       d="M 290.80419,250.07192 L 297.80065,283.90394"
 71.1024 +       id="path5077"
 71.1025 +       inkscape:connector-type="polyline"
 71.1026 +       inkscape:connection-start="#g3215"
 71.1027 +       inkscape:connection-end="#g3481" />
 71.1028 +    <path
 71.1029 +       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)"
 71.1030 +       d="M 229.63373,250.07601 L 190.07484,283.90394"
 71.1031 +       id="path5075"
 71.1032 +       inkscape:connector-type="polyline"
 71.1033 +       inkscape:connection-end="#g3423" />
 71.1034 +    <text
 71.1035 +       xml:space="preserve"
 71.1036 +       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"
 71.1037 +       x="131.5625"
 71.1038 +       y="100.79968"
 71.1039 +       id="text5897"><tspan
 71.1040 +         sodipodi:role="line"
 71.1041 +         id="tspan5899"
 71.1042 +         x="131.5625"
 71.1043 +         y="100.79968"
 71.1044 +         style="text-align:end;text-anchor:end">Head revision</tspan><tspan
 71.1045 +         sodipodi:role="line"
 71.1046 +         x="131.5625"
 71.1047 +         y="115.79968"
 71.1048 +         id="tspan5901"
 71.1049 +         style="text-align:end;text-anchor:end">(no children)</tspan></text>
 71.1050 +    <text
 71.1051 +       xml:space="preserve"
 71.1052 +       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"
 71.1053 +       x="131.5625"
 71.1054 +       y="207.04968"
 71.1055 +       id="text5903"><tspan
 71.1056 +         sodipodi:role="line"
 71.1057 +         id="tspan5905"
 71.1058 +         x="131.5625"
 71.1059 +         y="207.04968"
 71.1060 +         style="text-align:end;text-anchor:end">Merge revision</tspan><tspan
 71.1061 +         sodipodi:role="line"
 71.1062 +         x="131.5625"
 71.1063 +         y="222.04968"
 71.1064 +         id="tspan5907"
 71.1065 +         style="text-align:end;text-anchor:end">(two parents)</tspan></text>
 71.1066 +    <text
 71.1067 +       xml:space="preserve"
 71.1068 +       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"
 71.1069 +       x="131.92578"
 71.1070 +       y="451.58093"
 71.1071 +       id="text5909"><tspan
 71.1072 +         sodipodi:role="line"
 71.1073 +         id="tspan5911"
 71.1074 +         x="131.92578"
 71.1075 +         y="451.58093"
 71.1076 +         style="text-align:end;text-anchor:end">Branches</tspan><tspan
 71.1077 +         sodipodi:role="line"
 71.1078 +         x="131.92578"
 71.1079 +         y="466.58093"
 71.1080 +         id="tspan5913"
 71.1081 +         style="text-align:end;text-anchor:end">(two revisions,</tspan><tspan
 71.1082 +         sodipodi:role="line"
 71.1083 +         x="131.92578"
 71.1084 +         y="481.58093"
 71.1085 +         id="tspan5915"
 71.1086 +         style="text-align:end;text-anchor:end">same parent)</tspan></text>
 71.1087 +    <path
 71.1088 +       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"
 71.1089 +       d="M 111.71875,433.61218 L 154.7268,368.52294"
 71.1090 +       id="path5917"
 71.1091 +       inkscape:connector-type="polyline" />
 71.1092 +    <path
 71.1093 +       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"
 71.1094 +       d="M 134.375,464.86218 L 277.86691,440.37816"
 71.1095 +       id="path5919"
 71.1096 +       inkscape:connector-type="polyline"
 71.1097 +       inkscape:connection-end="#g5123" />
 71.1098 +    <text
 71.1099 +       xml:space="preserve"
 71.1100 +       style="font-size:12px;font-style:normal;font-weight:normal;text-align:end;text-anchor:end;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
 71.1101 +       x="131.5625"
 71.1102 +       y="536.73718"
 71.1103 +       id="text5927"><tspan
 71.1104 +         sodipodi:role="line"
 71.1105 +         id="tspan5929"
 71.1106 +         x="131.5625"
 71.1107 +         y="536.73718">First revision</tspan><tspan
 71.1108 +         sodipodi:role="line"
 71.1109 +         x="131.5625"
 71.1110 +         y="551.73718"
 71.1111 +         id="tspan5931">(both parents null)</tspan></text>
 71.1112 +    <rect
 71.1113 +       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"
 71.1114 +       id="rect2830"
 71.1115 +       width="43.664806"
 71.1116 +       height="20.562374"
 71.1117 +       x="217.0432"
 71.1118 +       y="232.10075" />
 71.1119 +    <text
 71.1120 +       xml:space="preserve"
 71.1121 +       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"
 71.1122 +       x="220.94551"
 71.1123 +       y="239.33966"
 71.1124 +       id="text2832"><tspan
 71.1125 +         id="tspan2836"
 71.1126 +         sodipodi:role="line"
 71.1127 +         x="220.94551"
 71.1128 +         y="239.33966">First parent</tspan></text>
 71.1129 +    <text
 71.1130 +       xml:space="preserve"
 71.1131 +       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"
 71.1132 +       x="220.65144"
 71.1133 +       y="248.09805"
 71.1134 +       id="text2879"><tspan
 71.1135 +         sodipodi:role="line"
 71.1136 +         id="tspan2881"
 71.1137 +         x="220.65144"
 71.1138 +         y="248.09805"
 71.1139 +         style="font-family:Courier">5b80c922ebdd</tspan></text>
 71.1140 +    <path
 71.1141 +       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"
 71.1142 +       d="M 139.84375,107.83093 L 210.15625,107.83093"
 71.1143 +       id="path5965"
 71.1144 +       inkscape:connector-type="polyline" />
 71.1145 +    <path
 71.1146 +       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"
 71.1147 +       d="M 137.5,213.29968 L 210.49036,214.09055"
 71.1148 +       id="path5967"
 71.1149 +       inkscape:connector-type="polyline" />
 71.1150 +    <path
 71.1151 +       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"
 71.1152 +       d="M 136.34375,544.54968 L 206.65625,544.54968"
 71.1153 +       id="path5969"
 71.1154 +       inkscape:connector-type="polyline"
 71.1155 +       inkscape:transform-center-y="-171.09375"
 71.1156 +       inkscape:transform-center-x="53.90625" />
 71.1157 +  </g>
 71.1158 +</svg>
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/fr/snapshot.svg	Thu Feb 05 12:37:03 2009 +0100
    72.3 @@ -0,0 +1,202 @@
    72.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    72.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    72.6 +<svg
    72.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    72.8 +   xmlns:cc="http://web.resource.org/cc/"
    72.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   72.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   72.11 +   xmlns="http://www.w3.org/2000/svg"
   72.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   72.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   72.14 +   width="744.09448819"
   72.15 +   height="1052.3622047"
   72.16 +   id="svg2807"
   72.17 +   sodipodi:version="0.32"
   72.18 +   inkscape:version="0.44.1"
   72.19 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
   72.20 +   sodipodi:docname="snapshots.svg">
   72.21 +  <defs
   72.22 +     id="defs2809" />
   72.23 +  <sodipodi:namedview
   72.24 +     id="base"
   72.25 +     pagecolor="#ffffff"
   72.26 +     bordercolor="#666666"
   72.27 +     borderopacity="1.0"
   72.28 +     gridtolerance="10000"
   72.29 +     guidetolerance="10"
   72.30 +     objecttolerance="10"
   72.31 +     inkscape:pageopacity="0.0"
   72.32 +     inkscape:pageshadow="2"
   72.33 +     inkscape:zoom="1.4"
   72.34 +     inkscape:cx="252.04111"
   72.35 +     inkscape:cy="605.75448"
   72.36 +     inkscape:document-units="px"
   72.37 +     inkscape:current-layer="layer1"
   72.38 +     inkscape:window-width="906"
   72.39 +     inkscape:window-height="721"
   72.40 +     inkscape:window-x="0"
   72.41 +     inkscape:window-y="25" />
   72.42 +  <metadata
   72.43 +     id="metadata2812">
   72.44 +    <rdf:RDF>
   72.45 +      <cc:Work
   72.46 +         rdf:about="">
   72.47 +        <dc:format>image/svg+xml</dc:format>
   72.48 +        <dc:type
   72.49 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   72.50 +      </cc:Work>
   72.51 +    </rdf:RDF>
   72.52 +  </metadata>
   72.53 +  <g
   72.54 +     inkscape:label="Layer 1"
   72.55 +     inkscape:groupmode="layer"
   72.56 +     id="layer1">
   72.57 +    <rect
   72.58 +       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"
   72.59 +       id="rect2817"
   72.60 +       width="118.18347"
   72.61 +       height="245.32632"
   72.62 +       x="243.05112"
   72.63 +       y="315.4133"
   72.64 +       inkscape:transform-center-x="136.84403"
   72.65 +       inkscape:transform-center-y="-66.529183" />
   72.66 +    <rect
   72.67 +       y="315.04153"
   72.68 +       x="46.965065"
   72.69 +       height="97.803009"
   72.70 +       width="108.92702"
   72.71 +       id="rect2815"
   72.72 +       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" />
   72.73 +    <g
   72.74 +       id="g3814">
   72.75 +      <rect
   72.76 +         y="348.94302"
   72.77 +         x="59.285713"
   72.78 +         height="30"
   72.79 +         width="84.285713"
   72.80 +         id="rect2819"
   72.81 +         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"
   72.82 +         ry="0" />
   72.83 +      <text
   72.84 +         id="text2821"
   72.85 +         y="368.02701"
   72.86 +         x="72.717636"
   72.87 +         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"
   72.88 +         xml:space="preserve"><tspan
   72.89 +           y="368.02701"
   72.90 +           x="72.717636"
   72.91 +           id="tspan2823"
   72.92 +           sodipodi:role="line">Index, rev 7</tspan></text>
   72.93 +    </g>
   72.94 +    <text
   72.95 +       id="text3722"
   72.96 +       y="301.29074"
   72.97 +       x="46.187778"
   72.98 +       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"
   72.99 +       xml:space="preserve"><tspan
  72.100 +         y="301.29074"
  72.101 +         x="46.187778"
  72.102 +         id="tspan3724"
  72.103 +         sodipodi:role="line">Revlog index (.i file)</tspan></text>
  72.104 +    <text
  72.105 +       id="text3726"
  72.106 +       y="301.29074"
  72.107 +       x="241.90207"
  72.108 +       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"
  72.109 +       xml:space="preserve"><tspan
  72.110 +         y="301.29074"
  72.111 +         x="241.90207"
  72.112 +         id="tspan3728"
  72.113 +         sodipodi:role="line">Revlog data (.d file)</tspan></text>
  72.114 +    <path
  72.115 +       style="fill:#c695ff;fill-opacity:0.60109288;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
  72.116 +       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 "
  72.117 +       id="path3839"
  72.118 +       sodipodi:nodetypes="ccccc" />
  72.119 +    <rect
  72.120 +       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"
  72.121 +       id="rect3752"
  72.122 +       width="92.720184"
  72.123 +       height="67.005905"
  72.124 +       x="255.42564"
  72.125 +       y="368.64264" />
  72.126 +    <text
  72.127 +       xml:space="preserve"
  72.128 +       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"
  72.129 +       x="264.45859"
  72.130 +       y="387.30099"
  72.131 +       id="text3754"><tspan
  72.132 +         sodipodi:role="line"
  72.133 +         id="tspan3756"
  72.134 +         x="264.45859"
  72.135 +         y="387.30099">Snapshot, rev 4</tspan></text>
  72.136 +    <rect
  72.137 +       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"
  72.138 +       id="rect3761"
  72.139 +       width="93.49366"
  72.140 +       height="29.922237"
  72.141 +       x="255.03891"
  72.142 +       y="442.04395" />
  72.143 +    <text
  72.144 +       xml:space="preserve"
  72.145 +       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"
  72.146 +       x="263.2662"
  72.147 +       y="460.17206"
  72.148 +       id="text3763"><tspan
  72.149 +         sodipodi:role="line"
  72.150 +         id="tspan3765"
  72.151 +         x="263.2662"
  72.152 +         y="460.17206">Delta, rev 4 to 5</tspan></text>
  72.153 +    <rect
  72.154 +       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"
  72.155 +       id="rect3774"
  72.156 +       width="93.49366"
  72.157 +       height="29.922237"
  72.158 +       x="255.03891"
  72.159 +       y="477.97485" />
  72.160 +    <text
  72.161 +       xml:space="preserve"
  72.162 +       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"
  72.163 +       x="263.2662"
  72.164 +       y="496.10297"
  72.165 +       id="text3776"><tspan
  72.166 +         sodipodi:role="line"
  72.167 +         id="tspan3778"
  72.168 +         x="263.2662"
  72.169 +         y="496.10297">Delta, rev 5 to 6</tspan></text>
  72.170 +    <rect
  72.171 +       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"
  72.172 +       id="rect3782"
  72.173 +       width="93.49366"
  72.174 +       height="29.922237"
  72.175 +       x="255.03891"
  72.176 +       y="513.90576" />
  72.177 +    <text
  72.178 +       xml:space="preserve"
  72.179 +       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"
  72.180 +       x="263.2662"
  72.181 +       y="532.03387"
  72.182 +       id="text3784"><tspan
  72.183 +         sodipodi:role="line"
  72.184 +         id="tspan3786"
  72.185 +         x="263.2662"
  72.186 +         y="532.03387">Delta, rev 6 to 7</tspan></text>
  72.187 +    <rect
  72.188 +       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"
  72.189 +       id="rect3889"
  72.190 +       width="93.49366"
  72.191 +       height="29.922237"
  72.192 +       x="255.03891"
  72.193 +       y="332.32489" />
  72.194 +    <text
  72.195 +       xml:space="preserve"
  72.196 +       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"
  72.197 +       x="263.2662"
  72.198 +       y="350.453"
  72.199 +       id="text3891"><tspan
  72.200 +         sodipodi:role="line"
  72.201 +         id="tspan3893"
  72.202 +         x="263.2662"
  72.203 +         y="350.453">Delta, rev 2 to 3</tspan></text>
  72.204 +  </g>
  72.205 +</svg>
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/fr/srcinstall.tex	Thu Feb 05 12:37:03 2009 +0100
    73.3 @@ -0,0 +1,53 @@
    73.4 +\chapter{Installing Mercurial from source}
    73.5 +\label{chap:srcinstall}
    73.6 +
    73.7 +\section{On a Unix-like system}
    73.8 +\label{sec:srcinstall:unixlike}
    73.9 +
   73.10 +If you are using a Unix-like system that has a sufficiently recent
   73.11 +version of Python (2.3~or newer) available, it is easy to install
   73.12 +Mercurial from source.
   73.13 +\begin{enumerate}
   73.14 +\item Download a recent source tarball from
   73.15 +  \url{http://www.selenic.com/mercurial/download}.
   73.16 +\item Unpack the tarball:
   73.17 +  \begin{codesample4}
   73.18 +    gzip -dc mercurial-\emph{version}.tar.gz | tar xf -
   73.19 +  \end{codesample4}
   73.20 +\item Go into the source directory and run the installer script.  This
   73.21 +  will build Mercurial and install it in your home directory.
   73.22 +  \begin{codesample4}
   73.23 +    cd mercurial-\emph{version}
   73.24 +    python setup.py install --force --home=\$HOME
   73.25 +  \end{codesample4}
   73.26 +\end{enumerate}
   73.27 +Once the install finishes, Mercurial will be in the \texttt{bin}
   73.28 +subdirectory of your home directory.  Don't forget to make sure that
   73.29 +this directory is present in your shell's search path.
   73.30 +
   73.31 +You will probably need to set the \envar{PYTHONPATH} environment
   73.32 +variable so that the Mercurial executable can find the rest of the
   73.33 +Mercurial packages.  For example, on my laptop, I have set it to
   73.34 +\texttt{/home/bos/lib/python}.  The exact path that you will need to
   73.35 +use depends on how Python was built for your system, but should be
   73.36 +easy to figure out.  If you're uncertain, look through the output of
   73.37 +the installer script above, and see where the contents of the
   73.38 +\texttt{mercurial} directory were installed to.
   73.39 +
   73.40 +\section{On Windows}
   73.41 +
   73.42 +Building and installing Mercurial on Windows requires a variety of
   73.43 +tools, a fair amount of technical knowledge, and considerable
   73.44 +patience.  I very much \emph{do not recommend} this route if you are a
   73.45 +``casual user''.  Unless you intend to hack on Mercurial, I strongly
   73.46 +suggest that you use a binary package instead.
   73.47 +
   73.48 +If you are intent on building Mercurial from source on Windows, follow
   73.49 +the ``hard way'' directions on the Mercurial wiki at
   73.50 +\url{http://www.selenic.com/mercurial/wiki/index.cgi/WindowsInstall},
   73.51 +and expect the process to involve a lot of fiddly work.
   73.52 +
   73.53 +%%% Local Variables: 
   73.54 +%%% mode: latex
   73.55 +%%% TeX-master: "00book"
   73.56 +%%% End: 
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/fr/template.tex	Thu Feb 05 12:37:03 2009 +0100
    74.3 @@ -0,0 +1,475 @@
    74.4 +\chapter{Customising the output of Mercurial}
    74.5 +\label{chap:template}
    74.6 +
    74.7 +Mercurial provides a powerful mechanism to let you control how it
    74.8 +displays information.  The mechanism is based on templates.  You can
    74.9 +use templates to generate specific output for a single command, or to
   74.10 +customise the entire appearance of the built-in web interface.
   74.11 +
   74.12 +\section{Using precanned output styles}
   74.13 +\label{sec:style}
   74.14 +
   74.15 +Packaged with Mercurial are some output styles that you can use
   74.16 +immediately.  A style is simply a precanned template that someone
   74.17 +wrote and installed somewhere that Mercurial can find.
   74.18 +
   74.19 +Before we take a look at Mercurial's bundled styles, let's review its
   74.20 +normal output.
   74.21 +
   74.22 +\interaction{template.simple.normal}
   74.23 +
   74.24 +This is somewhat informative, but it takes up a lot of space---five
   74.25 +lines of output per changeset.  The \texttt{compact} style reduces
   74.26 +this to three lines, presented in a sparse manner.
   74.27 +
   74.28 +\interaction{template.simple.compact}
   74.29 +
   74.30 +The \texttt{changelog} style hints at the expressive power of
   74.31 +Mercurial's templating engine.  This style attempts to follow the GNU
   74.32 +Project's changelog guidelines\cite{web:changelog}.
   74.33 +
   74.34 +\interaction{template.simple.changelog}
   74.35 +
   74.36 +You will not be shocked to learn that Mercurial's default output style
   74.37 +is named \texttt{default}.
   74.38 +
   74.39 +\subsection{Setting a default style}
   74.40 +
   74.41 +You can modify the output style that Mercurial will use for every
   74.42 +command by editing your \hgrc\ file, naming the style you would
   74.43 +prefer to use.
   74.44 +
   74.45 +\begin{codesample2}
   74.46 +  [ui]
   74.47 +  style = compact
   74.48 +\end{codesample2}
   74.49 +
   74.50 +If you write a style of your own, you can use it by either providing
   74.51 +the path to your style file, or copying your style file into a
   74.52 +location where Mercurial can find it (typically the \texttt{templates}
   74.53 +subdirectory of your Mercurial install directory).
   74.54 +
   74.55 +\section{Commands that support styles and templates}
   74.56 +
   74.57 +All of Mercurial's ``\texttt{log}-like'' commands let you use styles
   74.58 +and templates: \hgcmd{incoming}, \hgcmd{log}, \hgcmd{outgoing}, and
   74.59 +\hgcmd{tip}.
   74.60 +
   74.61 +As I write this manual, these are so far the only commands that
   74.62 +support styles and templates.  Since these are the most important
   74.63 +commands that need customisable output, there has been little pressure
   74.64 +from the Mercurial user community to add style and template support to
   74.65 +other commands.
   74.66 +
   74.67 +\section{The basics of templating}
   74.68 +
   74.69 +At its simplest, a Mercurial template is a piece of text.  Some of the
   74.70 +text never changes, while other parts are \emph{expanded}, or replaced
   74.71 +with new text, when necessary.
   74.72 +
   74.73 +Before we continue, let's look again at a simple example of
   74.74 +Mercurial's normal output.
   74.75 +
   74.76 +\interaction{template.simple.normal}
   74.77 +
   74.78 +Now, let's run the same command, but using a template to change its
   74.79 +output.
   74.80 +
   74.81 +\interaction{template.simple.simplest}
   74.82 +
   74.83 +The example above illustrates the simplest possible template; it's
   74.84 +just a piece of static text, printed once for each changeset.  The
   74.85 +\hgopt{log}{--template} option to the \hgcmd{log} command tells
   74.86 +Mercurial to use the given text as the template when printing each
   74.87 +changeset.
   74.88 +
   74.89 +Notice that the template string above ends with the text
   74.90 +``\Verb+\n+''.  This is an \emph{escape sequence}, telling Mercurial
   74.91 +to print a newline at the end of each template item.  If you omit this
   74.92 +newline, Mercurial will run each piece of output together.  See
   74.93 +section~\ref{sec:template:escape} for more details of escape sequences.
   74.94 +
   74.95 +A template that prints a fixed string of text all the time isn't very
   74.96 +useful; let's try something a bit more complex.
   74.97 +
   74.98 +\interaction{template.simple.simplesub}
   74.99 +
  74.100 +As you can see, the string ``\Verb+{desc}+'' in the template has been
  74.101 +replaced in the output with the description of each changeset.  Every
  74.102 +time Mercurial finds text enclosed in curly braces (``\texttt{\{}''
  74.103 +and ``\texttt{\}}''), it will try to replace the braces and text with
  74.104 +the expansion of whatever is inside.  To print a literal curly brace,
  74.105 +you must escape it, as described in section~\ref{sec:template:escape}.
  74.106 +
  74.107 +\section{Common template keywords}
  74.108 +\label{sec:template:keyword}
  74.109 +
  74.110 +You can start writing simple templates immediately using the keywords
  74.111 +below.
  74.112 +
  74.113 +\begin{itemize}
  74.114 +\item[\tplkword{author}] String.  The unmodified author of the changeset.
  74.115 +\item[\tplkword{branches}] String.  The name of the branch on which
  74.116 +  the changeset was committed.  Will be empty if the branch name was
  74.117 +  \texttt{default}.
  74.118 +\item[\tplkword{date}] Date information.  The date when the changeset
  74.119 +  was committed.  This is \emph{not} human-readable; you must pass it
  74.120 +  through a filter that will render it appropriately.  See
  74.121 +  section~\ref{sec:template:filter} for more information on filters.
  74.122 +  The date is expressed as a pair of numbers.  The first number is a
  74.123 +  Unix UTC timestamp (seconds since January 1, 1970); the second is
  74.124 +  the offset of the committer's timezone from UTC, in seconds.
  74.125 +\item[\tplkword{desc}] String.  The text of the changeset description.
  74.126 +\item[\tplkword{files}] List of strings.  All files modified, added, or
  74.127 +  removed by this changeset.
  74.128 +\item[\tplkword{file\_adds}] List of strings.  Files added by this
  74.129 +  changeset.
  74.130 +\item[\tplkword{file\_dels}] List of strings.  Files removed by this
  74.131 +  changeset.
  74.132 +\item[\tplkword{node}] String.  The changeset identification hash, as a
  74.133 +  40-character hexadecimal string.
  74.134 +\item[\tplkword{parents}] List of strings.  The parents of the
  74.135 +  changeset.
  74.136 +\item[\tplkword{rev}] Integer.  The repository-local changeset revision
  74.137 +  number.
  74.138 +\item[\tplkword{tags}] List of strings.  Any tags associated with the
  74.139 +  changeset.
  74.140 +\end{itemize}
  74.141 +
  74.142 +A few simple experiments will show us what to expect when we use these
  74.143 +keywords; you can see the results in
  74.144 +figure~\ref{fig:template:keywords}.
  74.145 +
  74.146 +\begin{figure}
  74.147 +  \interaction{template.simple.keywords}
  74.148 +  \caption{Template keywords in use}
  74.149 +  \label{fig:template:keywords}
  74.150 +\end{figure}
  74.151 +
  74.152 +As we noted above, the date keyword does not produce human-readable
  74.153 +output, so we must treat it specially.  This involves using a
  74.154 +\emph{filter}, about which more in section~\ref{sec:template:filter}.
  74.155 +
  74.156 +\interaction{template.simple.datekeyword}
  74.157 +
  74.158 +\section{Escape sequences}
  74.159 +\label{sec:template:escape}
  74.160 +
  74.161 +Mercurial's templating engine recognises the most commonly used escape
  74.162 +sequences in strings.  When it sees a backslash (``\Verb+\+'')
  74.163 +character, it looks at the following character and substitutes the two
  74.164 +characters with a single replacement, as described below.
  74.165 +
  74.166 +\begin{itemize}
  74.167 +\item[\Verb+\textbackslash\textbackslash+] Backslash, ``\Verb+\+'',
  74.168 +  ASCII~134.
  74.169 +\item[\Verb+\textbackslash n+] Newline, ASCII~12.
  74.170 +\item[\Verb+\textbackslash r+] Carriage return, ASCII~15.
  74.171 +\item[\Verb+\textbackslash t+] Tab, ASCII~11.
  74.172 +\item[\Verb+\textbackslash v+] Vertical tab, ASCII~13.
  74.173 +\item[\Verb+\textbackslash \{+] Open curly brace, ``\Verb+{+'', ASCII~173.
  74.174 +\item[\Verb+\textbackslash \}+] Close curly brace, ``\Verb+}+'', ASCII~175.
  74.175 +\end{itemize}
  74.176 +
  74.177 +As indicated above, if you want the expansion of a template to contain
  74.178 +a literal ``\Verb+\+'', ``\Verb+{+'', or ``\Verb+{+'' character, you
  74.179 +must escape it.
  74.180 +
  74.181 +\section{Filtering keywords to change their results}
  74.182 +\label{sec:template:filter}
  74.183 +
  74.184 +Some of the results of template expansion are not immediately easy to
  74.185 +use.  Mercurial lets you specify an optional chain of \emph{filters}
  74.186 +to modify the result of expanding a keyword.  You have already seen a
  74.187 +common filter, \tplkwfilt{date}{isodate}, in action above, to make a
  74.188 +date readable.
  74.189 +
  74.190 +Below is a list of the most commonly used filters that Mercurial
  74.191 +supports.  While some filters can be applied to any text, others can
  74.192 +only be used in specific circumstances.  The name of each filter is
  74.193 +followed first by an indication of where it can be used, then a
  74.194 +description of its effect.
  74.195 +
  74.196 +\begin{itemize}
  74.197 +\item[\tplfilter{addbreaks}] Any text. Add an XHTML ``\Verb+<br/>+''
  74.198 +  tag before the end of every line except the last.  For example,
  74.199 +  ``\Verb+foo\nbar+'' becomes ``\Verb+foo<br/>\nbar+''.
  74.200 +\item[\tplkwfilt{date}{age}] \tplkword{date} keyword.  Render the
  74.201 +  age of the date, relative to the current time.  Yields a string like
  74.202 +  ``\Verb+10 minutes+''.
  74.203 +\item[\tplfilter{basename}] Any text, but most useful for the
  74.204 +  \tplkword{files} keyword and its relatives.  Treat the text as a
  74.205 +  path, and return the basename. For example, ``\Verb+foo/bar/baz+''
  74.206 +  becomes ``\Verb+baz+''.
  74.207 +\item[\tplkwfilt{date}{date}] \tplkword{date} keyword.  Render a date
  74.208 +  in a similar format to the Unix \tplkword{date} command, but with
  74.209 +  timezone included.  Yields a string like
  74.210 +  ``\Verb+Mon Sep 04 15:13:13 2006 -0700+''.
  74.211 +\item[\tplkwfilt{author}{domain}] Any text, but most useful for the
  74.212 +  \tplkword{author} keyword.  Finds the first string that looks like
  74.213 +  an email address, and extract just the domain component.  For
  74.214 +  example, ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes
  74.215 +  ``\Verb+serpentine.com+''.
  74.216 +\item[\tplkwfilt{author}{email}] Any text, but most useful for the
  74.217 +  \tplkword{author} keyword.  Extract the first string that looks like
  74.218 +  an email address.  For example,
  74.219 +  ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes
  74.220 +  ``\Verb+bos@serpentine.com+''.
  74.221 +\item[\tplfilter{escape}] Any text.  Replace the special XML/XHTML
  74.222 +  characters ``\Verb+&+'', ``\Verb+<+'' and ``\Verb+>+'' with
  74.223 +  XML entities.
  74.224 +\item[\tplfilter{fill68}] Any text.  Wrap the text to fit in 68
  74.225 +  columns.  This is useful before you pass text through the
  74.226 +  \tplfilter{tabindent} filter, and still want it to fit in an
  74.227 +  80-column fixed-font window.
  74.228 +\item[\tplfilter{fill76}] Any text.  Wrap the text to fit in 76
  74.229 +  columns.
  74.230 +\item[\tplfilter{firstline}] Any text.  Yield the first line of text,
  74.231 +  without any trailing newlines.
  74.232 +\item[\tplkwfilt{date}{hgdate}] \tplkword{date} keyword.  Render the
  74.233 +  date as a pair of readable numbers.  Yields a string like
  74.234 +  ``\Verb+1157407993 25200+''.
  74.235 +\item[\tplkwfilt{date}{isodate}] \tplkword{date} keyword.  Render the
  74.236 +  date as a text string in ISO~8601 format.  Yields a string like
  74.237 +  ``\Verb+2006-09-04 15:13:13 -0700+''.
  74.238 +\item[\tplfilter{obfuscate}] Any text, but most useful for the
  74.239 +  \tplkword{author} keyword.  Yield the input text rendered as a
  74.240 +  sequence of XML entities.  This helps to defeat some particularly
  74.241 +  stupid screen-scraping email harvesting spambots.
  74.242 +\item[\tplkwfilt{author}{person}] Any text, but most useful for the
  74.243 +  \tplkword{author} keyword.  Yield the text before an email address.
  74.244 +  For example, ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+''
  74.245 +  becomes ``\Verb+Bryan O'Sullivan+''.
  74.246 +\item[\tplkwfilt{date}{rfc822date}] \tplkword{date} keyword.  Render a
  74.247 +  date using the same format used in email headers.  Yields a string
  74.248 +  like ``\Verb+Mon, 04 Sep 2006 15:13:13 -0700+''.
  74.249 +\item[\tplkwfilt{node}{short}] Changeset hash.  Yield the short form
  74.250 +  of a changeset hash, i.e.~a 12-character hexadecimal string.
  74.251 +\item[\tplkwfilt{date}{shortdate}] \tplkword{date} keyword.  Render
  74.252 +  the year, month, and day of the date.  Yields a string like
  74.253 +  ``\Verb+2006-09-04+''.
  74.254 +\item[\tplfilter{strip}] Any text.  Strip all leading and trailing
  74.255 +  whitespace from the string.
  74.256 +\item[\tplfilter{tabindent}] Any text.  Yield the text, with every line
  74.257 +  except the first starting with a tab character.
  74.258 +\item[\tplfilter{urlescape}] Any text.  Escape all characters that are
  74.259 +  considered ``special'' by URL parsers.  For example, \Verb+foo bar+
  74.260 +  becomes \Verb+foo%20bar+.
  74.261 +\item[\tplkwfilt{author}{user}] Any text, but most useful for the
  74.262 +  \tplkword{author} keyword.  Return the ``user'' portion of an email
  74.263 +  address.  For example,
  74.264 +  ``\Verb+Bryan O'Sullivan <bos@serpentine.com>+'' becomes
  74.265 +  ``\Verb+bos+''.
  74.266 +\end{itemize}
  74.267 +
  74.268 +\begin{figure}
  74.269 +  \interaction{template.simple.manyfilters}
  74.270 +  \caption{Template filters in action}
  74.271 +  \label{fig:template:filters}
  74.272 +\end{figure}
  74.273 +
  74.274 +\begin{note}
  74.275 +  If you try to apply a filter to a piece of data that it cannot
  74.276 +  process, Mercurial will fail and print a Python exception.  For
  74.277 +  example, trying to run the output of the \tplkword{desc} keyword
  74.278 +  into the \tplkwfilt{date}{isodate} filter is not a good idea.
  74.279 +\end{note}
  74.280 +
  74.281 +\subsection{Combining filters}
  74.282 +
  74.283 +It is easy to combine filters to yield output in the form you would
  74.284 +like.  The following chain of filters tidies up a description, then
  74.285 +makes sure that it fits cleanly into 68 columns, then indents it by a
  74.286 +further 8~characters (at least on Unix-like systems, where a tab is
  74.287 +conventionally 8~characters wide).
  74.288 +
  74.289 +\interaction{template.simple.combine}
  74.290 +
  74.291 +Note the use of ``\Verb+\t+'' (a tab character) in the template to
  74.292 +force the first line to be indented; this is necessary since
  74.293 +\tplkword{tabindent} indents all lines \emph{except} the first.
  74.294 +
  74.295 +Keep in mind that the order of filters in a chain is significant.  The
  74.296 +first filter is applied to the result of the keyword; the second to
  74.297 +the result of the first filter; and so on.  For example, using
  74.298 +\Verb+fill68|tabindent+ gives very different results from
  74.299 +\Verb+tabindent|fill68+.
  74.300 +
  74.301 +
  74.302 +\section{From templates to styles}
  74.303 +
  74.304 +A command line template provides a quick and simple way to format some
  74.305 +output.  Templates can become verbose, though, and it's useful to be
  74.306 +able to give a template a name.  A style file is a template with a
  74.307 +name, stored in a file.
  74.308 +
  74.309 +More than that, using a style file unlocks the power of Mercurial's
  74.310 +templating engine in ways that are not possible using the command line
  74.311 +\hgopt{log}{--template} option.
  74.312 +
  74.313 +\subsection{The simplest of style files}
  74.314 +
  74.315 +Our simple style file contains just one line:
  74.316 +
  74.317 +\interaction{template.simple.rev}
  74.318 +
  74.319 +This tells Mercurial, ``if you're printing a changeset, use the text
  74.320 +on the right as the template''.
  74.321 +
  74.322 +\subsection{Style file syntax}
  74.323 +
  74.324 +The syntax rules for a style file are simple.
  74.325 +
  74.326 +\begin{itemize}
  74.327 +\item The file is processed one line at a time.
  74.328 +
  74.329 +\item Leading and trailing white space are ignored.
  74.330 +
  74.331 +\item Empty lines are skipped.
  74.332 +
  74.333 +\item If a line starts with either of the characters ``\texttt{\#}'' or
  74.334 +  ``\texttt{;}'', the entire line is treated as a comment, and skipped
  74.335 +  as if empty.
  74.336 +
  74.337 +\item A line starts with a keyword.  This must start with an
  74.338 +  alphabetic character or underscore, and can subsequently contain any
  74.339 +  alphanumeric character or underscore.  (In regexp notation, a
  74.340 +  keyword must match \Verb+[A-Za-z_][A-Za-z0-9_]*+.)
  74.341 +
  74.342 +\item The next element must be an ``\texttt{=}'' character, which can
  74.343 +  be preceded or followed by an arbitrary amount of white space.
  74.344 +
  74.345 +\item If the rest of the line starts and ends with matching quote
  74.346 +  characters (either single or double quote), it is treated as a
  74.347 +  template body.
  74.348 +
  74.349 +\item If the rest of the line \emph{does not} start with a quote
  74.350 +  character, it is treated as the name of a file; the contents of this
  74.351 +  file will be read and used as a template body.
  74.352 +\end{itemize}
  74.353 +
  74.354 +\section{Style files by example}
  74.355 +
  74.356 +To illustrate how to write a style file, we will construct a few by
  74.357 +example.  Rather than provide a complete style file and walk through
  74.358 +it, we'll mirror the usual process of developing a style file by
  74.359 +starting with something very simple, and walking through a series of
  74.360 +successively more complete examples.
  74.361 +
  74.362 +\subsection{Identifying mistakes in style files}
  74.363 +
  74.364 +If Mercurial encounters a problem in a style file you are working on,
  74.365 +it prints a terse error message that, once you figure out what it
  74.366 +means, is actually quite useful.
  74.367 +
  74.368 +\interaction{template.svnstyle.syntax.input}
  74.369 +
  74.370 +Notice that \filename{broken.style} attempts to define a
  74.371 +\texttt{changeset} keyword, but forgets to give any content for it.
  74.372 +When instructed to use this style file, Mercurial promptly complains.
  74.373 +
  74.374 +\interaction{template.svnstyle.syntax.error}
  74.375 +
  74.376 +This error message looks intimidating, but it is not too hard to
  74.377 +follow.
  74.378 +
  74.379 +\begin{itemize}
  74.380 +\item The first component is simply Mercurial's way of saying ``I am
  74.381 +  giving up''.
  74.382 +  \begin{codesample4}
  74.383 +    \textbf{abort:} broken.style:1: parse error
  74.384 +  \end{codesample4}
  74.385 +
  74.386 +\item Next comes the name of the style file that contains the error.
  74.387 +  \begin{codesample4}
  74.388 +    abort: \textbf{broken.style}:1: parse error
  74.389 +  \end{codesample4}
  74.390 +
  74.391 +\item Following the file name is the line number where the error was
  74.392 +  encountered.
  74.393 +  \begin{codesample4}
  74.394 +    abort: broken.style:\textbf{1}: parse error
  74.395 +  \end{codesample4}
  74.396 +
  74.397 +\item Finally, a description of what went wrong.
  74.398 +  \begin{codesample4}
  74.399 +    abort: broken.style:1: \textbf{parse error}
  74.400 +  \end{codesample4}
  74.401 +  The description of the problem is not always clear (as in this
  74.402 +  case), but even when it is cryptic, it is almost always trivial to
  74.403 +  visually inspect the offending line in the style file and see what
  74.404 +  is wrong.
  74.405 +\end{itemize}
  74.406 +
  74.407 +\subsection{Uniquely identifying a repository}
  74.408 +
  74.409 +If you would like to be able to identify a Mercurial repository
  74.410 +``fairly uniquely'' using a short string as an identifier, you can
  74.411 +use the first revision in the repository.
  74.412 +\interaction{template.svnstyle.id} 
  74.413 +This is not guaranteed to be unique, but it is nevertheless useful in
  74.414 +many cases.
  74.415 +\begin{itemize}
  74.416 +\item It will not work in a completely empty repository, because such
  74.417 +  a repository does not have a revision~zero.
  74.418 +\item Neither will it work in the (extremely rare) case where a
  74.419 +  repository is a merge of two or more formerly independent
  74.420 +  repositories, and you still have those repositories around.
  74.421 +\end{itemize}
  74.422 +Here are some uses to which you could put this identifier:
  74.423 +\begin{itemize}
  74.424 +\item As a key into a table for a database that manages repositories
  74.425 +  on a server.
  74.426 +\item As half of a \{\emph{repository~ID}, \emph{revision~ID}\} tuple.
  74.427 +  Save this information away when you run an automated build or other
  74.428 +  activity, so that you can ``replay'' the build later if necessary.
  74.429 +\end{itemize}
  74.430 +
  74.431 +\subsection{Mimicking Subversion's output}
  74.432 +
  74.433 +Let's try to emulate the default output format used by another
  74.434 +revision control tool, Subversion.
  74.435 +\interaction{template.svnstyle.short}
  74.436 +
  74.437 +Since Subversion's output style is fairly simple, it is easy to
  74.438 +copy-and-paste a hunk of its output into a file, and replace the text
  74.439 +produced above by Subversion with the template values we'd like to see
  74.440 +expanded.
  74.441 +\interaction{template.svnstyle.template}
  74.442 +
  74.443 +There are a few small ways in which this template deviates from the
  74.444 +output produced by Subversion.
  74.445 +\begin{itemize}
  74.446 +\item Subversion prints a ``readable'' date (the ``\texttt{Wed, 27 Sep
  74.447 +    2006}'' in the example output above) in parentheses.  Mercurial's
  74.448 +  templating engine does not provide a way to display a date in this
  74.449 +  format without also printing the time and time zone.
  74.450 +\item We emulate Subversion's printing of ``separator'' lines full of
  74.451 +  ``\texttt{-}'' characters by ending the template with such a line.
  74.452 +  We use the templating engine's \tplkword{header} keyword to print a
  74.453 +  separator line as the first line of output (see below), thus
  74.454 +  achieving similar output to Subversion.
  74.455 +\item Subversion's output includes a count in the header of the number
  74.456 +  of lines in the commit message.  We cannot replicate this in
  74.457 +  Mercurial; the templating engine does not currently provide a filter
  74.458 +  that counts the number of lines the template generates.
  74.459 +\end{itemize}
  74.460 +It took me no more than a minute or two of work to replace literal
  74.461 +text from an example of Subversion's output with some keywords and
  74.462 +filters to give the template above.  The style file simply refers to
  74.463 +the template.
  74.464 +\interaction{template.svnstyle.style}
  74.465 +
  74.466 +We could have included the text of the template file directly in the
  74.467 +style file by enclosing it in quotes and replacing the newlines with
  74.468 +``\verb!\n!'' sequences, but it would have made the style file too
  74.469 +difficult to read.  Readability is a good guide when you're trying to
  74.470 +decide whether some text belongs in a style file, or in a template
  74.471 +file that the style file points to.  If the style file will look too
  74.472 +big or cluttered if you insert a literal piece of text, drop it into a
  74.473 +template instead.
  74.474 +
  74.475 +%%% Local Variables: 
  74.476 +%%% mode: latex
  74.477 +%%% TeX-master: "00book"
  74.478 +%%% End: 
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/fr/tour-basic.tex	Thu Feb 05 12:37:03 2009 +0100
    75.3 @@ -0,0 +1,624 @@
    75.4 +\chapter{A tour of Mercurial: the basics}
    75.5 +\label{chap:tour-basic}
    75.6 +
    75.7 +\section{Installing Mercurial on your system}
    75.8 +\label{sec:tour:install}
    75.9 +
   75.10 +Prebuilt binary packages of Mercurial are available for every popular
   75.11 +operating system.  These make it easy to start using Mercurial on your
   75.12 +computer immediately.
   75.13 +
   75.14 +\subsection{Linux}
   75.15 +
   75.16 +Because each Linux distribution has its own packaging tools, policies,
   75.17 +and rate of development, it's difficult to give a comprehensive set of
   75.18 +instructions on how to install Mercurial binaries.  The version of
   75.19 +Mercurial that you will end up with can vary depending on how active
   75.20 +the person is who maintains the package for your distribution.
   75.21 +
   75.22 +To keep things simple, I will focus on installing Mercurial from the
   75.23 +command line under the most popular Linux distributions.  Most of
   75.24 +these distributions provide graphical package managers that will let
   75.25 +you install Mercurial with a single click; the package name to look
   75.26 +for is \texttt{mercurial}.
   75.27 +
   75.28 +\begin{itemize}
   75.29 +\item[Debian]
   75.30 +  \begin{codesample4}
   75.31 +    apt-get install mercurial
   75.32 +  \end{codesample4}
   75.33 +
   75.34 +\item[Fedora Core]
   75.35 +  \begin{codesample4}
   75.36 +    yum install mercurial
   75.37 +  \end{codesample4}
   75.38 +
   75.39 +\item[Gentoo]
   75.40 +  \begin{codesample4}
   75.41 +    emerge mercurial
   75.42 +  \end{codesample4}
   75.43 +
   75.44 +\item[OpenSUSE]
   75.45 +  \begin{codesample4}
   75.46 +    yum install mercurial
   75.47 +  \end{codesample4}
   75.48 +
   75.49 +\item[Ubuntu] Ubuntu's Mercurial package is based on Debian's.  To
   75.50 +  install it, run the following command.
   75.51 +  \begin{codesample4}
   75.52 +    apt-get install mercurial
   75.53 +  \end{codesample4}
   75.54 +  The Ubuntu package for Mercurial tends to lag behind the Debian
   75.55 +  version by a considerable time margin (at the time of writing, seven
   75.56 +  months), which in some cases will mean that on Ubuntu, you may run
   75.57 +  into problems that have since been fixed in the Debian package.
   75.58 +\end{itemize}
   75.59 +
   75.60 +\subsection{Solaris}
   75.61 +
   75.62 +SunFreeWare, at \url{http://www.sunfreeware.com}, is a good source for a
   75.63 +large number of pre-built Solaris packages for 32 and 64 bit Intel and
   75.64 +Sparc architectures, including current versions of Mercurial.
   75.65 +
   75.66 +\subsection{Mac OS X}
   75.67 +
   75.68 +Lee Cantey publishes an installer of Mercurial for Mac OS~X at
   75.69 +\url{http://mercurial.berkwood.com}.  This package works on both
   75.70 +Intel-~and Power-based Macs.  Before you can use it, you must install
   75.71 +a compatible version of Universal MacPython~\cite{web:macpython}.  This
   75.72 +is easy to do; simply follow the instructions on Lee's site.
   75.73 +
   75.74 +It's also possible to install Mercurial using Fink or MacPorts,
   75.75 +two popular free package managers for Mac OS X.  If you have Fink,
   75.76 +use \command{sudo apt-get install mercurial-py25}.  If MacPorts,
   75.77 +\command{sudo port install mercurial}.
   75.78 +
   75.79 +\subsection{Windows}
   75.80 +
   75.81 +Lee Cantey publishes an installer of Mercurial for Windows at
   75.82 +\url{http://mercurial.berkwood.com}.  This package has no external
   75.83 +dependencies; it ``just works''.
   75.84 +
   75.85 +\begin{note}
   75.86 +  The Windows version of Mercurial does not automatically convert line
   75.87 +  endings between Windows and Unix styles.  If you want to share work
   75.88 +  with Unix users, you must do a little additional configuration
   75.89 +  work. XXX Flesh this out.
   75.90 +\end{note}
   75.91 +
   75.92 +\section{Getting started}
   75.93 +
   75.94 +To begin, we'll use the \hgcmd{version} command to find out whether
   75.95 +Mercurial is actually installed properly.  The actual version
   75.96 +information that it prints isn't so important; it's whether it prints
   75.97 +anything at all that we care about.
   75.98 +\interaction{tour.version}
   75.99 +
  75.100 +\subsection{Built-in help}
  75.101 +
  75.102 +Mercurial provides a built-in help system.  This is invaluable for those
  75.103 +times when you find yourself stuck trying to remember how to run a
  75.104 +command.  If you are completely stuck, simply run \hgcmd{help}; it
  75.105 +will print a brief list of commands, along with a description of what
  75.106 +each does.  If you ask for help on a specific command (as below), it
  75.107 +prints more detailed information.
  75.108 +\interaction{tour.help}
  75.109 +For a more impressive level of detail (which you won't usually need)
  75.110 +run \hgcmdargs{help}{\hggopt{-v}}.  The \hggopt{-v} option is short
  75.111 +for \hggopt{--verbose}, and tells Mercurial to print more information
  75.112 +than it usually would.
  75.113 +
  75.114 +\section{Working with a repository}
  75.115 +
  75.116 +In Mercurial, everything happens inside a \emph{repository}.  The
  75.117 +repository for a project contains all of the files that ``belong to''
  75.118 +that project, along with a historical record of the project's files.
  75.119 +
  75.120 +There's nothing particularly magical about a repository; it is simply
  75.121 +a directory tree in your filesystem that Mercurial treats as special.
  75.122 +You can rename or delete a repository any time you like, using either the
  75.123 +command line or your file browser.
  75.124 +
  75.125 +\subsection{Making a local copy of a repository}
  75.126 +
  75.127 +\emph{Copying} a repository is just a little bit special.  While you
  75.128 +could use a normal file copying command to make a copy of a
  75.129 +repository, it's best to use a built-in command that Mercurial
  75.130 +provides.  This command is called \hgcmd{clone}, because it creates an
  75.131 +identical copy of an existing repository.
  75.132 +\interaction{tour.clone}
  75.133 +If our clone succeeded, we should now have a local directory called
  75.134 +\dirname{hello}.  This directory will contain some files.
  75.135 +\interaction{tour.ls}
  75.136 +These files have the same contents and history in our repository as
  75.137 +they do in the repository we cloned.
  75.138 +
  75.139 +Every Mercurial repository is complete, self-contained, and
  75.140 +independent.  It contains its own private copy of a project's files
  75.141 +and history.  A cloned repository remembers the location of the
  75.142 +repository it was cloned from, but it does not communicate with that
  75.143 +repository, or any other, unless you tell it to.
  75.144 +
  75.145 +What this means for now is that we're free to experiment with our
  75.146 +repository, safe in the knowledge that it's a private ``sandbox'' that
  75.147 +won't affect anyone else.
  75.148 +
  75.149 +\subsection{What's in a repository?}
  75.150 +
  75.151 +When we take a more detailed look inside a repository, we can see that
  75.152 +it contains a directory named \dirname{.hg}.  This is where Mercurial
  75.153 +keeps all of its metadata for the repository.
  75.154 +\interaction{tour.ls-a}
  75.155 +
  75.156 +The contents of the \dirname{.hg} directory and its subdirectories are
  75.157 +private to Mercurial.  Every other file and directory in the
  75.158 +repository is yours to do with as you please.
  75.159 +
  75.160 +To introduce a little terminology, the \dirname{.hg} directory is the
  75.161 +``real'' repository, and all of the files and directories that coexist
  75.162 +with it are said to live in the \emph{working directory}.  An easy way
  75.163 +to remember the distinction is that the \emph{repository} contains the
  75.164 +\emph{history} of your project, while the \emph{working directory}
  75.165 +contains a \emph{snapshot} of your project at a particular point in
  75.166 +history.
  75.167 +
  75.168 +\section{A tour through history}
  75.169 +
  75.170 +One of the first things we might want to do with a new, unfamiliar
  75.171 +repository is understand its history.  The \hgcmd{log} command gives
  75.172 +us a view of history.
  75.173 +\interaction{tour.log}
  75.174 +By default, this command prints a brief paragraph of output for each
  75.175 +change to the project that was recorded.  In Mercurial terminology, we
  75.176 +call each of these recorded events a \emph{changeset}, because it can
  75.177 +contain a record of changes to several files.
  75.178 +
  75.179 +The fields in a record of output from \hgcmd{log} are as follows.
  75.180 +\begin{itemize}
  75.181 +\item[\texttt{changeset}] This field has the format of a number,
  75.182 +  followed by a colon, followed by a hexadecimal string.  These are
  75.183 +  \emph{identifiers} for the changeset.  There are two identifiers
  75.184 +  because the number is shorter and easier to type than the hex
  75.185 +  string.
  75.186 +\item[\texttt{user}] The identity of the person who created the
  75.187 +  changeset.  This is a free-form field, but it most often contains a
  75.188 +  person's name and email address.
  75.189 +\item[\texttt{date}] The date and time on which the changeset was
  75.190 +  created, and the timezone in which it was created.  (The date and
  75.191 +  time are local to that timezone; they display what time and date it
  75.192 +  was for the person who created the changeset.)
  75.193 +\item[\texttt{summary}] The first line of the text message that the
  75.194 +  creator of the changeset entered to describe the changeset.
  75.195 +\end{itemize}
  75.196 +The default output printed by \hgcmd{log} is purely a summary; it is
  75.197 +missing a lot of detail.
  75.198 +
  75.199 +Figure~\ref{fig:tour-basic:history} provides a graphical representation of
  75.200 +the history of the \dirname{hello} repository, to make it a little
  75.201 +easier to see which direction history is ``flowing'' in.  We'll be
  75.202 +returning to this figure several times in this chapter and the chapter
  75.203 +that follows.
  75.204 +
  75.205 +\begin{figure}[ht]
  75.206 +  \centering
  75.207 +  \grafix{tour-history}
  75.208 +  \caption{Graphical history of the \dirname{hello} repository}
  75.209 +  \label{fig:tour-basic:history}
  75.210 +\end{figure}
  75.211 +
  75.212 +\subsection{Changesets, revisions, and talking to other 
  75.213 +  people}
  75.214 +
  75.215 +As English is a notoriously sloppy language, and computer science has
  75.216 +a hallowed history of terminological confusion (why use one term when
  75.217 +four will do?), revision control has a variety of words and phrases
  75.218 +that mean the same thing.  If you are talking about Mercurial history
  75.219 +with other people, you will find that the word ``changeset'' is often
  75.220 +compressed to ``change'' or (when written) ``cset'', and sometimes a
  75.221 +changeset is referred to as a ``revision'' or a ``rev''.
  75.222 +
  75.223 +While it doesn't matter what \emph{word} you use to refer to the
  75.224 +concept of ``a~changeset'', the \emph{identifier} that you use to
  75.225 +refer to ``a~\emph{specific} changeset'' is of great importance.
  75.226 +Recall that the \texttt{changeset} field in the output from
  75.227 +\hgcmd{log} identifies a changeset using both a number and a
  75.228 +hexadecimal string.
  75.229 +\begin{itemize}
  75.230 +\item The revision number is \emph{only valid in that repository},
  75.231 +\item while the hex string is the \emph{permanent, unchanging
  75.232 +    identifier} that will always identify that exact changeset in
  75.233 +  \emph{every} copy of the repository.
  75.234 +\end{itemize}
  75.235 +This distinction is important.  If you send someone an email talking
  75.236 +about ``revision~33'', there's a high likelihood that their
  75.237 +revision~33 will \emph{not be the same} as yours.  The reason for this
  75.238 +is that a revision number depends on the order in which changes
  75.239 +arrived in a repository, and there is no guarantee that the same
  75.240 +changes will happen in the same order in different repositories.
  75.241 +Three changes $a,b,c$ can easily appear in one repository as $0,1,2$,
  75.242 +while in another as $1,0,2$.
  75.243 +
  75.244 +Mercurial uses revision numbers purely as a convenient shorthand.  If
  75.245 +you need to discuss a changeset with someone, or make a record of a
  75.246 +changeset for some other reason (for example, in a bug report), use
  75.247 +the hexadecimal identifier.
  75.248 +
  75.249 +\subsection{Viewing specific revisions}
  75.250 +
  75.251 +To narrow the output of \hgcmd{log} down to a single revision, use the
  75.252 +\hgopt{log}{-r} (or \hgopt{log}{--rev}) option.  You can use either a
  75.253 +revision number or a long-form changeset identifier, and you can
  75.254 +provide as many revisions as you want.  \interaction{tour.log-r}
  75.255 +
  75.256 +If you want to see the history of several revisions without having to
  75.257 +list each one, you can use \emph{range notation}; this lets you
  75.258 +express the idea ``I want all revisions between $a$ and $b$,
  75.259 +inclusive''.
  75.260 +\interaction{tour.log.range}
  75.261 +Mercurial also honours the order in which you specify revisions, so
  75.262 +\hgcmdargs{log}{-r 2:4} prints $2,3,4$ while \hgcmdargs{log}{-r 4:2}
  75.263 +prints $4,3,2$.
  75.264 +
  75.265 +\subsection{More detailed information}
  75.266 +
  75.267 +While the summary information printed by \hgcmd{log} is useful if you
  75.268 +already know what you're looking for, you may need to see a complete
  75.269 +description of the change, or a list of the files changed, if you're
  75.270 +trying to decide whether a changeset is the one you're looking for.
  75.271 +The \hgcmd{log} command's \hggopt{-v} (or \hggopt{--verbose})
  75.272 +option gives you this extra detail.
  75.273 +\interaction{tour.log-v}
  75.274 +
  75.275 +If you want to see both the description and content of a change, add
  75.276 +the \hgopt{log}{-p} (or \hgopt{log}{--patch}) option.  This displays
  75.277 +the content of a change as a \emph{unified diff} (if you've never seen
  75.278 +a unified diff before, see section~\ref{sec:mq:patch} for an overview).
  75.279 +\interaction{tour.log-vp}
  75.280 +
  75.281 +\section{All about command options}
  75.282 +
  75.283 +Let's take a brief break from exploring Mercurial commands to discuss
  75.284 +a pattern in the way that they work; you may find this useful to keep
  75.285 +in mind as we continue our tour.
  75.286 +
  75.287 +Mercurial has a consistent and straightforward approach to dealing
  75.288 +with the options that you can pass to commands.  It follows the
  75.289 +conventions for options that are common to modern Linux and Unix
  75.290 +systems.
  75.291 +\begin{itemize}
  75.292 +\item Every option has a long name.  For example, as we've already
  75.293 +  seen, the \hgcmd{log} command accepts a \hgopt{log}{--rev} option.
  75.294 +\item Most options have short names, too.  Instead of
  75.295 +  \hgopt{log}{--rev}, we can use \hgopt{log}{-r}.  (The reason that
  75.296 +  some options don't have short names is that the options in question
  75.297 +  are rarely used.)
  75.298 +\item Long options start with two dashes (e.g.~\hgopt{log}{--rev}),
  75.299 +  while short options start with one (e.g.~\hgopt{log}{-r}).
  75.300 +\item Option naming and usage is consistent across commands.  For
  75.301 +  example, every command that lets you specify a changeset~ID or
  75.302 +  revision number accepts both \hgopt{log}{-r} and \hgopt{log}{--rev}
  75.303 +  arguments.
  75.304 +\end{itemize}
  75.305 +In the examples throughout this book, I use short options instead of
  75.306 +long.  This just reflects my own preference, so don't read anything
  75.307 +significant into it.
  75.308 +
  75.309 +Most commands that print output of some kind will print more output
  75.310 +when passed a \hggopt{-v} (or \hggopt{--verbose}) option, and less
  75.311 +when passed \hggopt{-q} (or \hggopt{--quiet}).
  75.312 +
  75.313 +\section{Making and reviewing changes}
  75.314 +
  75.315 +Now that we have a grasp of viewing history in Mercurial, let's take a
  75.316 +look at making some changes and examining them.
  75.317 +
  75.318 +The first thing we'll do is isolate our experiment in a repository of
  75.319 +its own.  We use the \hgcmd{clone} command, but we don't need to
  75.320 +clone a copy of the remote repository.  Since we already have a copy
  75.321 +of it locally, we can just clone that instead.  This is much faster
  75.322 +than cloning over the network, and cloning a local repository uses
  75.323 +less disk space in most cases, too.
  75.324 +\interaction{tour.reclone}
  75.325 +As an aside, it's often good practice to keep a ``pristine'' copy of a
  75.326 +remote repository around, which you can then make temporary clones of
  75.327 +to create sandboxes for each task you want to work on.  This lets you
  75.328 +work on multiple tasks in parallel, each isolated from the others
  75.329 +until it's complete and you're ready to integrate it back.  Because
  75.330 +local clones are so cheap, there's almost no overhead to cloning and
  75.331 +destroying repositories whenever you want.
  75.332 +
  75.333 +In our \dirname{my-hello} repository, we have a file
  75.334 +\filename{hello.c} that contains the classic ``hello, world'' program.
  75.335 +Let's use the ancient and venerable \command{sed} command to edit this
  75.336 +file so that it prints a second line of output.  (I'm only using
  75.337 +\command{sed} to do this because it's easy to write a scripted example
  75.338 +this way.  Since you're not under the same constraint, you probably
  75.339 +won't want to use \command{sed}; simply use your preferred text editor to
  75.340 +do the same thing.)
  75.341 +\interaction{tour.sed}
  75.342 +
  75.343 +Mercurial's \hgcmd{status} command will tell us what Mercurial knows
  75.344 +about the files in the repository.
  75.345 +\interaction{tour.status}
  75.346 +The \hgcmd{status} command prints no output for some files, but a line
  75.347 +starting with ``\texttt{M}'' for \filename{hello.c}.  Unless you tell
  75.348 +it to, \hgcmd{status} will not print any output for files that have
  75.349 +not been modified.  
  75.350 +
  75.351 +The ``\texttt{M}'' indicates that Mercurial has noticed that we
  75.352 +modified \filename{hello.c}.  We didn't need to \emph{inform}
  75.353 +Mercurial that we were going to modify the file before we started, or
  75.354 +that we had modified the file after we were done; it was able to
  75.355 +figure this out itself.
  75.356 +
  75.357 +It's a little bit helpful to know that we've modified
  75.358 +\filename{hello.c}, but we might prefer to know exactly \emph{what}
  75.359 +changes we've made to it.  To do this, we use the \hgcmd{diff}
  75.360 +command.
  75.361 +\interaction{tour.diff}
  75.362 +
  75.363 +\section{Recording changes in a new changeset}
  75.364 +
  75.365 +We can modify files, build and test our changes, and use
  75.366 +\hgcmd{status} and \hgcmd{diff} to review our changes, until we're
  75.367 +satisfied with what we've done and arrive at a natural stopping point
  75.368 +where we want to record our work in a new changeset.
  75.369 +
  75.370 +The \hgcmd{commit} command lets us create a new changeset; we'll
  75.371 +usually refer to this as ``making a commit'' or ``committing''.  
  75.372 +
  75.373 +\subsection{Setting up a username}
  75.374 +
  75.375 +When you try to run \hgcmd{commit} for the first time, it is not
  75.376 +guaranteed to succeed.  Mercurial records your name and address with
  75.377 +each change that you commit, so that you and others will later be able
  75.378 +to tell who made each change.  Mercurial tries to automatically figure
  75.379 +out a sensible username to commit the change with.  It will attempt
  75.380 +each of the following methods, in order:
  75.381 +\begin{enumerate}
  75.382 +\item If you specify a \hgopt{commit}{-u} option to the \hgcmd{commit}
  75.383 +  command on the command line, followed by a username, this is always
  75.384 +  given the highest precedence.
  75.385 +\item If you have set the \envar{HGUSER} environment variable, this is
  75.386 +  checked next.
  75.387 +\item If you create a file in your home directory called
  75.388 +  \sfilename{.hgrc}, with a \rcitem{ui}{username} entry, that will be
  75.389 +  used next.  To see what the contents of this file should look like,
  75.390 +  refer to section~\ref{sec:tour-basic:username} below.
  75.391 +\item If you have set the \envar{EMAIL} environment variable, this
  75.392 +  will be used next.
  75.393 +\item Mercurial will query your system to find out your local user
  75.394 +  name and host name, and construct a username from these components.
  75.395 +  Since this often results in a username that is not very useful, it
  75.396 +  will print a warning if it has to do this.
  75.397 +\end{enumerate}
  75.398 +If all of these mechanisms fail, Mercurial will fail, printing an
  75.399 +error message.  In this case, it will not let you commit until you set
  75.400 +up a username.
  75.401 +
  75.402 +You should think of the \envar{HGUSER} environment variable and the
  75.403 +\hgopt{commit}{-u} option to the \hgcmd{commit} command as ways to
  75.404 +\emph{override} Mercurial's default selection of username.  For normal
  75.405 +use, the simplest and most robust way to set a username for yourself
  75.406 +is by creating a \sfilename{.hgrc} file; see below for details.
  75.407 +
  75.408 +\subsubsection{Creating a Mercurial configuration file}
  75.409 +\label{sec:tour-basic:username}
  75.410 +
  75.411 +To set a user name, use your favourite editor to create a file called
  75.412 +\sfilename{.hgrc} in your home directory.  Mercurial will use this
  75.413 +file to look up your personalised configuration settings.  The initial
  75.414 +contents of your \sfilename{.hgrc} should look like this.
  75.415 +\begin{codesample2}
  75.416 +  # This is a Mercurial configuration file.
  75.417 +  [ui]
  75.418 +  username = Firstname Lastname <email.address@domain.net>
  75.419 +\end{codesample2}
  75.420 +The ``\texttt{[ui]}'' line begins a \emph{section} of the config file,
  75.421 +so you can read the ``\texttt{username = ...}'' line as meaning ``set
  75.422 +the value of the \texttt{username} item in the \texttt{ui} section''.
  75.423 +A section continues until a new section begins, or the end of the
  75.424 +file.  Mercurial ignores empty lines and treats any text from
  75.425 +``\texttt{\#}'' to the end of a line as a comment.
  75.426 +
  75.427 +\subsubsection{Choosing a user name}
  75.428 +
  75.429 +You can use any text you like as the value of the \texttt{username}
  75.430 +config item, since this information is for reading by other people,
  75.431 +but for interpreting by Mercurial.  The convention that most people
  75.432 +follow is to use their name and email address, as in the example
  75.433 +above.
  75.434 +
  75.435 +\begin{note}
  75.436 +  Mercurial's built-in web server obfuscates email addresses, to make
  75.437 +  it more difficult for the email harvesting tools that spammers use.
  75.438 +  This reduces the likelihood that you'll start receiving more junk
  75.439 +  email if you publish a Mercurial repository on the web.
  75.440 +\end{note}
  75.441 +
  75.442 +\subsection{Writing a commit message}
  75.443 +
  75.444 +When we commit a change, Mercurial drops us into a text editor, to
  75.445 +enter a message that will describe the modifications we've made in
  75.446 +this changeset.  This is called the \emph{commit message}.  It will be
  75.447 +a record for readers of what we did and why, and it will be printed by
  75.448 +\hgcmd{log} after we've finished committing.
  75.449 +\interaction{tour.commit}
  75.450 +
  75.451 +The editor that the \hgcmd{commit} command drops us into will contain
  75.452 +an empty line, followed by a number of lines starting with
  75.453 +``\texttt{HG:}''.
  75.454 +\begin{codesample2}
  75.455 +  \emph{empty line}
  75.456 +  HG: changed hello.c
  75.457 +\end{codesample2}
  75.458 +Mercurial ignores the lines that start with ``\texttt{HG:}''; it uses
  75.459 +them only to tell us which files it's recording changes to.  Modifying
  75.460 +or deleting these lines has no effect.
  75.461 +
  75.462 +\subsection{Writing a good commit message}
  75.463 +
  75.464 +Since \hgcmd{log} only prints the first line of a commit message by
  75.465 +default, it's best to write a commit message whose first line stands
  75.466 +alone.  Here's a real example of a commit message that \emph{doesn't}
  75.467 +follow this guideline, and hence has a summary that is not readable.
  75.468 +\begin{codesample2}
  75.469 +  changeset:   73:584af0e231be
  75.470 +  user:        Censored Person <censored.person@example.org>
  75.471 +  date:        Tue Sep 26 21:37:07 2006 -0700
  75.472 +  summary:     include buildmeister/commondefs.   Add an exports and install
  75.473 +\end{codesample2}
  75.474 +
  75.475 +As far as the remainder of the contents of the commit message are
  75.476 +concerned, there are no hard-and-fast rules.  Mercurial itself doesn't
  75.477 +interpret or care about the contents of the commit message, though
  75.478 +your project may have policies that dictate a certain kind of
  75.479 +formatting.
  75.480 +
  75.481 +My personal preference is for short, but informative, commit messages
  75.482 +that tell me something that I can't figure out with a quick glance at
  75.483 +the output of \hgcmdargs{log}{--patch}.
  75.484 +
  75.485 +\subsection{Aborting a commit}
  75.486 +
  75.487 +If you decide that you don't want to commit while in the middle of
  75.488 +editing a commit message, simply exit from your editor without saving
  75.489 +the file that it's editing.  This will cause nothing to happen to
  75.490 +either the repository or the working directory.
  75.491 +
  75.492 +If we run the \hgcmd{commit} command without any arguments, it records
  75.493 +all of the changes we've made, as reported by \hgcmd{status} and
  75.494 +\hgcmd{diff}.
  75.495 +
  75.496 +\subsection{Admiring our new handiwork}
  75.497 +
  75.498 +Once we've finished the commit, we can use the \hgcmd{tip} command to
  75.499 +display the changeset we just created.  This command produces output
  75.500 +that is identical to \hgcmd{log}, but it only displays the newest
  75.501 +revision in the repository.
  75.502 +\interaction{tour.tip}
  75.503 +We refer to the newest revision in the repository as the tip revision,
  75.504 +or simply the tip.
  75.505 +
  75.506 +\section{Sharing changes}
  75.507 +
  75.508 +We mentioned earlier that repositories in Mercurial are
  75.509 +self-contained.  This means that the changeset we just created exists
  75.510 +only in our \dirname{my-hello} repository.  Let's look at a few ways
  75.511 +that we can propagate this change into other repositories.
  75.512 +
  75.513 +\subsection{Pulling changes from another repository}
  75.514 +\label{sec:tour:pull}
  75.515 +
  75.516 +To get started, let's clone our original \dirname{hello} repository,
  75.517 +which does not contain the change we just committed.  We'll call our
  75.518 +temporary repository \dirname{hello-pull}.
  75.519 +\interaction{tour.clone-pull}
  75.520 +
  75.521 +We'll use the \hgcmd{pull} command to bring changes from
  75.522 +\dirname{my-hello} into \dirname{hello-pull}.  However, blindly
  75.523 +pulling unknown changes into a repository is a somewhat scary
  75.524 +prospect.  Mercurial provides the \hgcmd{incoming} command to tell us
  75.525 +what changes the \hgcmd{pull} command \emph{would} pull into the
  75.526 +repository, without actually pulling the changes in.
  75.527 +\interaction{tour.incoming}
  75.528 +(Of course, someone could cause more changesets to appear in the
  75.529 +repository that we ran \hgcmd{incoming} in, before we get a chance to
  75.530 +\hgcmd{pull} the changes, so that we could end up pulling changes that we
  75.531 +didn't expect.)
  75.532 +
  75.533 +Bringing changes into a repository is a simple matter of running the
  75.534 +\hgcmd{pull} command, and telling it which repository to pull from.
  75.535 +\interaction{tour.pull}
  75.536 +As you can see from the before-and-after output of \hgcmd{tip}, we
  75.537 +have successfully pulled changes into our repository.  There remains
  75.538 +one step before we can see these changes in the working directory.
  75.539 +
  75.540 +\subsection{Updating the working directory}
  75.541 +
  75.542 +We have so far glossed over the relationship between a repository and
  75.543 +its working directory.  The \hgcmd{pull} command that we ran in
  75.544 +section~\ref{sec:tour:pull} brought changes into the repository, but
  75.545 +if we check, there's no sign of those changes in the working
  75.546 +directory.  This is because \hgcmd{pull} does not (by default) touch
  75.547 +the working directory.  Instead, we use the \hgcmd{update} command to
  75.548 +do this.
  75.549 +\interaction{tour.update}
  75.550 +
  75.551 +It might seem a bit strange that \hgcmd{pull} doesn't update the
  75.552 +working directory automatically.  There's actually a good reason for
  75.553 +this: you can use \hgcmd{update} to update the working directory to
  75.554 +the state it was in at \emph{any revision} in the history of the
  75.555 +repository.  If you had the working directory updated to an old
  75.556 +revision---to hunt down the origin of a bug, say---and ran a
  75.557 +\hgcmd{pull} which automatically updated the working directory to a
  75.558 +new revision, you might not be terribly happy.
  75.559 +
  75.560 +However, since pull-then-update is such a common thing to do,
  75.561 +Mercurial lets you combine the two by passing the \hgopt{pull}{-u}
  75.562 +option to \hgcmd{pull}.
  75.563 +\begin{codesample2}
  75.564 +  hg pull -u
  75.565 +\end{codesample2}
  75.566 +If you look back at the output of \hgcmd{pull} in
  75.567 +section~\ref{sec:tour:pull} when we ran it without \hgopt{pull}{-u},
  75.568 +you can see that it printed a helpful reminder that we'd have to take
  75.569 +an explicit step to update the working directory:
  75.570 +\begin{codesample2}
  75.571 +  (run 'hg update' to get a working copy)
  75.572 +\end{codesample2}
  75.573 +
  75.574 +To find out what revision the working directory is at, use the
  75.575 +\hgcmd{parents} command.
  75.576 +\interaction{tour.parents}
  75.577 +If you look back at figure~\ref{fig:tour-basic:history}, you'll see
  75.578 +arrows connecting each changeset.  The node that the arrow leads
  75.579 +\emph{from} in each case is a parent, and the node that the arrow
  75.580 +leads \emph{to} is its child.  The working directory has a parent in
  75.581 +just the same way; this is the changeset that the working directory
  75.582 +currently contains.
  75.583 +
  75.584 +To update the working directory to a particular revision, give a
  75.585 +revision number or changeset~ID to the \hgcmd{update} command.
  75.586 +\interaction{tour.older}
  75.587 +If you omit an explicit revision, \hgcmd{update} will update to the
  75.588 +tip revision, as shown by the second call to \hgcmd{update} in the
  75.589 +example above.
  75.590 +
  75.591 +\subsection{Pushing changes to another repository}
  75.592 +
  75.593 +Mercurial lets us push changes to another repository, from the
  75.594 +repository we're currently visiting.  As with the example of
  75.595 +\hgcmd{pull} above, we'll create a temporary repository to push our
  75.596 +changes into.
  75.597 +\interaction{tour.clone-push}
  75.598 +The \hgcmd{outgoing} command tells us what changes would be pushed
  75.599 +into another repository.
  75.600 +\interaction{tour.outgoing}
  75.601 +And the \hgcmd{push} command does the actual push.
  75.602 +\interaction{tour.push}
  75.603 +As with \hgcmd{pull}, the \hgcmd{push} command does not update the
  75.604 +working directory in the repository that it's pushing changes into.
  75.605 +(Unlike \hgcmd{pull}, \hgcmd{push} does not provide a \texttt{-u}
  75.606 +option that updates the other repository's working directory.)
  75.607 +
  75.608 +What happens if we try to pull or push changes and the receiving
  75.609 +repository already has those changes?  Nothing too exciting.
  75.610 +\interaction{tour.push.nothing}
  75.611 +
  75.612 +\subsection{Sharing changes over a network}
  75.613 +
  75.614 +The commands we have covered in the previous few sections are not
  75.615 +limited to working with local repositories.  Each works in exactly the
  75.616 +same fashion over a network connection; simply pass in a URL instead
  75.617 +of a local path.
  75.618 +\interaction{tour.outgoing.net}
  75.619 +In this example, we can see what changes we could push to the remote
  75.620 +repository, but the repository is understandably not set up to let
  75.621 +anonymous users push to it.
  75.622 +\interaction{tour.push.net}
  75.623 +
  75.624 +%%% Local Variables: 
  75.625 +%%% mode: latex
  75.626 +%%% TeX-master: "00book"
  75.627 +%%% End: 
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/fr/tour-history.svg	Thu Feb 05 12:37:03 2009 +0100
    76.3 @@ -0,0 +1,289 @@
    76.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    76.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    76.6 +<svg
    76.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    76.8 +   xmlns:cc="http://web.resource.org/cc/"
    76.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   76.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   76.11 +   xmlns="http://www.w3.org/2000/svg"
   76.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   76.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   76.14 +   width="744.09448819"
   76.15 +   height="1052.3622047"
   76.16 +   id="svg2"
   76.17 +   sodipodi:version="0.32"
   76.18 +   inkscape:version="0.44.1"
   76.19 +   sodipodi:docname="tour-history.svg">
   76.20 +  <defs
   76.21 +     id="defs4">
   76.22 +    <marker
   76.23 +       inkscape:stockid="Arrow1Mstart"
   76.24 +       orient="auto"
   76.25 +       refY="0.0"
   76.26 +       refX="0.0"
   76.27 +       id="Arrow1Mstart"
   76.28 +       style="overflow:visible">
   76.29 +      <path
   76.30 +         id="path2973"
   76.31 +         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 "
   76.32 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   76.33 +         transform="scale(0.4) translate(10,0)" />
   76.34 +    </marker>
   76.35 +    <marker
   76.36 +       inkscape:stockid="Arrow1Mend"
   76.37 +       orient="auto"
   76.38 +       refY="0.0"
   76.39 +       refX="0.0"
   76.40 +       id="Arrow1Mend"
   76.41 +       style="overflow:visible;">
   76.42 +      <path
   76.43 +         id="path3066"
   76.44 +         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 "
   76.45 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   76.46 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   76.47 +    </marker>
   76.48 +  </defs>
   76.49 +  <sodipodi:namedview
   76.50 +     id="base"
   76.51 +     pagecolor="#ffffff"
   76.52 +     bordercolor="#666666"
   76.53 +     borderopacity="1.0"
   76.54 +     gridtolerance="10000"
   76.55 +     guidetolerance="10"
   76.56 +     objecttolerance="10"
   76.57 +     inkscape:pageopacity="0.0"
   76.58 +     inkscape:pageshadow="2"
   76.59 +     inkscape:zoom="1.4"
   76.60 +     inkscape:cx="232.14286"
   76.61 +     inkscape:cy="672.75296"
   76.62 +     inkscape:document-units="px"
   76.63 +     inkscape:current-layer="layer1"
   76.64 +     inkscape:window-width="906"
   76.65 +     inkscape:window-height="620"
   76.66 +     inkscape:window-x="5"
   76.67 +     inkscape:window-y="49" />
   76.68 +  <metadata
   76.69 +     id="metadata7">
   76.70 +    <rdf:RDF>
   76.71 +      <cc:Work
   76.72 +         rdf:about="">
   76.73 +        <dc:format>image/svg+xml</dc:format>
   76.74 +        <dc:type
   76.75 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   76.76 +      </cc:Work>
   76.77 +    </rdf:RDF>
   76.78 +  </metadata>
   76.79 +  <g
   76.80 +     inkscape:label="Layer 1"
   76.81 +     inkscape:groupmode="layer"
   76.82 +     id="layer1">
   76.83 +    <rect
   76.84 +       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"
   76.85 +       id="rect1878"
   76.86 +       width="94.285713"
   76.87 +       height="20.714285"
   76.88 +       x="138"
   76.89 +       y="479.50504" />
   76.90 +    <text
   76.91 +       xml:space="preserve"
   76.92 +       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"
   76.93 +       x="162.09892"
   76.94 +       y="493.12619"
   76.95 +       id="text1872"><tspan
   76.96 +         sodipodi:role="line"
   76.97 +         id="tspan1874"
   76.98 +         x="162.09892"
   76.99 +         y="493.12619"
  76.100 +         style="font-family:Courier"><tspan
  76.101 +   style="font-weight:bold"
  76.102 +   id="tspan1876">0</tspan>: REV0</tspan></text>
  76.103 +    <rect
  76.104 +       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"
  76.105 +       id="rect2800"
  76.106 +       width="94.285713"
  76.107 +       height="20.714285"
  76.108 +       x="138"
  76.109 +       y="432.63004" />
  76.110 +    <text
  76.111 +       xml:space="preserve"
  76.112 +       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"
  76.113 +       x="162.09892"
  76.114 +       y="446.25119"
  76.115 +       id="text2794"><tspan
  76.116 +         sodipodi:role="line"
  76.117 +         id="tspan2796"
  76.118 +         x="162.09892"
  76.119 +         y="446.25119"
  76.120 +         style="font-family:Courier"><tspan
  76.121 +   id="tspan2868"
  76.122 +   style="font-weight:bold">1</tspan>: REV1</tspan></text>
  76.123 +    <rect
  76.124 +       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"
  76.125 +       id="rect2810"
  76.126 +       width="94.285713"
  76.127 +       height="20.714285"
  76.128 +       x="138"
  76.129 +       y="385.75504" />
  76.130 +    <text
  76.131 +       xml:space="preserve"
  76.132 +       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"
  76.133 +       x="162.09892"
  76.134 +       y="399.37619"
  76.135 +       id="text2804"><tspan
  76.136 +         sodipodi:role="line"
  76.137 +         id="tspan2806"
  76.138 +         x="162.09892"
  76.139 +         y="399.37619"
  76.140 +         style="font-family:Courier"><tspan
  76.141 +   style="font-weight:bold"
  76.142 +   id="tspan2866">2</tspan>: REV2</tspan></text>
  76.143 +    <rect
  76.144 +       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"
  76.145 +       id="rect2820"
  76.146 +       width="94.285713"
  76.147 +       height="20.714285"
  76.148 +       x="138"
  76.149 +       y="338.88007" />
  76.150 +    <text
  76.151 +       xml:space="preserve"
  76.152 +       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"
  76.153 +       x="162.09892"
  76.154 +       y="352.50122"
  76.155 +       id="text2814"><tspan
  76.156 +         sodipodi:role="line"
  76.157 +         id="tspan2816"
  76.158 +         x="162.09892"
  76.159 +         y="352.50122"
  76.160 +         style="font-family:Courier"><tspan
  76.161 +   style="font-weight:bold"
  76.162 +   id="tspan2864">3</tspan>: REV3</tspan></text>
  76.163 +    <rect
  76.164 +       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"
  76.165 +       id="rect2830"
  76.166 +       width="94.285713"
  76.167 +       height="20.714285"
  76.168 +       x="138"
  76.169 +       y="292.00504" />
  76.170 +    <text
  76.171 +       xml:space="preserve"
  76.172 +       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"
  76.173 +       x="162.09892"
  76.174 +       y="305.62619"
  76.175 +       id="text2824"><tspan
  76.176 +         sodipodi:role="line"
  76.177 +         id="tspan2826"
  76.178 +         x="162.09892"
  76.179 +         y="305.62619"
  76.180 +         style="font-family:Courier"><tspan
  76.181 +   style="font-weight:bold"
  76.182 +   id="tspan2862">4</tspan>: REV4</tspan></text>
  76.183 +    <text
  76.184 +       xml:space="preserve"
  76.185 +       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"
  76.186 +       x="173.57143"
  76.187 +       y="443.79074"
  76.188 +       id="text2832"><tspan
  76.189 +         sodipodi:role="line"
  76.190 +         id="tspan2834"
  76.191 +         x="173.57143"
  76.192 +         y="443.79074" /></text>
  76.193 +    <path
  76.194 +       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)"
  76.195 +       d="M 185.14286,478.50504 L 185.14286,454.34432"
  76.196 +       id="path2894"
  76.197 +       inkscape:connector-type="polyline" />
  76.198 +    <path
  76.199 +       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)"
  76.200 +       d="M 185.14286,431.63004 L 185.14286,407.46932"
  76.201 +       id="path2896"
  76.202 +       inkscape:connector-type="polyline" />
  76.203 +    <path
  76.204 +       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)"
  76.205 +       d="M 185.14286,384.75504 L 185.14286,360.59435"
  76.206 +       id="path2898"
  76.207 +       inkscape:connector-type="polyline" />
  76.208 +    <path
  76.209 +       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)"
  76.210 +       d="M 185.14286,337.88007 L 185.14286,313.71932"
  76.211 +       id="path2900"
  76.212 +       inkscape:connector-type="polyline" />
  76.213 +    <text
  76.214 +       xml:space="preserve"
  76.215 +       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"
  76.216 +       x="244.60992"
  76.217 +       y="305.245"
  76.218 +       id="text1902"><tspan
  76.219 +         sodipodi:role="line"
  76.220 +         id="tspan1904"
  76.221 +         x="244.60992"
  76.222 +         y="305.245">(newest)</tspan></text>
  76.223 +    <text
  76.224 +       xml:space="preserve"
  76.225 +       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"
  76.226 +       x="244.60992"
  76.227 +       y="492.745"
  76.228 +       id="text1906"><tspan
  76.229 +         sodipodi:role="line"
  76.230 +         id="tspan1908"
  76.231 +         x="244.60992"
  76.232 +         y="492.745">(oldest)</tspan></text>
  76.233 +    <rect
  76.234 +       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"
  76.235 +       id="rect1907"
  76.236 +       width="94.285713"
  76.237 +       height="20.714285"
  76.238 +       x="309.28571"
  76.239 +       y="324.86218" />
  76.240 +    <text
  76.241 +       xml:space="preserve"
  76.242 +       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"
  76.243 +       x="333.38464"
  76.244 +       y="338.48334"
  76.245 +       id="text1909"><tspan
  76.246 +         sodipodi:role="line"
  76.247 +         id="tspan1911"
  76.248 +         x="333.38464"
  76.249 +         y="338.48334"
  76.250 +         style="font-family:Courier"><tspan
  76.251 +   style="font-weight:bold"
  76.252 +   id="tspan1913">4</tspan>: REV4</tspan></text>
  76.253 +    <path
  76.254 +       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"
  76.255 +       d="M 332.14286,375.21932 L 335.71429,347.36218"
  76.256 +       id="path2802" />
  76.257 +    <path
  76.258 +       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"
  76.259 +       d="M 372.69968,375.21932 L 369.12825,347.36218"
  76.260 +       id="path2986" />
  76.261 +    <text
  76.262 +       xml:space="preserve"
  76.263 +       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"
  76.264 +       x="335.14285"
  76.265 +       y="387.21933"
  76.266 +       id="text2988"><tspan
  76.267 +         sodipodi:role="line"
  76.268 +         x="335.14285"
  76.269 +         y="387.21933"
  76.270 +         id="tspan3020"
  76.271 +         style="text-align:end;text-anchor:end">revision</tspan><tspan
  76.272 +         sodipodi:role="line"
  76.273 +         x="335.14285"
  76.274 +         y="402.21933"
  76.275 +         id="tspan3014"
  76.276 +         style="text-align:end;text-anchor:end">number</tspan></text>
  76.277 +    <text
  76.278 +       xml:space="preserve"
  76.279 +       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"
  76.280 +       x="368.71429"
  76.281 +       y="387.21933"
  76.282 +       id="text2994"><tspan
  76.283 +         sodipodi:role="line"
  76.284 +         id="tspan2996"
  76.285 +         x="368.71429"
  76.286 +         y="387.21933">changeset</tspan><tspan
  76.287 +         sodipodi:role="line"
  76.288 +         x="368.71429"
  76.289 +         y="402.21933"
  76.290 +         id="tspan2998">identifier</tspan></text>
  76.291 +  </g>
  76.292 +</svg>
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/fr/tour-merge-conflict.svg	Thu Feb 05 12:37:03 2009 +0100
    77.3 @@ -0,0 +1,210 @@
    77.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    77.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    77.6 +<svg
    77.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    77.8 +   xmlns:cc="http://web.resource.org/cc/"
    77.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   77.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   77.11 +   xmlns="http://www.w3.org/2000/svg"
   77.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   77.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   77.14 +   width="744.09448819"
   77.15 +   height="1052.3622047"
   77.16 +   id="svg2"
   77.17 +   sodipodi:version="0.32"
   77.18 +   inkscape:version="0.44.1"
   77.19 +   sodipodi:docname="tour-merge-conflict.svg">
   77.20 +  <defs
   77.21 +     id="defs4">
   77.22 +    <marker
   77.23 +       inkscape:stockid="Arrow1Mend"
   77.24 +       orient="auto"
   77.25 +       refY="0.0"
   77.26 +       refX="0.0"
   77.27 +       id="Arrow1Mend"
   77.28 +       style="overflow:visible;">
   77.29 +      <path
   77.30 +         id="path3053"
   77.31 +         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 "
   77.32 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   77.33 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   77.34 +    </marker>
   77.35 +  </defs>
   77.36 +  <sodipodi:namedview
   77.37 +     id="base"
   77.38 +     pagecolor="#ffffff"
   77.39 +     bordercolor="#666666"
   77.40 +     borderopacity="1.0"
   77.41 +     gridtolerance="10000"
   77.42 +     guidetolerance="10"
   77.43 +     objecttolerance="10"
   77.44 +     inkscape:pageopacity="0.0"
   77.45 +     inkscape:pageshadow="2"
   77.46 +     inkscape:zoom="1.4"
   77.47 +     inkscape:cx="164.78349"
   77.48 +     inkscape:cy="590.07679"
   77.49 +     inkscape:document-units="px"
   77.50 +     inkscape:current-layer="layer1"
   77.51 +     inkscape:window-width="906"
   77.52 +     inkscape:window-height="620"
   77.53 +     inkscape:window-x="5"
   77.54 +     inkscape:window-y="49" />
   77.55 +  <metadata
   77.56 +     id="metadata7">
   77.57 +    <rdf:RDF>
   77.58 +      <cc:Work
   77.59 +         rdf:about="">
   77.60 +        <dc:format>image/svg+xml</dc:format>
   77.61 +        <dc:type
   77.62 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   77.63 +      </cc:Work>
   77.64 +    </rdf:RDF>
   77.65 +  </metadata>
   77.66 +  <g
   77.67 +     inkscape:label="Layer 1"
   77.68 +     inkscape:groupmode="layer"
   77.69 +     id="layer1">
   77.70 +    <g
   77.71 +       id="g1988"
   77.72 +       transform="translate(84.85711,0)">
   77.73 +      <g
   77.74 +         id="g1876">
   77.75 +        <path
   77.76 +           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
   77.77 +           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 "
   77.78 +           id="path1872"
   77.79 +           sodipodi:nodetypes="cccccc" />
   77.80 +        <path
   77.81 +           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
   77.82 +           d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242"
   77.83 +           id="path1874"
   77.84 +           sodipodi:nodetypes="cccc" />
   77.85 +      </g>
   77.86 +      <flowRoot
   77.87 +         style="font-size:8px;font-family:Times New Roman"
   77.88 +         id="flowRoot1898"
   77.89 +         xml:space="preserve"><flowRegion
   77.90 +           id="flowRegion1900"><rect
   77.91 +             style="font-size:8px;font-family:Times New Roman"
   77.92 +             y="464.50504"
   77.93 +             x="122.85714"
   77.94 +             height="93.571426"
   77.95 +             width="76.428574"
   77.96 +             id="rect1902" /></flowRegion><flowPara
   77.97 +           id="flowPara1904">Greetings!</flowPara><flowPara
   77.98 +           id="flowPara1906" /><flowPara
   77.99 +           id="flowPara1908">I am Mariam Abacha, the wife of former Nigerian dictator Sani Abacha. I am contacting you in confidence, and as a means of developing</flowPara></flowRoot>    </g>
  77.100 +    <g
  77.101 +       id="g1966"
  77.102 +       transform="translate(82,0.35715)">
  77.103 +      <g
  77.104 +         transform="translate(-77.85718,-140.0714)"
  77.105 +         id="g1910">
  77.106 +        <path
  77.107 +           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
  77.108 +           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 "
  77.109 +           id="path1912"
  77.110 +           sodipodi:nodetypes="cccccc" />
  77.111 +        <path
  77.112 +           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
  77.113 +           d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242"
  77.114 +           id="path1914"
  77.115 +           sodipodi:nodetypes="cccc" />
  77.116 +      </g>
  77.117 +      <flowRoot
  77.118 +         transform="translate(-77.85718,-140.0714)"
  77.119 +         style="font-size:8px;font-family:Times New Roman"
  77.120 +         id="flowRoot1916"
  77.121 +         xml:space="preserve"><flowRegion
  77.122 +           id="flowRegion1918"><rect
  77.123 +             style="font-size:8px;font-family:Times New Roman"
  77.124 +             y="464.50504"
  77.125 +             x="122.85714"
  77.126 +             height="93.571426"
  77.127 +             width="76.428574"
  77.128 +             id="rect1920" /></flowRegion><flowPara
  77.129 +           id="flowPara1922">Greetings!</flowPara><flowPara
  77.130 +           id="flowPara1924" /><flowPara
  77.131 +           id="flowPara1926">I am <flowSpan
  77.132 +   style="font-style:italic;fill:red"
  77.133 +   id="flowSpan3094">Shehu Musa Abacha, cousin to</flowSpan> the former Nigerian dictator Sani Abacha. I am contacting you in confidence, and as a means of developing</flowPara></flowRoot>    </g>
  77.134 +    <g
  77.135 +       id="g1977"
  77.136 +       transform="translate(81.99999,-0.35715)">
  77.137 +      <g
  77.138 +         transform="translate(83.57141,-139.3571)"
  77.139 +         id="g1932">
  77.140 +        <path
  77.141 +           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
  77.142 +           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 "
  77.143 +           id="path1934"
  77.144 +           sodipodi:nodetypes="cccccc" />
  77.145 +        <path
  77.146 +           style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
  77.147 +           d="M 191.55484,563.36862 L 191.6923,560.98794 L 192.69126,552.44884 L 203.80416,551.31242"
  77.148 +           id="path1936"
  77.149 +           sodipodi:nodetypes="cccc" />
  77.150 +      </g>
  77.151 +      <flowRoot
  77.152 +         transform="translate(83.57141,-139.3571)"
  77.153 +         style="font-size:8px;font-family:Times New Roman"
  77.154 +         id="flowRoot1938"
  77.155 +         xml:space="preserve"><flowRegion
  77.156 +           id="flowRegion1940"><rect
  77.157 +             style="font-size:8px;font-family:Times New Roman"
  77.158 +             y="464.50504"
  77.159 +             x="122.85714"
  77.160 +             height="93.571426"
  77.161 +             width="76.428574"
  77.162 +             id="rect1942" /></flowRegion><flowPara
  77.163 +           id="flowPara1944">Greetings!</flowPara><flowPara
  77.164 +           id="flowPara1946" /><flowPara
  77.165 +           id="flowPara1948">I am <flowSpan
  77.166 +   style="font-style:italic;fill:red"
  77.167 +   id="flowSpan3096">Alhaji Abba Abacha, son of</flowSpan> the former Nigerian dictator Sani Abacha. I am contacting you in confidence, and as a means of developing</flowPara></flowRoot>    </g>
  77.168 +    <path
  77.169 +       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"
  77.170 +       d="M 215.502,457.71933 L 196.35507,424.5765"
  77.171 +       id="path1999"
  77.172 +       inkscape:connector-type="polyline"
  77.173 +       inkscape:connection-start="#g1988"
  77.174 +       inkscape:connection-end="#g1966" />
  77.175 +    <path
  77.176 +       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"
  77.177 +       d="M 277.06936,457.71933 L 296.21629,424.5765"
  77.178 +       id="path2001"
  77.179 +       inkscape:connector-type="polyline"
  77.180 +       inkscape:connection-start="#g1988"
  77.181 +       inkscape:connection-end="#g1977" />
  77.182 +    <text
  77.183 +       xml:space="preserve"
  77.184 +       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"
  77.185 +       x="302.42859"
  77.186 +       y="515.08905"
  77.187 +       id="text1905"><tspan
  77.188 +         sodipodi:role="line"
  77.189 +         id="tspan1907"
  77.190 +         x="302.42859"
  77.191 +         y="515.08905">Base version</tspan></text>
  77.192 +    <text
  77.193 +       xml:space="preserve"
  77.194 +       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"
  77.195 +       x="45.57143"
  77.196 +       y="374.1619"
  77.197 +       id="text1917"><tspan
  77.198 +         sodipodi:role="line"
  77.199 +         id="tspan1919"
  77.200 +         x="45.57143"
  77.201 +         y="374.1619">Our changes</tspan></text>
  77.202 +    <text
  77.203 +       xml:space="preserve"
  77.204 +       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"
  77.205 +       x="385.71429"
  77.206 +       y="374.1619"
  77.207 +       id="text1921"><tspan
  77.208 +         sodipodi:role="line"
  77.209 +         id="tspan1923"
  77.210 +         x="385.71429"
  77.211 +         y="374.1619">Their changes</tspan></text>
  77.212 +  </g>
  77.213 +</svg>
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/fr/tour-merge-merge.svg	Thu Feb 05 12:37:03 2009 +0100
    78.3 @@ -0,0 +1,380 @@
    78.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    78.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    78.6 +<svg
    78.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    78.8 +   xmlns:cc="http://web.resource.org/cc/"
    78.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   78.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   78.11 +   xmlns="http://www.w3.org/2000/svg"
   78.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   78.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   78.14 +   width="744.09448819"
   78.15 +   height="1052.3622047"
   78.16 +   id="svg2"
   78.17 +   sodipodi:version="0.32"
   78.18 +   inkscape:version="0.44.1"
   78.19 +   sodipodi:docname="tour-merge-merge.svg">
   78.20 +  <defs
   78.21 +     id="defs4">
   78.22 +    <marker
   78.23 +       inkscape:stockid="Arrow1Mstart"
   78.24 +       orient="auto"
   78.25 +       refY="0.0"
   78.26 +       refX="0.0"
   78.27 +       id="Arrow1Mstart"
   78.28 +       style="overflow:visible">
   78.29 +      <path
   78.30 +         id="path2973"
   78.31 +         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 "
   78.32 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   78.33 +         transform="scale(0.4) translate(10,0)" />
   78.34 +    </marker>
   78.35 +    <marker
   78.36 +       inkscape:stockid="Arrow1Mend"
   78.37 +       orient="auto"
   78.38 +       refY="0.0"
   78.39 +       refX="0.0"
   78.40 +       id="Arrow1Mend"
   78.41 +       style="overflow:visible;">
   78.42 +      <path
   78.43 +         id="path3066"
   78.44 +         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 "
   78.45 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   78.46 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   78.47 +    </marker>
   78.48 +  </defs>
   78.49 +  <sodipodi:namedview
   78.50 +     id="base"
   78.51 +     pagecolor="#ffffff"
   78.52 +     bordercolor="#666666"
   78.53 +     borderopacity="1.0"
   78.54 +     gridtolerance="10000"
   78.55 +     guidetolerance="10"
   78.56 +     objecttolerance="10"
   78.57 +     inkscape:pageopacity="0.0"
   78.58 +     inkscape:pageshadow="2"
   78.59 +     inkscape:zoom="1.4"
   78.60 +     inkscape:cx="247.53795"
   78.61 +     inkscape:cy="871.05738"
   78.62 +     inkscape:document-units="px"
   78.63 +     inkscape:current-layer="layer1"
   78.64 +     inkscape:window-width="906"
   78.65 +     inkscape:window-height="620"
   78.66 +     inkscape:window-x="38"
   78.67 +     inkscape:window-y="95" />
   78.68 +  <metadata
   78.69 +     id="metadata7">
   78.70 +    <rdf:RDF>
   78.71 +      <cc:Work
   78.72 +         rdf:about="">
   78.73 +        <dc:format>image/svg+xml</dc:format>
   78.74 +        <dc:type
   78.75 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   78.76 +      </cc:Work>
   78.77 +    </rdf:RDF>
   78.78 +  </metadata>
   78.79 +  <g
   78.80 +     inkscape:label="Layer 1"
   78.81 +     inkscape:groupmode="layer"
   78.82 +     id="layer1">
   78.83 +    <rect
   78.84 +       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"
   78.85 +       id="rect2995"
   78.86 +       width="94.285713"
   78.87 +       height="20.714285"
   78.88 +       x="532.85718"
   78.89 +       y="203.0479" />
   78.90 +    <text
   78.91 +       xml:space="preserve"
   78.92 +       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"
   78.93 +       x="173.57143"
   78.94 +       y="443.79074"
   78.95 +       id="text2832"><tspan
   78.96 +         sodipodi:role="line"
   78.97 +         id="tspan2834"
   78.98 +         x="173.57143"
   78.99 +         y="443.79074" /></text>
  78.100 +    <rect
  78.101 +       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"
  78.102 +       id="rect2830"
  78.103 +       width="94.285713"
  78.104 +       height="20.714285"
  78.105 +       x="138"
  78.106 +       y="297.76227" />
  78.107 +    <text
  78.108 +       xml:space="preserve"
  78.109 +       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"
  78.110 +       x="162.09892"
  78.111 +       y="311.38342"
  78.112 +       id="text2824"><tspan
  78.113 +         sodipodi:role="line"
  78.114 +         id="tspan2826"
  78.115 +         x="162.09892"
  78.116 +         y="311.38342"
  78.117 +         style="font-family:Courier"><tspan
  78.118 +   style="font-weight:bold"
  78.119 +   id="tspan2862">4</tspan>: REV4</tspan></text>
  78.120 +    <path
  78.121 +       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"
  78.122 +       d="M 185.14286,343.63731 L 185.14286,319.47656"
  78.123 +       id="path2900"
  78.124 +       inkscape:connector-type="polyline" />
  78.125 +    <rect
  78.126 +       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"
  78.127 +       id="rect2863"
  78.128 +       width="94.285713"
  78.129 +       height="20.714285"
  78.130 +       x="91.428574"
  78.131 +       y="250.47656" />
  78.132 +    <text
  78.133 +       xml:space="preserve"
  78.134 +       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"
  78.135 +       x="116.09886"
  78.136 +       y="264.56592"
  78.137 +       id="text1965"
  78.138 +       transform="scale(1.000002,0.999998)"><tspan
  78.139 +         sodipodi:role="line"
  78.140 +         id="tspan1967"
  78.141 +         x="116.09886"
  78.142 +         y="264.56592"
  78.143 +         style="font-family:Courier"><tspan
  78.144 +   style="font-weight:bold"
  78.145 +   id="tspan1973">5</tspan>: REV_my_new_hello</tspan></text>
  78.146 +    <path
  78.147 +       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"
  78.148 +       d="M 173.95727,296.76228 L 149.75702,272.19085"
  78.149 +       id="path1971"
  78.150 +       inkscape:connector-type="polyline"
  78.151 +       inkscape:connection-end="#rect2863"
  78.152 +       inkscape:connection-start="#rect2830" />
  78.153 +    <rect
  78.154 +       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"
  78.155 +       id="rect2911"
  78.156 +       width="94.285995"
  78.157 +       height="20.714283"
  78.158 +       x="186.71414"
  78.159 +       y="204.40514" />
  78.160 +    <text
  78.161 +       xml:space="preserve"
  78.162 +       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"
  78.163 +       x="210.81311"
  78.164 +       y="218.02673"
  78.165 +       id="text2913"
  78.166 +       transform="scale(1.000002,0.999998)"><tspan
  78.167 +         sodipodi:role="line"
  78.168 +         id="tspan2915"
  78.169 +         x="210.81311"
  78.170 +         y="218.02673"
  78.171 +         style="font-family:Courier"><tspan
  78.172 +   id="tspan1966"
  78.173 +   style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text>
  78.174 +    <path
  78.175 +       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"
  78.176 +       d="M 191.06908,296.76228 L 227.93092,226.11942"
  78.177 +       id="path2919"
  78.178 +       inkscape:connector-type="polyline"
  78.179 +       inkscape:connection-start="#rect2830" />
  78.180 +    <text
  78.181 +       xml:space="preserve"
  78.182 +       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"
  78.183 +       x="295.28571"
  78.184 +       y="217.56711"
  78.185 +       id="text2871"><tspan
  78.186 +         sodipodi:role="line"
  78.187 +         id="tspan2873"
  78.188 +         x="295.28571"
  78.189 +         y="217.56711">tip (and head)</tspan></text>
  78.190 +    <text
  78.191 +       xml:space="preserve"
  78.192 +       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"
  78.193 +       x="76"
  78.194 +       y="264.91769"
  78.195 +       id="text2875"><tspan
  78.196 +         sodipodi:role="line"
  78.197 +         id="tspan2877"
  78.198 +         x="76"
  78.199 +         y="264.91769"
  78.200 +         style="text-align:end;text-anchor:end">head</tspan></text>
  78.201 +    <rect
  78.202 +       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"
  78.203 +       id="rect1913"
  78.204 +       width="94.285713"
  78.205 +       height="20.714285"
  78.206 +       x="138"
  78.207 +       y="156.90514" />
  78.208 +    <path
  78.209 +       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"
  78.210 +       d="M 144.22399,249.47657 L 179.49029,178.61943"
  78.211 +       id="path1915"
  78.212 +       inkscape:connector-type="polyline"
  78.213 +       inkscape:connection-start="#rect2863"
  78.214 +       inkscape:connection-end="#rect1913" />
  78.215 +    <path
  78.216 +       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"
  78.217 +       d="M 222.20966,203.40514 L 196.79033,178.61943"
  78.218 +       id="path1917"
  78.219 +       inkscape:connector-type="polyline"
  78.220 +       inkscape:connection-start="#rect2911"
  78.221 +       inkscape:connection-end="#rect1913" />
  78.222 +    <text
  78.223 +       xml:space="preserve"
  78.224 +       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"
  78.225 +       x="166.16823"
  78.226 +       y="168.52228"
  78.227 +       id="text2806"><tspan
  78.228 +         sodipodi:role="line"
  78.229 +         id="tspan2808"
  78.230 +         x="166.16823"
  78.231 +         y="168.52228"
  78.232 +         style="font-family:Courier">merge</tspan></text>
  78.233 +    <text
  78.234 +       xml:space="preserve"
  78.235 +       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"
  78.236 +       x="246"
  78.237 +       y="162.63338"
  78.238 +       id="text2810"><tspan
  78.239 +         sodipodi:role="line"
  78.240 +         id="tspan2812"
  78.241 +         x="246"
  78.242 +         y="162.63338">working directory</tspan><tspan
  78.243 +         sodipodi:role="line"
  78.244 +         x="246"
  78.245 +         y="177.63338"
  78.246 +         id="tspan2814">during merge</tspan></text>
  78.247 +    <rect
  78.248 +       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"
  78.249 +       id="rect2816"
  78.250 +       width="94.285713"
  78.251 +       height="20.714285"
  78.252 +       x="483.14636"
  78.253 +       y="297.76227" />
  78.254 +    <text
  78.255 +       xml:space="preserve"
  78.256 +       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"
  78.257 +       x="507.24527"
  78.258 +       y="311.38342"
  78.259 +       id="text2818"><tspan
  78.260 +         sodipodi:role="line"
  78.261 +         id="tspan2820"
  78.262 +         x="507.24527"
  78.263 +         y="311.38342"
  78.264 +         style="font-family:Courier"><tspan
  78.265 +   style="font-weight:bold"
  78.266 +   id="tspan2822">4</tspan>: REV4</tspan></text>
  78.267 +    <path
  78.268 +       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"
  78.269 +       d="M 530.28921,343.6373 L 530.28921,319.47655"
  78.270 +       id="path2824"
  78.271 +       inkscape:connector-type="polyline" />
  78.272 +    <rect
  78.273 +       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"
  78.274 +       id="rect2826"
  78.275 +       width="94.285713"
  78.276 +       height="20.714285"
  78.277 +       x="436.57492"
  78.278 +       y="250.47656" />
  78.279 +    <text
  78.280 +       xml:space="preserve"
  78.281 +       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"
  78.282 +       x="461.24484"
  78.283 +       y="264.56613"
  78.284 +       id="text2828"
  78.285 +       transform="scale(1.000002,0.999998)"><tspan
  78.286 +         sodipodi:role="line"
  78.287 +         id="tspan2830"
  78.288 +         x="461.24484"
  78.289 +         y="264.56613"
  78.290 +         style="font-family:Courier"><tspan
  78.291 +   style="font-weight:bold"
  78.292 +   id="tspan2832">5</tspan>: REV_my_new_hello</tspan></text>
  78.293 +    <path
  78.294 +       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"
  78.295 +       d="M 519.10362,296.76227 L 494.90337,272.19084"
  78.296 +       id="path2834"
  78.297 +       inkscape:connector-type="polyline" />
  78.298 +    <rect
  78.299 +       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"
  78.300 +       id="rect2836"
  78.301 +       width="94.285995"
  78.302 +       height="20.714283"
  78.303 +       x="483.14001"
  78.304 +       y="156.548" />
  78.305 +    <text
  78.306 +       xml:space="preserve"
  78.307 +       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"
  78.308 +       x="555.95911"
  78.309 +       y="218.02698"
  78.310 +       id="text2838"
  78.311 +       transform="scale(1.000002,0.999998)"><tspan
  78.312 +         sodipodi:role="line"
  78.313 +         id="tspan2840"
  78.314 +         x="555.95911"
  78.315 +         y="218.02698"
  78.316 +         style="font-family:Courier"><tspan
  78.317 +   id="tspan2842"
  78.318 +   style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text>
  78.319 +    <path
  78.320 +       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"
  78.321 +       d="M 536.21543,296.76227 L 574.03453,224.76218"
  78.322 +       id="path2844"
  78.323 +       inkscape:connector-type="polyline" />
  78.324 +    <text
  78.325 +       xml:space="preserve"
  78.326 +       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"
  78.327 +       x="594.43207"
  78.328 +       y="169.78796"
  78.329 +       id="text2846"><tspan
  78.330 +         sodipodi:role="line"
  78.331 +         id="tspan2848"
  78.332 +         x="594.43207"
  78.333 +         y="169.78796">tip</tspan></text>
  78.334 +    <path
  78.335 +       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"
  78.336 +       d="M 489.37034,249.47656 L 524.65575,178.26229"
  78.337 +       id="path2856"
  78.338 +       inkscape:connector-type="polyline"
  78.339 +       inkscape:connection-end="#rect2836" />
  78.340 +    <path
  78.341 +       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"
  78.342 +       d="M 567.85714,202.0479 L 542.42591,178.26229"
  78.343 +       id="path2858"
  78.344 +       inkscape:connector-type="polyline"
  78.345 +       inkscape:connection-end="#rect2836"
  78.346 +       inkscape:connection-start="#rect2995" />
  78.347 +    <text
  78.348 +       xml:space="preserve"
  78.349 +       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"
  78.350 +       x="504.54507"
  78.351 +       y="170.39714"
  78.352 +       id="text2860"><tspan
  78.353 +         sodipodi:role="line"
  78.354 +         id="tspan2863"
  78.355 +         x="504.54507"
  78.356 +         y="170.39714"
  78.357 +         style="font-family:Courier"><tspan
  78.358 +   style="font-weight:bold"
  78.359 +   id="tspan2997">7</tspan>: REV7_my_new_hello</tspan></text>
  78.360 +    <text
  78.361 +       xml:space="preserve"
  78.362 +       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"
  78.363 +       x="90.323105"
  78.364 +       y="120.21933"
  78.365 +       id="text2929"><tspan
  78.366 +         sodipodi:role="line"
  78.367 +         id="tspan2931"
  78.368 +         x="90.323105"
  78.369 +         y="120.21933"
  78.370 +         style="font-weight:bold">Working directory during merge</tspan></text>
  78.371 +    <text
  78.372 +       xml:space="preserve"
  78.373 +       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"
  78.374 +       x="435.35226"
  78.375 +       y="120.21933"
  78.376 +       id="text2937"><tspan
  78.377 +         sodipodi:role="line"
  78.378 +         id="tspan2939"
  78.379 +         x="435.35226"
  78.380 +         y="120.21933"
  78.381 +         style="font-weight:bold">Repository after merge committed</tspan></text>
  78.382 +  </g>
  78.383 +</svg>
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/fr/tour-merge-pull.svg	Thu Feb 05 12:37:03 2009 +0100
    79.3 @@ -0,0 +1,288 @@
    79.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    79.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    79.6 +<svg
    79.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    79.8 +   xmlns:cc="http://web.resource.org/cc/"
    79.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   79.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   79.11 +   xmlns="http://www.w3.org/2000/svg"
   79.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   79.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   79.14 +   width="744.09448819"
   79.15 +   height="1052.3622047"
   79.16 +   id="svg2"
   79.17 +   sodipodi:version="0.32"
   79.18 +   inkscape:version="0.44.1"
   79.19 +   sodipodi:docname="tour-merge-pull.svg"
   79.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en">
   79.21 +  <defs
   79.22 +     id="defs4">
   79.23 +    <marker
   79.24 +       inkscape:stockid="Arrow1Mstart"
   79.25 +       orient="auto"
   79.26 +       refY="0.0"
   79.27 +       refX="0.0"
   79.28 +       id="Arrow1Mstart"
   79.29 +       style="overflow:visible">
   79.30 +      <path
   79.31 +         id="path2973"
   79.32 +         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 "
   79.33 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   79.34 +         transform="scale(0.4) translate(10,0)" />
   79.35 +    </marker>
   79.36 +    <marker
   79.37 +       inkscape:stockid="Arrow1Mend"
   79.38 +       orient="auto"
   79.39 +       refY="0.0"
   79.40 +       refX="0.0"
   79.41 +       id="Arrow1Mend"
   79.42 +       style="overflow:visible;">
   79.43 +      <path
   79.44 +         id="path3066"
   79.45 +         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 "
   79.46 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   79.47 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   79.48 +    </marker>
   79.49 +  </defs>
   79.50 +  <sodipodi:namedview
   79.51 +     id="base"
   79.52 +     pagecolor="#ffffff"
   79.53 +     bordercolor="#666666"
   79.54 +     borderopacity="1.0"
   79.55 +     gridtolerance="10000"
   79.56 +     guidetolerance="10"
   79.57 +     objecttolerance="10"
   79.58 +     inkscape:pageopacity="0.0"
   79.59 +     inkscape:pageshadow="2"
   79.60 +     inkscape:zoom="1.4"
   79.61 +     inkscape:cx="233.63208"
   79.62 +     inkscape:cy="832.54381"
   79.63 +     inkscape:document-units="px"
   79.64 +     inkscape:current-layer="layer1"
   79.65 +     inkscape:window-width="906"
   79.66 +     inkscape:window-height="620"
   79.67 +     inkscape:window-x="237"
   79.68 +     inkscape:window-y="103" />
   79.69 +  <metadata
   79.70 +     id="metadata7">
   79.71 +    <rdf:RDF>
   79.72 +      <cc:Work
   79.73 +         rdf:about="">
   79.74 +        <dc:format>image/svg+xml</dc:format>
   79.75 +        <dc:type
   79.76 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   79.77 +      </cc:Work>
   79.78 +    </rdf:RDF>
   79.79 +  </metadata>
   79.80 +  <g
   79.81 +     inkscape:label="Layer 1"
   79.82 +     inkscape:groupmode="layer"
   79.83 +     id="layer1">
   79.84 +    <text
   79.85 +       xml:space="preserve"
   79.86 +       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"
   79.87 +       x="173.57143"
   79.88 +       y="443.79074"
   79.89 +       id="text2832"><tspan
   79.90 +         sodipodi:role="line"
   79.91 +         id="tspan2834"
   79.92 +         x="173.57143"
   79.93 +         y="443.79074" /></text>
   79.94 +    <rect
   79.95 +       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"
   79.96 +       id="rect1878"
   79.97 +       width="94.285713"
   79.98 +       height="20.714285"
   79.99 +       x="138"
  79.100 +       y="479.50504" />
  79.101 +    <text
  79.102 +       xml:space="preserve"
  79.103 +       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"
  79.104 +       x="162.09892"
  79.105 +       y="493.12619"
  79.106 +       id="text1872"><tspan
  79.107 +         sodipodi:role="line"
  79.108 +         id="tspan1874"
  79.109 +         x="162.09892"
  79.110 +         y="493.12619"
  79.111 +         style="font-family:Courier"><tspan
  79.112 +   style="font-weight:bold"
  79.113 +   id="tspan1876">0</tspan>: REV0</tspan></text>
  79.114 +    <rect
  79.115 +       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"
  79.116 +       id="rect2800"
  79.117 +       width="94.285713"
  79.118 +       height="20.714285"
  79.119 +       x="138"
  79.120 +       y="432.63004" />
  79.121 +    <text
  79.122 +       xml:space="preserve"
  79.123 +       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"
  79.124 +       x="162.09892"
  79.125 +       y="446.25119"
  79.126 +       id="text2794"><tspan
  79.127 +         sodipodi:role="line"
  79.128 +         id="tspan2796"
  79.129 +         x="162.09892"
  79.130 +         y="446.25119"
  79.131 +         style="font-family:Courier"><tspan
  79.132 +   id="tspan2868"
  79.133 +   style="font-weight:bold">1</tspan>: REV1</tspan></text>
  79.134 +    <rect
  79.135 +       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"
  79.136 +       id="rect2810"
  79.137 +       width="94.285713"
  79.138 +       height="20.714285"
  79.139 +       x="138"
  79.140 +       y="385.75504" />
  79.141 +    <text
  79.142 +       xml:space="preserve"
  79.143 +       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"
  79.144 +       x="162.09892"
  79.145 +       y="399.37619"
  79.146 +       id="text2804"><tspan
  79.147 +         sodipodi:role="line"
  79.148 +         id="tspan2806"
  79.149 +         x="162.09892"
  79.150 +         y="399.37619"
  79.151 +         style="font-family:Courier"><tspan
  79.152 +   style="font-weight:bold"
  79.153 +   id="tspan2866">2</tspan>: REV2</tspan></text>
  79.154 +    <rect
  79.155 +       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"
  79.156 +       id="rect2820"
  79.157 +       width="94.285713"
  79.158 +       height="20.714285"
  79.159 +       x="138"
  79.160 +       y="338.88007" />
  79.161 +    <text
  79.162 +       xml:space="preserve"
  79.163 +       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"
  79.164 +       x="162.09892"
  79.165 +       y="352.50122"
  79.166 +       id="text2814"><tspan
  79.167 +         sodipodi:role="line"
  79.168 +         id="tspan2816"
  79.169 +         x="162.09892"
  79.170 +         y="352.50122"
  79.171 +         style="font-family:Courier"><tspan
  79.172 +   style="font-weight:bold"
  79.173 +   id="tspan2864">3</tspan>: REV3</tspan></text>
  79.174 +    <rect
  79.175 +       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"
  79.176 +       id="rect2830"
  79.177 +       width="94.285713"
  79.178 +       height="20.714285"
  79.179 +       x="138"
  79.180 +       y="292.00504" />
  79.181 +    <text
  79.182 +       xml:space="preserve"
  79.183 +       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"
  79.184 +       x="162.09892"
  79.185 +       y="305.62619"
  79.186 +       id="text2824"><tspan
  79.187 +         sodipodi:role="line"
  79.188 +         id="tspan2826"
  79.189 +         x="162.09892"
  79.190 +         y="305.62619"
  79.191 +         style="font-family:Courier"><tspan
  79.192 +   style="font-weight:bold"
  79.193 +   id="tspan2862">4</tspan>: REV4</tspan></text>
  79.194 +    <path
  79.195 +       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"
  79.196 +       d="M 185.14286,478.50504 L 185.14286,454.34432"
  79.197 +       id="path2894"
  79.198 +       inkscape:connector-type="polyline" />
  79.199 +    <path
  79.200 +       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"
  79.201 +       d="M 185.14286,431.63004 L 185.14286,407.46932"
  79.202 +       id="path2896"
  79.203 +       inkscape:connector-type="polyline" />
  79.204 +    <path
  79.205 +       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"
  79.206 +       d="M 185.14286,384.75504 L 185.14286,360.59435"
  79.207 +       id="path2898"
  79.208 +       inkscape:connector-type="polyline" />
  79.209 +    <path
  79.210 +       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"
  79.211 +       d="M 185.14286,337.88007 L 185.14286,313.71932"
  79.212 +       id="path2900"
  79.213 +       inkscape:connector-type="polyline" />
  79.214 +    <rect
  79.215 +       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"
  79.216 +       id="rect2863"
  79.217 +       width="94.285713"
  79.218 +       height="20.714285"
  79.219 +       x="91.428574"
  79.220 +       y="244.71933" />
  79.221 +    <text
  79.222 +       xml:space="preserve"
  79.223 +       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"
  79.224 +       x="116.09886"
  79.225 +       y="258.80865"
  79.226 +       id="text1965"
  79.227 +       transform="scale(1.000002,0.999998)"><tspan
  79.228 +         sodipodi:role="line"
  79.229 +         id="tspan1967"
  79.230 +         x="116.09886"
  79.231 +         y="258.80865"
  79.232 +         style="font-family:Courier"><tspan
  79.233 +   style="font-weight:bold"
  79.234 +   id="tspan1973">5</tspan>: REV_my_new_hello</tspan></text>
  79.235 +    <path
  79.236 +       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"
  79.237 +       d="M 173.95727,291.00504 L 149.75702,266.43361"
  79.238 +       id="path1971"
  79.239 +       inkscape:connector-type="polyline"
  79.240 +       inkscape:connection-end="#rect2863"
  79.241 +       inkscape:connection-start="#rect2830" />
  79.242 +    <rect
  79.243 +       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"
  79.244 +       id="rect2911"
  79.245 +       width="94.285995"
  79.246 +       height="20.714283"
  79.247 +       x="186.71414"
  79.248 +       y="198.6479" />
  79.249 +    <text
  79.250 +       xml:space="preserve"
  79.251 +       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"
  79.252 +       x="210.81311"
  79.253 +       y="212.26949"
  79.254 +       id="text2913"
  79.255 +       transform="scale(1.000002,0.999998)"><tspan
  79.256 +         sodipodi:role="line"
  79.257 +         id="tspan2915"
  79.258 +         x="210.81311"
  79.259 +         y="212.26949"
  79.260 +         style="font-family:Courier"><tspan
  79.261 +   id="tspan1966"
  79.262 +   style="font-weight:bold">6</tspan>: REV6_my_new_hello</tspan></text>
  79.263 +    <path
  79.264 +       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"
  79.265 +       d="M 191.06908,291.00504 L 227.93092,220.36218"
  79.266 +       id="path2919"
  79.267 +       inkscape:connector-type="polyline"
  79.268 +       inkscape:connection-start="#rect2830" />
  79.269 +    <text
  79.270 +       xml:space="preserve"
  79.271 +       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"
  79.272 +       x="295.28571"
  79.273 +       y="211.80988"
  79.274 +       id="text2871"><tspan
  79.275 +         sodipodi:role="line"
  79.276 +         id="tspan2873"
  79.277 +         x="295.28571"
  79.278 +         y="211.80988">tip (and head)</tspan></text>
  79.279 +    <text
  79.280 +       xml:space="preserve"
  79.281 +       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"
  79.282 +       x="76"
  79.283 +       y="259.16046"
  79.284 +       id="text2875"><tspan
  79.285 +         sodipodi:role="line"
  79.286 +         id="tspan2877"
  79.287 +         x="76"
  79.288 +         y="259.16046"
  79.289 +         style="text-align:end;text-anchor:end">head</tspan></text>
  79.290 +  </g>
  79.291 +</svg>
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/fr/tour-merge-sep-repos.svg	Thu Feb 05 12:37:03 2009 +0100
    80.3 @@ -0,0 +1,466 @@
    80.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    80.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    80.6 +<svg
    80.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    80.8 +   xmlns:cc="http://web.resource.org/cc/"
    80.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   80.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   80.11 +   xmlns="http://www.w3.org/2000/svg"
   80.12 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   80.13 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   80.14 +   width="744.09448819"
   80.15 +   height="1052.3622047"
   80.16 +   id="svg2"
   80.17 +   sodipodi:version="0.32"
   80.18 +   inkscape:version="0.44.1"
   80.19 +   sodipodi:docname="tour-merge-sep-repos.svg">
   80.20 +  <defs
   80.21 +     id="defs4">
   80.22 +    <marker
   80.23 +       inkscape:stockid="Arrow1Mstart"
   80.24 +       orient="auto"
   80.25 +       refY="0.0"
   80.26 +       refX="0.0"
   80.27 +       id="Arrow1Mstart"
   80.28 +       style="overflow:visible">
   80.29 +      <path
   80.30 +         id="path2973"
   80.31 +         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 "
   80.32 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   80.33 +         transform="scale(0.4) translate(10,0)" />
   80.34 +    </marker>
   80.35 +    <marker
   80.36 +       inkscape:stockid="Arrow1Mend"
   80.37 +       orient="auto"
   80.38 +       refY="0.0"
   80.39 +       refX="0.0"
   80.40 +       id="Arrow1Mend"
   80.41 +       style="overflow:visible;">
   80.42 +      <path
   80.43 +         id="path3066"
   80.44 +         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 "
   80.45 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   80.46 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   80.47 +    </marker>
   80.48 +  </defs>
   80.49 +  <sodipodi:namedview
   80.50 +     id="base"
   80.51 +     pagecolor="#ffffff"
   80.52 +     bordercolor="#666666"
   80.53 +     borderopacity="1.0"
   80.54 +     gridtolerance="10000"
   80.55 +     guidetolerance="10"
   80.56 +     objecttolerance="10"
   80.57 +     inkscape:pageopacity="0.0"
   80.58 +     inkscape:pageshadow="2"
   80.59 +     inkscape:zoom="1.4"
   80.60 +     inkscape:cx="307.20351"
   80.61 +     inkscape:cy="716.87911"
   80.62 +     inkscape:document-units="px"
   80.63 +     inkscape:current-layer="layer1"
   80.64 +     inkscape:window-width="906"
   80.65 +     inkscape:window-height="620"
   80.66 +     inkscape:window-x="5"
   80.67 +     inkscape:window-y="49" />
   80.68 +  <metadata
   80.69 +     id="metadata7">
   80.70 +    <rdf:RDF>
   80.71 +      <cc:Work
   80.72 +         rdf:about="">
   80.73 +        <dc:format>image/svg+xml</dc:format>
   80.74 +        <dc:type
   80.75 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
   80.76 +      </cc:Work>
   80.77 +    </rdf:RDF>
   80.78 +  </metadata>
   80.79 +  <g
   80.80 +     inkscape:label="Layer 1"
   80.81 +     inkscape:groupmode="layer"
   80.82 +     id="layer1">
   80.83 +    <text
   80.84 +       xml:space="preserve"
   80.85 +       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"
   80.86 +       x="173.57143"
   80.87 +       y="443.79074"
   80.88 +       id="text2832"><tspan
   80.89 +         sodipodi:role="line"
   80.90 +         id="tspan2834"
   80.91 +         x="173.57143"
   80.92 +         y="443.79074" /></text>
   80.93 +    <rect
   80.94 +       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"
   80.95 +       id="rect1878"
   80.96 +       width="94.285713"
   80.97 +       height="20.714285"
   80.98 +       x="138"
   80.99 +       y="479.50504" />
  80.100 +    <text
  80.101 +       xml:space="preserve"
  80.102 +       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"
  80.103 +       x="162.09892"
  80.104 +       y="493.12619"
  80.105 +       id="text1872"><tspan
  80.106 +         sodipodi:role="line"
  80.107 +         id="tspan1874"
  80.108 +         x="162.09892"
  80.109 +         y="493.12619"
  80.110 +         style="font-family:Courier"><tspan
  80.111 +   style="font-weight:bold"
  80.112 +   id="tspan1876">0</tspan>: REV0</tspan></text>
  80.113 +    <rect
  80.114 +       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"
  80.115 +       id="rect2800"
  80.116 +       width="94.285713"
  80.117 +       height="20.714285"
  80.118 +       x="138"
  80.119 +       y="432.63004" />
  80.120 +    <text
  80.121 +       xml:space="preserve"
  80.122 +       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"
  80.123 +       x="162.09892"
  80.124 +       y="446.25119"
  80.125 +       id="text2794"><tspan
  80.126 +         sodipodi:role="line"
  80.127 +         id="tspan2796"
  80.128 +         x="162.09892"
  80.129 +         y="446.25119"
  80.130 +         style="font-family:Courier"><tspan
  80.131 +   id="tspan2868"
  80.132 +   style="font-weight:bold">1</tspan>: REV1</tspan></text>
  80.133 +    <rect
  80.134 +       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"
  80.135 +       id="rect2810"
  80.136 +       width="94.285713"
  80.137 +       height="20.714285"
  80.138 +       x="138"
  80.139 +       y="385.75504" />
  80.140 +    <text
  80.141 +       xml:space="preserve"
  80.142 +       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"
  80.143 +       x="162.09892"
  80.144 +       y="399.37619"
  80.145 +       id="text2804"><tspan
  80.146 +         sodipodi:role="line"
  80.147 +         id="tspan2806"
  80.148 +         x="162.09892"
  80.149 +         y="399.37619"
  80.150 +         style="font-family:Courier"><tspan
  80.151 +   style="font-weight:bold"
  80.152 +   id="tspan2866">2</tspan>: REV2</tspan></text>
  80.153 +    <rect
  80.154 +       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"
  80.155 +       id="rect2820"
  80.156 +       width="94.285713"
  80.157 +       height="20.714285"
  80.158 +       x="138"
  80.159 +       y="338.88007" />
  80.160 +    <text
  80.161 +       xml:space="preserve"
  80.162 +       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"
  80.163 +       x="162.09892"
  80.164 +       y="352.50122"
  80.165 +       id="text2814"><tspan
  80.166 +         sodipodi:role="line"
  80.167 +         id="tspan2816"
  80.168 +         x="162.09892"
  80.169 +         y="352.50122"
  80.170 +         style="font-family:Courier"><tspan
  80.171 +   style="font-weight:bold"
  80.172 +   id="tspan2864">3</tspan>: REV3</tspan></text>
  80.173 +    <rect
  80.174 +       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"
  80.175 +       id="rect2830"
  80.176 +       width="94.285713"
  80.177 +       height="20.714285"
  80.178 +       x="138"
  80.179 +       y="292.00504" />
  80.180 +    <text
  80.181 +       xml:space="preserve"
  80.182 +       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"
  80.183 +       x="162.09892"
  80.184 +       y="305.62619"
  80.185 +       id="text2824"><tspan
  80.186 +         sodipodi:role="line"
  80.187 +         id="tspan2826"
  80.188 +         x="162.09892"
  80.189 +         y="305.62619"
  80.190 +         style="font-family:Courier"><tspan
  80.191 +   style="font-weight:bold"
  80.192 +   id="tspan2862">4</tspan>: REV4</tspan></text>
  80.193 +    <path
  80.194 +       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"
  80.195 +       d="M 185.14286,478.50504 L 185.14286,454.34432"
  80.196 +       id="path2894"
  80.197 +       inkscape:connector-type="polyline" />
  80.198 +    <path
  80.199 +       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"
  80.200 +       d="M 185.14286,431.63004 L 185.14286,407.46932"
  80.201 +       id="path2896"
  80.202 +       inkscape:connector-type="polyline" />
  80.203 +    <path
  80.204 +       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"
  80.205 +       d="M 185.14286,384.75504 L 185.14286,360.59435"
  80.206 +       id="path2898"
  80.207 +       inkscape:connector-type="polyline" />
  80.208 +    <path
  80.209 +       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"
  80.210 +       d="M 185.14286,337.88007 L 185.14286,313.71932"
  80.211 +       id="path2900"
  80.212 +       inkscape:connector-type="polyline" />
  80.213 +    <rect
  80.214 +       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"
  80.215 +       id="rect1963"
  80.216 +       width="94.285995"
  80.217 +       height="20.714283"
  80.218 +       x="138"
  80.219 +       y="245.18723" />
  80.220 +    <text
  80.221 +       xml:space="preserve"
  80.222 +       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"
  80.223 +       x="162.09877"
  80.224 +       y="258.80865"
  80.225 +       id="text1965"
  80.226 +       transform="scale(1.000002,0.999998)"><tspan
  80.227 +         sodipodi:role="line"
  80.228 +         id="tspan1967"
  80.229 +         x="162.09877"
  80.230 +         y="258.80865"
  80.231 +         style="font-family:Courier"><tspan
  80.232 +   style="font-weight:bold"
  80.233 +   id="tspan1973">5</tspan>: REV_my_hello</tspan></text>
  80.234 +    <path
  80.235 +       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"
  80.236 +       d="M 185.143,291.06218 L 185.143,266.90143"
  80.237 +       id="path1971"
  80.238 +       inkscape:connector-type="polyline" />
  80.239 +    <text
  80.240 +       xml:space="preserve"
  80.241 +       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"
  80.242 +       x="136.90039"
  80.243 +       y="232.25546"
  80.244 +       id="text2921"><tspan
  80.245 +         sodipodi:role="line"
  80.246 +         id="tspan2923"
  80.247 +         x="136.90039"
  80.248 +         y="232.25546">my-hello</tspan></text>
  80.249 +    <rect
  80.250 +       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"
  80.251 +       id="rect2863"
  80.252 +       width="94.285713"
  80.253 +       height="20.714285"
  80.254 +       x="370.71414"
  80.255 +       y="479.49289" />
  80.256 +    <text
  80.257 +       xml:space="preserve"
  80.258 +       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"
  80.259 +       x="394.81305"
  80.260 +       y="493.11404"
  80.261 +       id="text2865"><tspan
  80.262 +         sodipodi:role="line"
  80.263 +         id="tspan2867"
  80.264 +         x="394.81305"
  80.265 +         y="493.11404"
  80.266 +         style="font-family:Courier"><tspan
  80.267 +   style="font-weight:bold"
  80.268 +   id="tspan2869">0</tspan>: REV0</tspan></text>
  80.269 +    <rect
  80.270 +       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"
  80.271 +       id="rect2871"
  80.272 +       width="94.285713"
  80.273 +       height="20.714285"
  80.274 +       x="370.71414"
  80.275 +       y="432.61789" />
  80.276 +    <text
  80.277 +       xml:space="preserve"
  80.278 +       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"
  80.279 +       x="394.81305"
  80.280 +       y="446.23904"
  80.281 +       id="text2873"><tspan
  80.282 +         sodipodi:role="line"
  80.283 +         id="tspan2875"
  80.284 +         x="394.81305"
  80.285 +         y="446.23904"
  80.286 +         style="font-family:Courier"><tspan
  80.287 +   id="tspan2877"
  80.288 +   style="font-weight:bold">1</tspan>: REV1</tspan></text>
  80.289 +    <rect
  80.290 +       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"
  80.291 +       id="rect2879"
  80.292 +       width="94.285713"
  80.293 +       height="20.714285"
  80.294 +       x="370.71414"
  80.295 +       y="385.74289" />
  80.296 +    <text
  80.297 +       xml:space="preserve"
  80.298 +       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"
  80.299 +       x="394.81305"
  80.300 +       y="399.36404"
  80.301 +       id="text2881"><tspan
  80.302 +         sodipodi:role="line"
  80.303 +         id="tspan2883"
  80.304 +         x="394.81305"
  80.305 +         y="399.36404"
  80.306 +         style="font-family:Courier"><tspan
  80.307 +   style="font-weight:bold"
  80.308 +   id="tspan2885">2</tspan>: REV2</tspan></text>
  80.309 +    <rect
  80.310 +       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"
  80.311 +       id="rect2887"
  80.312 +       width="94.285713"
  80.313 +       height="20.714285"
  80.314 +       x="370.71414"
  80.315 +       y="338.86792" />
  80.316 +    <text
  80.317 +       xml:space="preserve"
  80.318 +       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"
  80.319 +       x="394.81305"
  80.320 +       y="352.48907"
  80.321 +       id="text2889"><tspan
  80.322 +         sodipodi:role="line"
  80.323 +         id="tspan2891"
  80.324 +         x="394.81305"
  80.325 +         y="352.48907"
  80.326 +         style="font-family:Courier"><tspan
  80.327 +   style="font-weight:bold"
  80.328 +   id="tspan2893">3</tspan>: REV3</tspan></text>
  80.329 +    <rect
  80.330 +       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"
  80.331 +       id="rect2895"
  80.332 +       width="94.285713"
  80.333 +       height="20.714285"
  80.334 +       x="370.71414"
  80.335 +       y="291.99289" />
  80.336 +    <text
  80.337 +       xml:space="preserve"
  80.338 +       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"
  80.339 +       x="394.81305"
  80.340 +       y="305.61404"
  80.341 +       id="text2897"><tspan
  80.342 +         sodipodi:role="line"
  80.343 +         id="tspan2899"
  80.344 +         x="394.81305"
  80.345 +         y="305.61404"
  80.346 +         style="font-family:Courier"><tspan
  80.347 +   style="font-weight:bold"
  80.348 +   id="tspan2901">4</tspan>: REV4</tspan></text>
  80.349 +    <path
  80.350 +       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"
  80.351 +       d="M 417.85701,478.4929 L 417.85701,454.33218"
  80.352 +       id="path2903"
  80.353 +       inkscape:connector-type="polyline" />
  80.354 +    <path
  80.355 +       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"
  80.356 +       d="M 417.85701,431.6179 L 417.85701,407.45718"
  80.357 +       id="path2905"
  80.358 +       inkscape:connector-type="polyline" />
  80.359 +    <path
  80.360 +       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"
  80.361 +       d="M 417.85701,384.7429 L 417.85701,360.58221"
  80.362 +       id="path2907"
  80.363 +       inkscape:connector-type="polyline" />
  80.364 +    <path
  80.365 +       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"
  80.366 +       d="M 417.85701,337.86793 L 417.85701,313.70718"
  80.367 +       id="path2909"
  80.368 +       inkscape:connector-type="polyline" />
  80.369 +    <rect
  80.370 +       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"
  80.371 +       id="rect2911"
  80.372 +       width="94.285995"
  80.373 +       height="20.714283"
  80.374 +       x="370.71414"
  80.375 +       y="245.17511" />
  80.376 +    <text
  80.377 +       xml:space="preserve"
  80.378 +       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"
  80.379 +       x="394.81274"
  80.380 +       y="258.79678"
  80.381 +       id="text2913"
  80.382 +       transform="scale(1.000002,0.999998)"><tspan
  80.383 +         sodipodi:role="line"
  80.384 +         id="tspan2915"
  80.385 +         x="394.81274"
  80.386 +         y="258.79678"
  80.387 +         style="font-family:Courier"><tspan
  80.388 +   style="font-weight:bold"
  80.389 +   id="tspan2917">5</tspan>: REV_my_new_hello</tspan></text>
  80.390 +    <path
  80.391 +       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"
  80.392 +       d="M 417.85715,291.05004 L 417.85715,266.88929"
  80.393 +       id="path2919"
  80.394 +       inkscape:connector-type="polyline" />
  80.395 +    <text
  80.396 +       xml:space="preserve"
  80.397 +       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"
  80.398 +       x="369.61453"
  80.399 +       y="232.25546"
  80.400 +       id="text2925"><tspan
  80.401 +         sodipodi:role="line"
  80.402 +         id="tspan2927"
  80.403 +         x="369.61453"
  80.404 +         y="232.25546">my-new-hello</tspan></text>
  80.405 +    <text
  80.406 +       xml:space="preserve"
  80.407 +       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"
  80.408 +       x="300.54352"
  80.409 +       y="252.12723"
  80.410 +       id="text2933"><tspan
  80.411 +         sodipodi:role="line"
  80.412 +         id="tspan2935"
  80.413 +         x="300.54352"
  80.414 +         y="252.12723"
  80.415 +         style="text-align:center;text-anchor:middle">newest changes</tspan><tspan
  80.416 +         sodipodi:role="line"
  80.417 +         x="300.54352"
  80.418 +         y="267.12723"
  80.419 +         style="text-align:center;text-anchor:middle"
  80.420 +         id="tspan3132">differ</tspan></text>
  80.421 +    <text
  80.422 +       xml:space="preserve"
  80.423 +       style="font-size:12px;font-style:normal;font-weight:normal;text-align:start;text-anchor:start;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Times New Roman"
  80.424 +       x="262.15436"
  80.425 +       y="398.37112"
  80.426 +       id="text2929"><tspan
  80.427 +         sodipodi:role="line"
  80.428 +         x="262.15436"
  80.429 +         y="398.37112"
  80.430 +         id="tspan3013"
  80.431 +         style="text-align:start;text-anchor:start">common history</tspan></text>
  80.432 +    <g
  80.433 +       id="g3107"
  80.434 +       transform="translate(0,0.855744)">
  80.435 +      <path
  80.436 +         id="path3101"
  80.437 +         d="M 300.35713,381.29075 L 300.35713,304.50504"
  80.438 +         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" />
  80.439 +      <path
  80.440 +         id="path3105"
  80.441 +         d="M 291.07142,301.64789 L 309.28571,301.64789"
  80.442 +         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" />
  80.443 +    </g>
  80.444 +    <path
  80.445 +       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"
  80.446 +       d="M 300.53571,486.38926 L 300.53571,409.60355"
  80.447 +       id="path3113" />
  80.448 +    <path
  80.449 +       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"
  80.450 +       d="M 291.25,488.49641 L 309.46429,488.49641"
  80.451 +       id="path3115" />
  80.452 +    <text
  80.453 +       xml:space="preserve"
  80.454 +       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"
  80.455 +       x="480.71429"
  80.456 +       y="250.91507"
  80.457 +       id="text1949"><tspan
  80.458 +         sodipodi:role="line"
  80.459 +         id="tspan1951"
  80.460 +         x="480.71429"
  80.461 +         y="250.91507"
  80.462 +         style="text-align:start;text-anchor:start">head revision</tspan><tspan
  80.463 +         sodipodi:role="line"
  80.464 +         x="480.71429"
  80.465 +         y="265.91507"
  80.466 +         id="tspan1953"
  80.467 +         style="text-align:start;text-anchor:start">(has no children)</tspan></text>
  80.468 +  </g>
  80.469 +</svg>
    81.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.2 +++ b/fr/tour-merge.tex	Thu Feb 05 12:37:03 2009 +0100
    81.3 @@ -0,0 +1,283 @@
    81.4 +\chapter{A tour of Mercurial: merging work}
    81.5 +\label{chap:tour-merge}
    81.6 +
    81.7 +We've now covered cloning a repository, making changes in a
    81.8 +repository, and pulling or pushing changes from one repository into
    81.9 +another.  Our next step is \emph{merging} changes from separate
   81.10 +repositories.
   81.11 +
   81.12 +\section{Merging streams of work}
   81.13 +
   81.14 +Merging is a fundamental part of working with a distributed revision
   81.15 +control tool.
   81.16 +\begin{itemize}
   81.17 +\item Alice and Bob each have a personal copy of a repository for a
   81.18 +  project they're collaborating on.  Alice fixes a bug in her
   81.19 +  repository; Bob adds a new feature in his.  They want the shared
   81.20 +  repository to contain both the bug fix and the new feature.
   81.21 +\item I frequently work on several different tasks for a single
   81.22 +  project at once, each safely isolated in its own repository.
   81.23 +  Working this way means that I often need to merge one piece of my
   81.24 +  own work with another.
   81.25 +\end{itemize}
   81.26 +
   81.27 +Because merging is such a common thing to need to do, Mercurial makes
   81.28 +it easy.  Let's walk through the process.  We'll begin by cloning yet
   81.29 +another repository (see how often they spring up?) and making a change
   81.30 +in it.
   81.31 +\interaction{tour.merge.clone}
   81.32 +We should now have two copies of \filename{hello.c} with different
   81.33 +contents.  The histories of the two repositories have also diverged,
   81.34 +as illustrated in figure~\ref{fig:tour-merge:sep-repos}.
   81.35 +\interaction{tour.merge.cat}
   81.36 +
   81.37 +\begin{figure}[ht]
   81.38 +  \centering
   81.39 +  \grafix{tour-merge-sep-repos}
   81.40 +  \caption{Divergent recent histories of the \dirname{my-hello} and
   81.41 +    \dirname{my-new-hello} repositories}
   81.42 +  \label{fig:tour-merge:sep-repos}
   81.43 +\end{figure}
   81.44 +
   81.45 +We already know that pulling changes from our \dirname{my-hello}
   81.46 +repository will have no effect on the working directory.
   81.47 +\interaction{tour.merge.pull}
   81.48 +However, the \hgcmd{pull} command says something about ``heads''.  
   81.49 +
   81.50 +\subsection{Head changesets}
   81.51 +
   81.52 +A head is a change that has no descendants, or children, as they're
   81.53 +also known.  The tip revision is thus a head, because the newest
   81.54 +revision in a repository doesn't have any children, but a repository
   81.55 +can contain more than one head.
   81.56 +
   81.57 +\begin{figure}[ht]
   81.58 +  \centering
   81.59 +  \grafix{tour-merge-pull}
   81.60 +  \caption{Repository contents after pulling from \dirname{my-hello} into
   81.61 +    \dirname{my-new-hello}}
   81.62 +  \label{fig:tour-merge:pull}
   81.63 +\end{figure}
   81.64 +
   81.65 +In figure~\ref{fig:tour-merge:pull}, you can see the effect of the
   81.66 +pull from \dirname{my-hello} into \dirname{my-new-hello}.  The history
   81.67 +that was already present in \dirname{my-new-hello} is untouched, but a
   81.68 +new revision has been added.  By referring to
   81.69 +figure~\ref{fig:tour-merge:sep-repos}, we can see that the
   81.70 +\emph{changeset ID} remains the same in the new repository, but the
   81.71 +\emph{revision number} has changed.  (This, incidentally, is a fine
   81.72 +example of why it's not safe to use revision numbers when discussing
   81.73 +changesets.)  We can view the heads in a repository using the
   81.74 +\hgcmd{heads} command.
   81.75 +\interaction{tour.merge.heads}
   81.76 +
   81.77 +\subsection{Performing the merge}
   81.78 +
   81.79 +What happens if we try to use the normal \hgcmd{update} command to
   81.80 +update to the new tip?
   81.81 +\interaction{tour.merge.update}
   81.82 +Mercurial is telling us that the \hgcmd{update} command won't do a
   81.83 +merge; it won't update the working directory when it thinks we might
   81.84 +be wanting to do a merge, unless we force it to do so.  Instead, we
   81.85 +use the \hgcmd{merge} command to merge the two heads.
   81.86 +\interaction{tour.merge.merge}
   81.87 +
   81.88 +\begin{figure}[ht]
   81.89 +  \centering
   81.90 +  \grafix{tour-merge-merge}
   81.91 +  \caption{Working directory and repository during merge, and
   81.92 +    following commit}
   81.93 +  \label{fig:tour-merge:merge}
   81.94 +\end{figure}
   81.95 +
   81.96 +This updates the working directory so that it contains changes from
   81.97 +\emph{both} heads, which is reflected in both the output of
   81.98 +\hgcmd{parents} and the contents of \filename{hello.c}.
   81.99 +\interaction{tour.merge.parents}
  81.100 +
  81.101 +\subsection{Committing the results of the merge}
  81.102 +
  81.103 +Whenever we've done a merge, \hgcmd{parents} will display two parents
  81.104 +until we \hgcmd{commit} the results of the merge.
  81.105 +\interaction{tour.merge.commit}
  81.106 +We now have a new tip revision; notice that it has \emph{both} of
  81.107 +our former heads as its parents.  These are the same revisions that
  81.108 +were previously displayed by \hgcmd{parents}.
  81.109 +\interaction{tour.merge.tip}
  81.110 +In figure~\ref{fig:tour-merge:merge}, you can see a representation of
  81.111 +what happens to the working directory during the merge, and how this
  81.112 +affects the repository when the commit happens.  During the merge, the
  81.113 +working directory has two parent changesets, and these become the
  81.114 +parents of the new changeset.
  81.115 +
  81.116 +\section{Merging conflicting changes}
  81.117 +
  81.118 +Most merges are simple affairs, but sometimes you'll find yourself
  81.119 +merging changes where each modifies the same portions of the same
  81.120 +files.  Unless both modifications are identical, this results in a
  81.121 +\emph{conflict}, where you have to decide how to reconcile the
  81.122 +different changes into something coherent.
  81.123 +
  81.124 +\begin{figure}[ht]
  81.125 +  \centering
  81.126 +  \grafix{tour-merge-conflict}
  81.127 +  \caption{Conflicting changes to a document}
  81.128 +  \label{fig:tour-merge:conflict}
  81.129 +\end{figure}
  81.130 +
  81.131 +Figure~\ref{fig:tour-merge:conflict} illustrates an instance of two
  81.132 +conflicting changes to a document.  We started with a single version
  81.133 +of the file; then we made some changes; while someone else made
  81.134 +different changes to the same text.  Our task in resolving the
  81.135 +conflicting changes is to decide what the file should look like.
  81.136 +
  81.137 +Mercurial doesn't have a built-in facility for handling conflicts.
  81.138 +Instead, it runs an external program called \command{hgmerge}.  This
  81.139 +is a shell script that is bundled with Mercurial; you can change it to
  81.140 +behave however you please.  What it does by default is try to find one
  81.141 +of several different merging tools that are likely to be installed on
  81.142 +your system.  It first tries a few fully automatic merging tools; if
  81.143 +these don't succeed (because the resolution process requires human
  81.144 +guidance) or aren't present, the script tries a few different
  81.145 +graphical merging tools.
  81.146 +
  81.147 +It's also possible to get Mercurial to run another program or script
  81.148 +instead of \command{hgmerge}, by setting the \envar{HGMERGE}
  81.149 +environment variable to the name of your preferred program.
  81.150 +
  81.151 +\subsection{Using a graphical merge tool}
  81.152 +
  81.153 +My preferred graphical merge tool is \command{kdiff3}, which I'll use
  81.154 +to describe the features that are common to graphical file merging
  81.155 +tools.  You can see a screenshot of \command{kdiff3} in action in
  81.156 +figure~\ref{fig:tour-merge:kdiff3}.  The kind of merge it is
  81.157 +performing is called a \emph{three-way merge}, because there are three
  81.158 +different versions of the file of interest to us.  The tool thus
  81.159 +splits the upper portion of the window into three panes:
  81.160 +\begin{itemize}
  81.161 +\item At the left is the \emph{base} version of the file, i.e.~the
  81.162 +  most recent version from which the two versions we're trying to
  81.163 +  merge are descended.
  81.164 +\item In the middle is ``our'' version of the file, with the contents
  81.165 +  that we modified.
  81.166 +\item On the right is ``their'' version of the file, the one that
  81.167 +  from the changeset that we're trying to merge with.
  81.168 +\end{itemize}
  81.169 +In the pane below these is the current \emph{result} of the merge.
  81.170 +Our task is to replace all of the red text, which indicates unresolved
  81.171 +conflicts, with some sensible merger of the ``ours'' and ``theirs''
  81.172 +versions of the file.
  81.173 +
  81.174 +All four of these panes are \emph{locked together}; if we scroll
  81.175 +vertically or horizontally in any of them, the others are updated to
  81.176 +display the corresponding sections of their respective files.
  81.177 +
  81.178 +\begin{figure}[ht]
  81.179 +  \centering
  81.180 +  \grafix{kdiff3}
  81.181 +  \caption{Using \command{kdiff3} to merge versions of a file}
  81.182 +  \label{fig:tour-merge:kdiff3}
  81.183 +\end{figure}
  81.184 +
  81.185 +For each conflicting portion of the file, we can choose to resolve
  81.186 +the conflict using some combination of text from the base version,
  81.187 +ours, or theirs.  We can also manually edit the merged file at any
  81.188 +time, in case we need to make further modifications.
  81.189 +
  81.190 +There are \emph{many} file merging tools available, too many to cover
  81.191 +here.  They vary in which platforms they are available for, and in
  81.192 +their particular strengths and weaknesses.  Most are tuned for merging
  81.193 +files containing plain text, while a few are aimed at specialised file
  81.194 +formats (generally XML).
  81.195 +
  81.196 +\subsection{A worked example}
  81.197 +
  81.198 +In this example, we will reproduce the file modification history of
  81.199 +figure~\ref{fig:tour-merge:conflict} above.  Let's begin by creating a
  81.200 +repository with a base version of our document.
  81.201 +\interaction{tour-merge-conflict.wife}
  81.202 +We'll clone the repository and make a change to the file.
  81.203 +\interaction{tour-merge-conflict.cousin}
  81.204 +And another clone, to simulate someone else making a change to the
  81.205 +file.  (This hints at the idea that it's not all that unusual to merge
  81.206 +with yourself when you isolate tasks in separate repositories, and
  81.207 +indeed to find and resolve conflicts while doing so.)
  81.208 +\interaction{tour-merge-conflict.son}
  81.209 +Having created two different versions of the file, we'll set up an
  81.210 +environment suitable for running our merge.
  81.211 +\interaction{tour-merge-conflict.pull}
  81.212 +
  81.213 +In this example, I won't use Mercurial's normal \command{hgmerge}
  81.214 +program to do the merge, because it would drop my nice automated
  81.215 +example-running tool into a graphical user interface.  Instead, I'll
  81.216 +set \envar{HGMERGE} to tell Mercurial to use the non-interactive
  81.217 +\command{merge} command.  This is bundled with many Unix-like systems.
  81.218 +If you're following this example on your computer, don't bother
  81.219 +setting \envar{HGMERGE}.
  81.220 +\interaction{tour-merge-conflict.merge}
  81.221 +Because \command{merge} can't resolve the conflicting changes, it
  81.222 +leaves \emph{merge markers} inside the file that has conflicts,
  81.223 +indicating which lines have conflicts, and whether they came from our
  81.224 +version of the file or theirs.
  81.225 +
  81.226 +Mercurial can tell from the way \command{merge} exits that it wasn't
  81.227 +able to merge successfully, so it tells us what commands we'll need to
  81.228 +run if we want to redo the merging operation.  This could be useful
  81.229 +if, for example, we were running a graphical merge tool and quit
  81.230 +because we were confused or realised we had made a mistake.
  81.231 +
  81.232 +If automatic or manual merges fail, there's nothing to prevent us from
  81.233 +``fixing up'' the affected files ourselves, and committing the results
  81.234 +of our merge:
  81.235 +\interaction{tour-merge-conflict.commit}
  81.236 +
  81.237 +\section{Simplifying the pull-merge-commit sequence}
  81.238 +\label{sec:tour-merge:fetch}
  81.239 +
  81.240 +The process of merging changes as outlined above is straightforward,
  81.241 +but requires running three commands in sequence.
  81.242 +\begin{codesample2}
  81.243 +  hg pull
  81.244 +  hg merge
  81.245 +  hg commit -m 'Merged remote changes'
  81.246 +\end{codesample2}
  81.247 +In the case of the final commit, you also need to enter a commit
  81.248 +message, which is almost always going to be a piece of uninteresting
  81.249 +``boilerplate'' text.
  81.250 +
  81.251 +It would be nice to reduce the number of steps needed, if this were
  81.252 +possible.  Indeed, Mercurial is distributed with an extension called
  81.253 +\hgext{fetch} that does just this.
  81.254 +
  81.255 +Mercurial provides a flexible extension mechanism that lets people
  81.256 +extend its functionality, while keeping the core of Mercurial small
  81.257 +and easy to deal with.  Some extensions add new commands that you can
  81.258 +use from the command line, while others work ``behind the scenes,''
  81.259 +for example adding capabilities to the server.
  81.260 +
  81.261 +The \hgext{fetch} extension adds a new command called, not
  81.262 +surprisingly, \hgcmd{fetch}.  This extension acts as a combination of
  81.263 +\hgcmd{pull}, \hgcmd{update} and \hgcmd{merge}.  It begins by pulling
  81.264 +changes from another repository into the current repository.  If it
  81.265 +finds that the changes added a new head to the repository, it begins a
  81.266 +merge, then commits the result of the merge with an
  81.267 +automatically-generated commit message.  If no new heads were added,
  81.268 +it updates the working directory to the new tip changeset.
  81.269 +
  81.270 +Enabling the \hgext{fetch} extension is easy.  Edit your
  81.271 +\sfilename{.hgrc}, and either go to the \rcsection{extensions} section
  81.272 +or create an \rcsection{extensions} section.  Then add a line that
  81.273 +simply reads ``\Verb+fetch +''.
  81.274 +\begin{codesample2}
  81.275 +  [extensions]
  81.276 +  fetch =
  81.277 +\end{codesample2}
  81.278 +(Normally, on the right-hand side of the ``\texttt{=}'' would appear
  81.279 +the location of the extension, but since the \hgext{fetch} extension
  81.280 +is in the standard distribution, Mercurial knows where to search for
  81.281 +it.)
  81.282 +
  81.283 +%%% Local Variables: 
  81.284 +%%% mode: latex
  81.285 +%%% TeX-master: "00book"
  81.286 +%%% End: 
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/fr/undo-manual-merge.dot	Thu Feb 05 12:37:03 2009 +0100
    82.3 @@ -0,0 +1,8 @@
    82.4 +digraph undo_manual {
    82.5 +	"first change" -> "second change";
    82.6 +	"second change" -> "third change";
    82.7 +	backout [label="back out\nsecond change", shape=box];
    82.8 +	"second change" -> backout;
    82.9 +	"third change" -> "manual\nmerge";
   82.10 +	backout -> "manual\nmerge";
   82.11 +}
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/fr/undo-manual.dot	Thu Feb 05 12:37:03 2009 +0100
    83.3 @@ -0,0 +1,6 @@
    83.4 +digraph undo_manual {
    83.5 +	"first change" -> "second change";
    83.6 +	"second change" -> "third change";
    83.7 +	backout [label="back out\nsecond change", shape=box];
    83.8 +	"second change" -> backout;
    83.9 +}
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/fr/undo-non-tip.dot	Thu Feb 05 12:37:03 2009 +0100
    84.3 @@ -0,0 +1,9 @@
    84.4 +digraph undo_non_tip {
    84.5 +	"first change" -> "second change";
    84.6 +	"second change" -> "third change";
    84.7 +	backout [label="back out\nsecond change", shape=box];
    84.8 +	"second change" -> backout;
    84.9 +	merge [label="automated\nmerge", shape=box];
   84.10 +	"third change" -> merge;
   84.11 +	backout -> merge;
   84.12 +}
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/fr/undo-simple.dot	Thu Feb 05 12:37:03 2009 +0100
    85.3 @@ -0,0 +1,4 @@
    85.4 +digraph undo_simple {
    85.5 +	"first change" -> "second change";
    85.6 +	"second change" -> "back out\nsecond change";
    85.7 +}
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/fr/undo.tex	Thu Feb 05 12:37:03 2009 +0100
    86.3 @@ -0,0 +1,767 @@
    86.4 +\chapter{Finding and fixing your mistakes}
    86.5 +\label{chap:undo}
    86.6 +
    86.7 +To err might be human, but to really handle the consequences well
    86.8 +takes a top-notch revision control system.  In this chapter, we'll
    86.9 +discuss some of the techniques you can use when you find that a
   86.10 +problem has crept into your project.  Mercurial has some highly
   86.11 +capable features that will help you to isolate the sources of
   86.12 +problems, and to handle them appropriately.
   86.13 +
   86.14 +\section{Erasing local history}
   86.15 +
   86.16 +\subsection{The accidental commit}
   86.17 +
   86.18 +I have the occasional but persistent problem of typing rather more
   86.19 +quickly than I can think, which sometimes results in me committing a
   86.20 +changeset that is either incomplete or plain wrong.  In my case, the
   86.21 +usual kind of incomplete changeset is one in which I've created a new
   86.22 +source file, but forgotten to \hgcmd{add} it.  A ``plain wrong''
   86.23 +changeset is not as common, but no less annoying.
   86.24 +
   86.25 +\subsection{Rolling back a transaction}
   86.26 +\label{sec:undo:rollback}
   86.27 +
   86.28 +In section~\ref{sec:concepts:txn}, I mentioned that Mercurial treats
   86.29 +each modification of a repository as a \emph{transaction}.  Every time
   86.30 +you commit a changeset or pull changes from another repository,
   86.31 +Mercurial remembers what you did.  You can undo, or \emph{roll back},
   86.32 +exactly one of these actions using the \hgcmd{rollback} command.  (See
   86.33 +section~\ref{sec:undo:rollback-after-push} for an important caveat
   86.34 +about the use of this command.)
   86.35 +
   86.36 +Here's a mistake that I often find myself making: committing a change
   86.37 +in which I've created a new file, but forgotten to \hgcmd{add} it.
   86.38 +\interaction{rollback.commit}
   86.39 +Looking at the output of \hgcmd{status} after the commit immediately
   86.40 +confirms the error.
   86.41 +\interaction{rollback.status}
   86.42 +The commit captured the changes to the file \filename{a}, but not the
   86.43 +new file \filename{b}.  If I were to push this changeset to a
   86.44 +repository that I shared with a colleague, the chances are high that
   86.45 +something in \filename{a} would refer to \filename{b}, which would not
   86.46 +be present in their repository when they pulled my changes.  I would
   86.47 +thus become the object of some indignation.
   86.48 +
   86.49 +However, luck is with me---I've caught my error before I pushed the
   86.50 +changeset.  I use the \hgcmd{rollback} command, and Mercurial makes
   86.51 +that last changeset vanish.
   86.52 +\interaction{rollback.rollback}
   86.53 +Notice that the changeset is no longer present in the repository's
   86.54 +history, and the working directory once again thinks that the file
   86.55 +\filename{a} is modified.  The commit and rollback have left the
   86.56 +working directory exactly as it was prior to the commit; the changeset
   86.57 +has been completely erased.  I can now safely \hgcmd{add} the file
   86.58 +\filename{b}, and rerun my commit.
   86.59 +\interaction{rollback.add}
   86.60 +
   86.61 +\subsection{The erroneous pull}
   86.62 +
   86.63 +It's common practice with Mercurial to maintain separate development
   86.64 +branches of a project in different repositories.  Your development
   86.65 +team might have one shared repository for your project's ``0.9''
   86.66 +release, and another, containing different changes, for the ``1.0''
   86.67 +release.
   86.68 +
   86.69 +Given this, you can imagine that the consequences could be messy if
   86.70 +you had a local ``0.9'' repository, and accidentally pulled changes
   86.71 +from the shared ``1.0'' repository into it.  At worst, you could be
   86.72 +paying insufficient attention, and push those changes into the shared
   86.73 +``0.9'' tree, confusing your entire team (but don't worry, we'll
   86.74 +return to this horror scenario later).  However, it's more likely that
   86.75 +you'll notice immediately, because Mercurial will display the URL it's
   86.76 +pulling from, or you will see it pull a suspiciously large number of
   86.77 +changes into the repository.
   86.78 +
   86.79 +The \hgcmd{rollback} command will work nicely to expunge all of the
   86.80 +changesets that you just pulled.  Mercurial groups all changes from
   86.81 +one \hgcmd{pull} into a single transaction, so one \hgcmd{rollback} is
   86.82 +all you need to undo this mistake.
   86.83 +
   86.84 +\subsection{Rolling back is useless once you've pushed}
   86.85 +\label{sec:undo:rollback-after-push}
   86.86 +
   86.87 +The value of the \hgcmd{rollback} command drops to zero once you've
   86.88 +pushed your changes to another repository.  Rolling back a change
   86.89 +makes it disappear entirely, but \emph{only} in the repository in
   86.90 +which you perform the \hgcmd{rollback}.  Because a rollback eliminates
   86.91 +history, there's no way for the disappearance of a change to propagate
   86.92 +between repositories.
   86.93 +
   86.94 +If you've pushed a change to another repository---particularly if it's
   86.95 +a shared repository---it has essentially ``escaped into the wild,''
   86.96 +and you'll have to recover from your mistake in a different way.  What
   86.97 +will happen if you push a changeset somewhere, then roll it back, then
   86.98 +pull from the repository you pushed to, is that the changeset will
   86.99 +reappear in your repository.
  86.100 +
  86.101 +(If you absolutely know for sure that the change you want to roll back
  86.102 +is the most recent change in the repository that you pushed to,
  86.103 +\emph{and} you know that nobody else could have pulled it from that
  86.104 +repository, you can roll back the changeset there, too, but you really
  86.105 +should really not rely on this working reliably.  If you do this,
  86.106 +sooner or later a change really will make it into a repository that
  86.107 +you don't directly control (or have forgotten about), and come back to
  86.108 +bite you.)
  86.109 +
  86.110 +\subsection{You can only roll back once}
  86.111 +
  86.112 +Mercurial stores exactly one transaction in its transaction log; that
  86.113 +transaction is the most recent one that occurred in the repository.
  86.114 +This means that you can only roll back one transaction.  If you expect
  86.115 +to be able to roll back one transaction, then its predecessor, this is
  86.116 +not the behaviour you will get.
  86.117 +\interaction{rollback.twice}
  86.118 +Once you've rolled back one transaction in a repository, you can't
  86.119 +roll back again in that repository until you perform another commit or
  86.120 +pull.
  86.121 +
  86.122 +\section{Reverting the mistaken change}
  86.123 +
  86.124 +If you make a modification to a file, and decide that you really
  86.125 +didn't want to change the file at all, and you haven't yet committed
  86.126 +your changes, the \hgcmd{revert} command is the one you'll need.  It
  86.127 +looks at the changeset that's the parent of the working directory, and
  86.128 +restores the contents of the file to their state as of that changeset.
  86.129 +(That's a long-winded way of saying that, in the normal case, it
  86.130 +undoes your modifications.)
  86.131 +
  86.132 +Let's illustrate how the \hgcmd{revert} command works with yet another
  86.133 +small example.  We'll begin by modifying a file that Mercurial is
  86.134 +already tracking.
  86.135 +\interaction{daily.revert.modify}
  86.136 +If we don't want that change, we can simply \hgcmd{revert} the file.
  86.137 +\interaction{daily.revert.unmodify}
  86.138 +The \hgcmd{revert} command provides us with an extra degree of safety
  86.139 +by saving our modified file with a \filename{.orig} extension.
  86.140 +\interaction{daily.revert.status}
  86.141 +
  86.142 +Here is a summary of the cases that the \hgcmd{revert} command can
  86.143 +deal with.  We will describe each of these in more detail in the
  86.144 +section that follows.
  86.145 +\begin{itemize}
  86.146 +\item If you modify a file, it will restore the file to its unmodified
  86.147 +  state.
  86.148 +\item If you \hgcmd{add} a file, it will undo the ``added'' state of
  86.149 +  the file, but leave the file itself untouched.
  86.150 +\item If you delete a file without telling Mercurial, it will restore
  86.151 +  the file to its unmodified contents.
  86.152 +\item If you use the \hgcmd{remove} command to remove a file, it will
  86.153 +  undo the ``removed'' state of the file, and restore the file to its
  86.154 +  unmodified contents.
  86.155 +\end{itemize}
  86.156 +
  86.157 +\subsection{File management errors}
  86.158 +\label{sec:undo:mgmt}
  86.159 +
  86.160 +The \hgcmd{revert} command is useful for more than just modified
  86.161 +files.  It lets you reverse the results of all of Mercurial's file
  86.162 +management commands---\hgcmd{add}, \hgcmd{remove}, and so on.
  86.163 +
  86.164 +If you \hgcmd{add} a file, then decide that in fact you don't want
  86.165 +Mercurial to track it, use \hgcmd{revert} to undo the add.  Don't
  86.166 +worry; Mercurial will not modify the file in any way.  It will just
  86.167 +``unmark'' the file.
  86.168 +\interaction{daily.revert.add}
  86.169 +
  86.170 +Similarly, if you ask Mercurial to \hgcmd{remove} a file, you can use
  86.171 +\hgcmd{revert} to restore it to the contents it had as of the parent
  86.172 +of the working directory.
  86.173 +\interaction{daily.revert.remove}
  86.174 +This works just as well for a file that you deleted by hand, without
  86.175 +telling Mercurial (recall that in Mercurial terminology, this kind of
  86.176 +file is called ``missing'').
  86.177 +\interaction{daily.revert.missing}
  86.178 +
  86.179 +If you revert a \hgcmd{copy}, the copied-to file remains in your
  86.180 +working directory afterwards, untracked.  Since a copy doesn't affect
  86.181 +the copied-from file in any way, Mercurial doesn't do anything with
  86.182 +the copied-from file.
  86.183 +\interaction{daily.revert.copy}
  86.184 +
  86.185 +\subsubsection{A slightly special case: reverting a rename}
  86.186 +
  86.187 +If you \hgcmd{rename} a file, there is one small detail that
  86.188 +you should remember.  When you \hgcmd{revert} a rename, it's not
  86.189 +enough to provide the name of the renamed-to file, as you can see
  86.190 +here.
  86.191 +\interaction{daily.revert.rename}
  86.192 +As you can see from the output of \hgcmd{status}, the renamed-to file
  86.193 +is no longer identified as added, but the renamed-\emph{from} file is
  86.194 +still removed!  This is counter-intuitive (at least to me), but at
  86.195 +least it's easy to deal with.
  86.196 +\interaction{daily.revert.rename-orig}
  86.197 +So remember, to revert a \hgcmd{rename}, you must provide \emph{both}
  86.198 +the source and destination names.  
  86.199 +
  86.200 +% TODO: the output doesn't look like it will be removed!
  86.201 +
  86.202 +(By the way, if you rename a file, then modify the renamed-to file,
  86.203 +then revert both components of the rename, when Mercurial restores the
  86.204 +file that was removed as part of the rename, it will be unmodified.
  86.205 +If you need the modifications in the renamed-to file to show up in the
  86.206 +renamed-from file, don't forget to copy them over.)
  86.207 +
  86.208 +These fiddly aspects of reverting a rename arguably constitute a small
  86.209 +bug in Mercurial.
  86.210 +
  86.211 +\section{Dealing with committed changes}
  86.212 +
  86.213 +Consider a case where you have committed a change $a$, and another
  86.214 +change $b$ on top of it; you then realise that change $a$ was
  86.215 +incorrect.  Mercurial lets you ``back out'' an entire changeset
  86.216 +automatically, and building blocks that let you reverse part of a
  86.217 +changeset by hand.
  86.218 +
  86.219 +Before you read this section, here's something to keep in mind: the
  86.220 +\hgcmd{backout} command undoes changes by \emph{adding} history, not
  86.221 +by modifying or erasing it.  It's the right tool to use if you're
  86.222 +fixing bugs, but not if you're trying to undo some change that has
  86.223 +catastrophic consequences.  To deal with those, see
  86.224 +section~\ref{sec:undo:aaaiiieee}.
  86.225 +
  86.226 +\subsection{Backing out a changeset}
  86.227 +
  86.228 +The \hgcmd{backout} command lets you ``undo'' the effects of an entire
  86.229 +changeset in an automated fashion.  Because Mercurial's history is
  86.230 +immutable, this command \emph{does not} get rid of the changeset you
  86.231 +want to undo.  Instead, it creates a new changeset that
  86.232 +\emph{reverses} the effect of the to-be-undone changeset.
  86.233 +
  86.234 +The operation of the \hgcmd{backout} command is a little intricate, so
  86.235 +let's illustrate it with some examples.  First, we'll create a
  86.236 +repository with some simple changes.
  86.237 +\interaction{backout.init}
  86.238 +
  86.239 +The \hgcmd{backout} command takes a single changeset ID as its
  86.240 +argument; this is the changeset to back out.  Normally,
  86.241 +\hgcmd{backout} will drop you into a text editor to write a commit
  86.242 +message, so you can record why you're backing the change out.  In this
  86.243 +example, we provide a commit message on the command line using the
  86.244 +\hgopt{backout}{-m} option.
  86.245 +
  86.246 +\subsection{Backing out the tip changeset}
  86.247 +
  86.248 +We're going to start by backing out the last changeset we committed.
  86.249 +\interaction{backout.simple}
  86.250 +You can see that the second line from \filename{myfile} is no longer
  86.251 +present.  Taking a look at the output of \hgcmd{log} gives us an idea
  86.252 +of what the \hgcmd{backout} command has done.
  86.253 +\interaction{backout.simple.log}
  86.254 +Notice that the new changeset that \hgcmd{backout} has created is a
  86.255 +child of the changeset we backed out.  It's easier to see this in
  86.256 +figure~\ref{fig:undo:backout}, which presents a graphical view of the
  86.257 +change history.  As you can see, the history is nice and linear.
  86.258 +
  86.259 +\begin{figure}[htb]
  86.260 +  \centering
  86.261 +  \grafix{undo-simple}
  86.262 +  \caption{Backing out a change using the \hgcmd{backout} command}
  86.263 +  \label{fig:undo:backout}
  86.264 +\end{figure}
  86.265 +
  86.266 +\subsection{Backing out a non-tip change}
  86.267 +
  86.268 +If you want to back out a change other than the last one you
  86.269 +committed, pass the \hgopt{backout}{--merge} option to the
  86.270 +\hgcmd{backout} command.
  86.271 +\interaction{backout.non-tip.clone}
  86.272 +This makes backing out any changeset a ``one-shot'' operation that's
  86.273 +usually simple and fast.
  86.274 +\interaction{backout.non-tip.backout}
  86.275 +
  86.276 +If you take a look at the contents of \filename{myfile} after the
  86.277 +backout finishes, you'll see that the first and third changes are
  86.278 +present, but not the second.
  86.279 +\interaction{backout.non-tip.cat}
  86.280 +
  86.281 +As the graphical history in figure~\ref{fig:undo:backout-non-tip}
  86.282 +illustrates, Mercurial actually commits \emph{two} changes in this
  86.283 +kind of situation (the box-shaped nodes are the ones that Mercurial
  86.284 +commits automatically).  Before Mercurial begins the backout process,
  86.285 +it first remembers what the current parent of the working directory
  86.286 +is.  It then backs out the target changeset, and commits that as a
  86.287 +changeset.  Finally, it merges back to the previous parent of the
  86.288 +working directory, and commits the result of the merge.
  86.289 +
  86.290 +% TODO: to me it looks like mercurial doesn't commit the second merge automatically!
  86.291 +
  86.292 +\begin{figure}[htb]
  86.293 +  \centering
  86.294 +  \grafix{undo-non-tip}
  86.295 +  \caption{Automated backout of a non-tip change using the \hgcmd{backout} command}
  86.296 +  \label{fig:undo:backout-non-tip}
  86.297 +\end{figure}
  86.298 +
  86.299 +The result is that you end up ``back where you were'', only with some
  86.300 +extra history that undoes the effect of the changeset you wanted to
  86.301 +back out.
  86.302 +
  86.303 +\subsubsection{Always use the \hgopt{backout}{--merge} option}
  86.304 +
  86.305 +In fact, since the \hgopt{backout}{--merge} option will do the ``right
  86.306 +thing'' whether or not the changeset you're backing out is the tip
  86.307 +(i.e.~it won't try to merge if it's backing out the tip, since there's
  86.308 +no need), you should \emph{always} use this option when you run the
  86.309 +\hgcmd{backout} command.
  86.310 +
  86.311 +\subsection{Gaining more control of the backout process}
  86.312 +
  86.313 +While I've recommended that you always use the
  86.314 +\hgopt{backout}{--merge} option when backing out a change, the
  86.315 +\hgcmd{backout} command lets you decide how to merge a backout
  86.316 +changeset.  Taking control of the backout process by hand is something
  86.317 +you will rarely need to do, but it can be useful to understand what
  86.318 +the \hgcmd{backout} command is doing for you automatically.  To
  86.319 +illustrate this, let's clone our first repository, but omit the
  86.320 +backout change that it contains.
  86.321 +
  86.322 +\interaction{backout.manual.clone}
  86.323 +As with our earlier example, We'll commit a third changeset, then back
  86.324 +out its parent, and see what happens.
  86.325 +\interaction{backout.manual.backout} 
  86.326 +Our new changeset is again a descendant of the changeset we backout
  86.327 +out; it's thus a new head, \emph{not} a descendant of the changeset
  86.328 +that was the tip.  The \hgcmd{backout} command was quite explicit in
  86.329 +telling us this.
  86.330 +\interaction{backout.manual.log}
  86.331 +
  86.332 +Again, it's easier to see what has happened by looking at a graph of
  86.333 +the revision history, in figure~\ref{fig:undo:backout-manual}.  This
  86.334 +makes it clear that when we use \hgcmd{backout} to back out a change
  86.335 +other than the tip, Mercurial adds a new head to the repository (the
  86.336 +change it committed is box-shaped).
  86.337 +
  86.338 +\begin{figure}[htb]
  86.339 +  \centering
  86.340 +  \grafix{undo-manual}
  86.341 +  \caption{Backing out a change using the \hgcmd{backout} command}
  86.342 +  \label{fig:undo:backout-manual}
  86.343 +\end{figure}
  86.344 +
  86.345 +After the \hgcmd{backout} command has completed, it leaves the new
  86.346 +``backout'' changeset as the parent of the working directory.
  86.347 +\interaction{backout.manual.parents}
  86.348 +Now we have two isolated sets of changes.
  86.349 +\interaction{backout.manual.heads}
  86.350 +
  86.351 +Let's think about what we expect to see as the contents of
  86.352 +\filename{myfile} now.  The first change should be present, because
  86.353 +we've never backed it out.  The second change should be missing, as
  86.354 +that's the change we backed out.  Since the history graph shows the
  86.355 +third change as a separate head, we \emph{don't} expect to see the
  86.356 +third change present in \filename{myfile}.
  86.357 +\interaction{backout.manual.cat}
  86.358 +To get the third change back into the file, we just do a normal merge
  86.359 +of our two heads.
  86.360 +\interaction{backout.manual.merge}
  86.361 +Afterwards, the graphical history of our repository looks like
  86.362 +figure~\ref{fig:undo:backout-manual-merge}.
  86.363 +
  86.364 +\begin{figure}[htb]
  86.365 +  \centering
  86.366 +  \grafix{undo-manual-merge}
  86.367 +  \caption{Manually merging a backout change}
  86.368 +  \label{fig:undo:backout-manual-merge}
  86.369 +\end{figure}
  86.370 +
  86.371 +\subsection{Why \hgcmd{backout} works as it does}
  86.372 +
  86.373 +Here's a brief description of how the \hgcmd{backout} command works.
  86.374 +\begin{enumerate}
  86.375 +\item It ensures that the working directory is ``clean'', i.e.~that
  86.376 +  the output of \hgcmd{status} would be empty.
  86.377 +\item It remembers the current parent of the working directory.  Let's
  86.378 +  call this changeset \texttt{orig}
  86.379 +\item It does the equivalent of a \hgcmd{update} to sync the working
  86.380 +  directory to the changeset you want to back out.  Let's call this
  86.381 +  changeset \texttt{backout}
  86.382 +\item It finds the parent of that changeset.  Let's call that
  86.383 +  changeset \texttt{parent}.
  86.384 +\item For each file that the \texttt{backout} changeset affected, it
  86.385 +  does the equivalent of a \hgcmdargs{revert}{-r parent} on that file,
  86.386 +  to restore it to the contents it had before that changeset was
  86.387 +  committed.
  86.388 +\item It commits the result as a new changeset.  This changeset has
  86.389 +  \texttt{backout} as its parent.
  86.390 +\item If you specify \hgopt{backout}{--merge} on the command line, it
  86.391 +  merges with \texttt{orig}, and commits the result of the merge.
  86.392 +\end{enumerate}
  86.393 +
  86.394 +An alternative way to implement the \hgcmd{backout} command would be
  86.395 +to \hgcmd{export} the to-be-backed-out changeset as a diff, then use
  86.396 +the \cmdopt{patch}{--reverse} option to the \command{patch} command to
  86.397 +reverse the effect of the change without fiddling with the working
  86.398 +directory.  This sounds much simpler, but it would not work nearly as
  86.399 +well.
  86.400 +
  86.401 +The reason that \hgcmd{backout} does an update, a commit, a merge, and
  86.402 +another commit is to give the merge machinery the best chance to do a
  86.403 +good job when dealing with all the changes \emph{between} the change
  86.404 +you're backing out and the current tip.  
  86.405 +
  86.406 +If you're backing out a changeset that's~100 revisions back in your
  86.407 +project's history, the chances that the \command{patch} command will
  86.408 +be able to apply a reverse diff cleanly are not good, because
  86.409 +intervening changes are likely to have ``broken the context'' that
  86.410 +\command{patch} uses to determine whether it can apply a patch (if
  86.411 +this sounds like gibberish, see \ref{sec:mq:patch} for a
  86.412 +discussion of the \command{patch} command).  Also, Mercurial's merge
  86.413 +machinery will handle files and directories being renamed, permission
  86.414 +changes, and modifications to binary files, none of which
  86.415 +\command{patch} can deal with.
  86.416 +
  86.417 +\section{Changes that should never have been}
  86.418 +\label{sec:undo:aaaiiieee}
  86.419 +
  86.420 +Most of the time, the \hgcmd{backout} command is exactly what you need
  86.421 +if you want to undo the effects of a change.  It leaves a permanent
  86.422 +record of exactly what you did, both when committing the original
  86.423 +changeset and when you cleaned up after it.
  86.424 +
  86.425 +On rare occasions, though, you may find that you've committed a change
  86.426 +that really should not be present in the repository at all.  For
  86.427 +example, it would be very unusual, and usually considered a mistake,
  86.428 +to commit a software project's object files as well as its source
  86.429 +files.  Object files have almost no intrinsic value, and they're
  86.430 +\emph{big}, so they increase the size of the repository and the amount
  86.431 +of time it takes to clone or pull changes.
  86.432 +
  86.433 +Before I discuss the options that you have if you commit a ``brown
  86.434 +paper bag'' change (the kind that's so bad that you want to pull a
  86.435 +brown paper bag over your head), let me first discuss some approaches
  86.436 +that probably won't work.
  86.437 +
  86.438 +Since Mercurial treats history as accumulative---every change builds
  86.439 +on top of all changes that preceded it---you generally can't just make
  86.440 +disastrous changes disappear.  The one exception is when you've just
  86.441 +committed a change, and it hasn't been pushed or pulled into another
  86.442 +repository.  That's when you can safely use the \hgcmd{rollback}
  86.443 +command, as I detailed in section~\ref{sec:undo:rollback}.
  86.444 +
  86.445 +After you've pushed a bad change to another repository, you
  86.446 +\emph{could} still use \hgcmd{rollback} to make your local copy of the
  86.447 +change disappear, but it won't have the consequences you want.  The
  86.448 +change will still be present in the remote repository, so it will
  86.449 +reappear in your local repository the next time you pull.
  86.450 +
  86.451 +If a situation like this arises, and you know which repositories your
  86.452 +bad change has propagated into, you can \emph{try} to get rid of the
  86.453 +changeefrom \emph{every} one of those repositories.  This is, of
  86.454 +course, not a satisfactory solution: if you miss even a single
  86.455 +repository while you're expunging, the change is still ``in the
  86.456 +wild'', and could propagate further.
  86.457 +
  86.458 +If you've committed one or more changes \emph{after} the change that
  86.459 +you'd like to see disappear, your options are further reduced.
  86.460 +Mercurial doesn't provide a way to ``punch a hole'' in history,
  86.461 +leaving changesets intact.
  86.462 +
  86.463 +XXX This needs filling out.  The \texttt{hg-replay} script in the
  86.464 +\texttt{examples} directory works, but doesn't handle merge
  86.465 +changesets.  Kind of an important omission.
  86.466 +
  86.467 +\subsection{Protect yourself from ``escaped'' changes}
  86.468 +
  86.469 +If you've committed some changes to your local repository and they've
  86.470 +been pushed or pulled somewhere else, this isn't necessarily a
  86.471 +disaster.  You can protect yourself ahead of time against some classes
  86.472 +of bad changeset.  This is particularly easy if your team usually
  86.473 +pulls changes from a central repository.
  86.474 +
  86.475 +By configuring some hooks on that repository to validate incoming
  86.476 +changesets (see chapter~\ref{chap:hook}), you can automatically
  86.477 +prevent some kinds of bad changeset from being pushed to the central
  86.478 +repository at all.  With such a configuration in place, some kinds of
  86.479 +bad changeset will naturally tend to ``die out'' because they can't
  86.480 +propagate into the central repository.  Better yet, this happens
  86.481 +without any need for explicit intervention.
  86.482 +
  86.483 +For instance, an incoming change hook that verifies that a changeset
  86.484 +will actually compile can prevent people from inadvertantly ``breaking
  86.485 +the build''.
  86.486 +
  86.487 +\section{Finding the source of a bug}
  86.488 +\label{sec:undo:bisect}
  86.489 +
  86.490 +While it's all very well to be able to back out a changeset that
  86.491 +introduced a bug, this requires that you know which changeset to back
  86.492 +out.  Mercurial provides an invaluable command, called
  86.493 +\hgcmd{bisect}, that helps you to automate this process and accomplish
  86.494 +it very efficiently.
  86.495 +
  86.496 +The idea behind the \hgcmd{bisect} command is that a changeset has
  86.497 +introduced some change of behaviour that you can identify with a
  86.498 +simple binary test.  You don't know which piece of code introduced the
  86.499 +change, but you know how to test for the presence of the bug.  The
  86.500 +\hgcmd{bisect} command uses your test to direct its search for the
  86.501 +changeset that introduced the code that caused the bug.
  86.502 +
  86.503 +Here are a few scenarios to help you understand how you might apply
  86.504 +this command.
  86.505 +\begin{itemize}
  86.506 +\item The most recent version of your software has a bug that you
  86.507 +  remember wasn't present a few weeks ago, but you don't know when it
  86.508 +  was introduced.  Here, your binary test checks for the presence of
  86.509 +  that bug.
  86.510 +\item You fixed a bug in a rush, and now it's time to close the entry
  86.511 +  in your team's bug database.  The bug database requires a changeset
  86.512 +  ID when you close an entry, but you don't remember which changeset
  86.513 +  you fixed the bug in.  Once again, your binary test checks for the
  86.514 +  presence of the bug.
  86.515 +\item Your software works correctly, but runs~15\% slower than the
  86.516 +  last time you measured it.  You want to know which changeset
  86.517 +  introduced the performance regression.  In this case, your binary
  86.518 +  test measures the performance of your software, to see whether it's
  86.519 +  ``fast'' or ``slow''.
  86.520 +\item The sizes of the components of your project that you ship
  86.521 +  exploded recently, and you suspect that something changed in the way
  86.522 +  you build your project.
  86.523 +\end{itemize}
  86.524 +
  86.525 +From these examples, it should be clear that the \hgcmd{bisect}
  86.526 +command is not useful only for finding the sources of bugs.  You can
  86.527 +use it to find any ``emergent property'' of a repository (anything
  86.528 +that you can't find from a simple text search of the files in the
  86.529 +tree) for which you can write a binary test.
  86.530 +
  86.531 +We'll introduce a little bit of terminology here, just to make it
  86.532 +clear which parts of the search process are your responsibility, and
  86.533 +which are Mercurial's.  A \emph{test} is something that \emph{you} run
  86.534 +when \hgcmd{bisect} chooses a changeset.  A \emph{probe} is what
  86.535 +\hgcmd{bisect} runs to tell whether a revision is good.  Finally,
  86.536 +we'll use the word ``bisect'', as both a noun and a verb, to stand in
  86.537 +for the phrase ``search using the \hgcmd{bisect} command.
  86.538 +
  86.539 +One simple way to automate the searching process would be simply to
  86.540 +probe every changeset.  However, this scales poorly.  If it took ten
  86.541 +minutes to test a single changeset, and you had 10,000 changesets in
  86.542 +your repository, the exhaustive approach would take on average~35
  86.543 +\emph{days} to find the changeset that introduced a bug.  Even if you
  86.544 +knew that the bug was introduced by one of the last 500 changesets,
  86.545 +and limited your search to those, you'd still be looking at over 40
  86.546 +hours to find the changeset that introduced your bug.
  86.547 +
  86.548 +What the \hgcmd{bisect} command does is use its knowledge of the
  86.549 +``shape'' of your project's revision history to perform a search in
  86.550 +time proportional to the \emph{logarithm} of the number of changesets
  86.551 +to check (the kind of search it performs is called a dichotomic
  86.552 +search).  With this approach, searching through 10,000 changesets will
  86.553 +take less than three hours, even at ten minutes per test (the search
  86.554 +will require about 14 tests).  Limit your search to the last hundred
  86.555 +changesets, and it will take only about an hour (roughly seven tests).
  86.556 +
  86.557 +The \hgcmd{bisect} command is aware of the ``branchy'' nature of a
  86.558 +Mercurial project's revision history, so it has no problems dealing
  86.559 +with branches, merges, or multiple heads in a repository.  It can
  86.560 +prune entire branches of history with a single probe, which is how it
  86.561 +operates so efficiently.
  86.562 +
  86.563 +\subsection{Using the \hgcmd{bisect} command}
  86.564 +
  86.565 +Here's an example of \hgcmd{bisect} in action.
  86.566 +
  86.567 +\begin{note}
  86.568 +  In versions 0.9.5 and earlier of Mercurial, \hgcmd{bisect} was not a
  86.569 +  core command: it was distributed with Mercurial as an extension.
  86.570 +  This section describes the built-in command, not the old extension.
  86.571 +\end{note}
  86.572 +
  86.573 +Now let's create a repository, so that we can try out the
  86.574 +\hgcmd{bisect} command in isolation.
  86.575 +\interaction{bisect.init}
  86.576 +We'll simulate a project that has a bug in it in a simple-minded way:
  86.577 +create trivial changes in a loop, and nominate one specific change
  86.578 +that will have the ``bug''.  This loop creates 35 changesets, each
  86.579 +adding a single file to the repository.  We'll represent our ``bug''
  86.580 +with a file that contains the text ``i have a gub''.
  86.581 +\interaction{bisect.commits}
  86.582 +
  86.583 +The next thing that we'd like to do is figure out how to use the
  86.584 +\hgcmd{bisect} command.  We can use Mercurial's normal built-in help
  86.585 +mechanism for this.
  86.586 +\interaction{bisect.help}
  86.587 +
  86.588 +The \hgcmd{bisect} command works in steps.  Each step proceeds as follows.
  86.589 +\begin{enumerate}
  86.590 +\item You run your binary test.
  86.591 +  \begin{itemize}
  86.592 +  \item If the test succeeded, you tell \hgcmd{bisect} by running the
  86.593 +    \hgcmdargs{bisect}{good} command.
  86.594 +  \item If it failed, run the \hgcmdargs{bisect}{--bad} command.
  86.595 +  \end{itemize}
  86.596 +\item The command uses your information to decide which changeset to
  86.597 +  test next.
  86.598 +\item It updates the working directory to that changeset, and the
  86.599 +  process begins again.
  86.600 +\end{enumerate}
  86.601 +The process ends when \hgcmd{bisect} identifies a unique changeset
  86.602 +that marks the point where your test transitioned from ``succeeding''
  86.603 +to ``failing''.
  86.604 +
  86.605 +To start the search, we must run the \hgcmdargs{bisect}{--reset} command.
  86.606 +\interaction{bisect.search.init}
  86.607 +
  86.608 +In our case, the binary test we use is simple: we check to see if any
  86.609 +file in the repository contains the string ``i have a gub''.  If it
  86.610 +does, this changeset contains the change that ``caused the bug''.  By
  86.611 +convention, a changeset that has the property we're searching for is
  86.612 +``bad'', while one that doesn't is ``good''.
  86.613 +
  86.614 +Most of the time, the revision to which the working directory is
  86.615 +synced (usually the tip) already exhibits the problem introduced by
  86.616 +the buggy change, so we'll mark it as ``bad''.
  86.617 +\interaction{bisect.search.bad-init}
  86.618 +
  86.619 +Our next task is to nominate a changeset that we know \emph{doesn't}
  86.620 +have the bug; the \hgcmd{bisect} command will ``bracket'' its search
  86.621 +between the first pair of good and bad changesets.  In our case, we
  86.622 +know that revision~10 didn't have the bug.  (I'll have more words
  86.623 +about choosing the first ``good'' changeset later.)
  86.624 +\interaction{bisect.search.good-init}
  86.625 +
  86.626 +Notice that this command printed some output.
  86.627 +\begin{itemize}
  86.628 +\item It told us how many changesets it must consider before it can
  86.629 +  identify the one that introduced the bug, and how many tests that
  86.630 +  will require.
  86.631 +\item It updated the working directory to the next changeset to test,
  86.632 +  and told us which changeset it's testing.
  86.633 +\end{itemize}
  86.634 +
  86.635 +We now run our test in the working directory.  We use the
  86.636 +\command{grep} command to see if our ``bad'' file is present in the
  86.637 +working directory.  If it is, this revision is bad; if not, this
  86.638 +revision is good.
  86.639 +\interaction{bisect.search.step1}
  86.640 +
  86.641 +This test looks like a perfect candidate for automation, so let's turn
  86.642 +it into a shell function.
  86.643 +\interaction{bisect.search.mytest}
  86.644 +We can now run an entire test step with a single command,
  86.645 +\texttt{mytest}.
  86.646 +\interaction{bisect.search.step2}
  86.647 +A few more invocations of our canned test step command, and we're
  86.648 +done.
  86.649 +\interaction{bisect.search.rest}
  86.650 +
  86.651 +Even though we had~40 changesets to search through, the \hgcmd{bisect}
  86.652 +command let us find the changeset that introduced our ``bug'' with
  86.653 +only five tests.  Because the number of tests that the \hgcmd{bisect}
  86.654 +command performs grows logarithmically with the number of changesets to
  86.655 +search, the advantage that it has over the ``brute force'' search
  86.656 +approach increases with every changeset you add.
  86.657 +
  86.658 +\subsection{Cleaning up after your search}
  86.659 +
  86.660 +When you're finished using the \hgcmd{bisect} command in a
  86.661 +repository, you can use the \hgcmdargs{bisect}{reset} command to drop
  86.662 +the information it was using to drive your search.  The command
  86.663 +doesn't use much space, so it doesn't matter if you forget to run this
  86.664 +command.  However, \hgcmd{bisect} won't let you start a new search in
  86.665 +that repository until you do a \hgcmdargs{bisect}{reset}.
  86.666 +\interaction{bisect.search.reset}
  86.667 +
  86.668 +\section{Tips for finding bugs effectively}
  86.669 +
  86.670 +\subsection{Give consistent input}
  86.671 +
  86.672 +The \hgcmd{bisect} command requires that you correctly report the
  86.673 +result of every test you perform.  If you tell it that a test failed
  86.674 +when it really succeeded, it \emph{might} be able to detect the
  86.675 +inconsistency.  If it can identify an inconsistency in your reports,
  86.676 +it will tell you that a particular changeset is both good and bad.
  86.677 +However, it can't do this perfectly; it's about as likely to report
  86.678 +the wrong changeset as the source of the bug.
  86.679 +
  86.680 +\subsection{Automate as much as possible}
  86.681 +
  86.682 +When I started using the \hgcmd{bisect} command, I tried a few times
  86.683 +to run my tests by hand, on the command line.  This is an approach
  86.684 +that I, at least, am not suited to.  After a few tries, I found that I
  86.685 +was making enough mistakes that I was having to restart my searches
  86.686 +several times before finally getting correct results.
  86.687 +
  86.688 +My initial problems with driving the \hgcmd{bisect} command by hand
  86.689 +occurred even with simple searches on small repositories; if the
  86.690 +problem you're looking for is more subtle, or the number of tests that
  86.691 +\hgcmd{bisect} must perform increases, the likelihood of operator
  86.692 +error ruining the search is much higher.  Once I started automating my
  86.693 +tests, I had much better results.
  86.694 +
  86.695 +The key to automated testing is twofold:
  86.696 +\begin{itemize}
  86.697 +\item always test for the same symptom, and
  86.698 +\item always feed consistent input to the \hgcmd{bisect} command.
  86.699 +\end{itemize}
  86.700 +In my tutorial example above, the \command{grep} command tests for the
  86.701 +symptom, and the \texttt{if} statement takes the result of this check
  86.702 +and ensures that we always feed the same input to the \hgcmd{bisect}
  86.703 +command.  The \texttt{mytest} function marries these together in a
  86.704 +reproducible way, so that every test is uniform and consistent.
  86.705 +
  86.706 +\subsection{Check your results}
  86.707 +
  86.708 +Because the output of a \hgcmd{bisect} search is only as good as the
  86.709 +input you give it, don't take the changeset it reports as the
  86.710 +absolute truth.  A simple way to cross-check its report is to manually
  86.711 +run your test at each of the following changesets:
  86.712 +\begin{itemize}
  86.713 +\item The changeset that it reports as the first bad revision.  Your
  86.714 +  test should still report this as bad.
  86.715 +\item The parent of that changeset (either parent, if it's a merge).
  86.716 +  Your test should report this changeset as good.
  86.717 +\item A child of that changeset.  Your test should report this
  86.718 +  changeset as bad.
  86.719 +\end{itemize}
  86.720 +
  86.721 +\subsection{Beware interference between bugs}
  86.722 +
  86.723 +It's possible that your search for one bug could be disrupted by the
  86.724 +presence of another.  For example, let's say your software crashes at
  86.725 +revision 100, and worked correctly at revision 50.  Unknown to you,
  86.726 +someone else introduced a different crashing bug at revision 60, and
  86.727 +fixed it at revision 80.  This could distort your results in one of
  86.728 +several ways.
  86.729 +
  86.730 +It is possible that this other bug completely ``masks'' yours, which
  86.731 +is to say that it occurs before your bug has a chance to manifest
  86.732 +itself.  If you can't avoid that other bug (for example, it prevents
  86.733 +your project from building), and so can't tell whether your bug is
  86.734 +present in a particular changeset, the \hgcmd{bisect} command cannot
  86.735 +help you directly.  Instead, you can mark a changeset as untested by
  86.736 +running \hgcmdargs{bisect}{--skip}.
  86.737 +
  86.738 +A different problem could arise if your test for a bug's presence is
  86.739 +not specific enough.  If you check for ``my program crashes'', then
  86.740 +both your crashing bug and an unrelated crashing bug that masks it
  86.741 +will look like the same thing, and mislead \hgcmd{bisect}.
  86.742 +
  86.743 +Another useful situation in which to use \hgcmdargs{bisect}{--skip} is
  86.744 +if you can't test a revision because your project was in a broken and
  86.745 +hence untestable state at that revision, perhaps because someone
  86.746 +checked in a change that prevented the project from building.
  86.747 +
  86.748 +\subsection{Bracket your search lazily}
  86.749 +
  86.750 +Choosing the first ``good'' and ``bad'' changesets that will mark the
  86.751 +end points of your search is often easy, but it bears a little
  86.752 +discussion nevertheless.  From the perspective of \hgcmd{bisect}, the
  86.753 +``newest'' changeset is conventionally ``bad'', and the older
  86.754 +changeset is ``good''.
  86.755 +
  86.756 +If you're having trouble remembering when a suitable ``good'' change
  86.757 +was, so that you can tell \hgcmd{bisect}, you could do worse than
  86.758 +testing changesets at random.  Just remember to eliminate contenders
  86.759 +that can't possibly exhibit the bug (perhaps because the feature with
  86.760 +the bug isn't present yet) and those where another problem masks the
  86.761 +bug (as I discussed above).
  86.762 +
  86.763 +Even if you end up ``early'' by thousands of changesets or months of
  86.764 +history, you will only add a handful of tests to the total number that
  86.765 +\hgcmd{bisect} must perform, thanks to its logarithmic behaviour.
  86.766 +
  86.767 +%%% Local Variables: 
  86.768 +%%% mode: latex
  86.769 +%%% TeX-master: "00book"
  86.770 +%%% End: 
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/fr/wdir-after-commit.svg	Thu Feb 05 12:37:03 2009 +0100
    87.3 @@ -0,0 +1,394 @@
    87.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    87.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    87.6 +<svg
    87.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    87.8 +   xmlns:cc="http://web.resource.org/cc/"
    87.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   87.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   87.11 +   xmlns="http://www.w3.org/2000/svg"
   87.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
   87.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   87.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   87.15 +   width="744.09448819"
   87.16 +   height="1052.3622047"
   87.17 +   id="svg5971"
   87.18 +   sodipodi:version="0.32"
   87.19 +   inkscape:version="0.44.1"
   87.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
   87.21 +   sodipodi:docname="wdir-after-commit.svg">
   87.22 +  <defs
   87.23 +     id="defs5973">
   87.24 +    <linearGradient
   87.25 +       inkscape:collect="always"
   87.26 +       xlink:href="#linearGradient6049"
   87.27 +       id="linearGradient6445"
   87.28 +       gradientUnits="userSpaceOnUse"
   87.29 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
   87.30 +       x1="333.91171"
   87.31 +       y1="488.79077"
   87.32 +       x2="508.94543"
   87.33 +       y2="263.79077" />
   87.34 +    <marker
   87.35 +       inkscape:stockid="Arrow1Mstart"
   87.36 +       orient="auto"
   87.37 +       refY="0.0"
   87.38 +       refX="0.0"
   87.39 +       id="Arrow1Mstart"
   87.40 +       style="overflow:visible">
   87.41 +      <path
   87.42 +         id="path4855"
   87.43 +         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 "
   87.44 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   87.45 +         transform="scale(0.4) translate(10,0)" />
   87.46 +    </marker>
   87.47 +    <linearGradient
   87.48 +       id="linearGradient6049">
   87.49 +      <stop
   87.50 +         style="stop-color:#686868;stop-opacity:1;"
   87.51 +         offset="0"
   87.52 +         id="stop6051" />
   87.53 +      <stop
   87.54 +         style="stop-color:#f0f0f0;stop-opacity:1;"
   87.55 +         offset="1"
   87.56 +         id="stop6053" />
   87.57 +    </linearGradient>
   87.58 +    <marker
   87.59 +       inkscape:stockid="Arrow1Mend"
   87.60 +       orient="auto"
   87.61 +       refY="0.0"
   87.62 +       refX="0.0"
   87.63 +       id="Arrow1Mend"
   87.64 +       style="overflow:visible;">
   87.65 +      <path
   87.66 +         id="path4852"
   87.67 +         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 "
   87.68 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   87.69 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   87.70 +    </marker>
   87.71 +    <linearGradient
   87.72 +       inkscape:collect="always"
   87.73 +       xlink:href="#linearGradient6049"
   87.74 +       id="linearGradient6083"
   87.75 +       gradientUnits="userSpaceOnUse"
   87.76 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
   87.77 +       x1="333.91171"
   87.78 +       y1="488.79077"
   87.79 +       x2="508.94543"
   87.80 +       y2="263.79077" />
   87.81 +    <linearGradient
   87.82 +       inkscape:collect="always"
   87.83 +       xlink:href="#linearGradient6049"
   87.84 +       id="linearGradient6142"
   87.85 +       gradientUnits="userSpaceOnUse"
   87.86 +       gradientTransform="translate(-42.00893,-30.49544)"
   87.87 +       x1="333.91171"
   87.88 +       y1="488.79077"
   87.89 +       x2="508.94543"
   87.90 +       y2="263.79077" />
   87.91 +    <linearGradient
   87.92 +       inkscape:collect="always"
   87.93 +       xlink:href="#linearGradient6049"
   87.94 +       id="linearGradient6193"
   87.95 +       gradientUnits="userSpaceOnUse"
   87.96 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
   87.97 +       x1="333.91171"
   87.98 +       y1="488.79077"
   87.99 +       x2="508.94543"
  87.100 +       y2="263.79077" />
  87.101 +    <linearGradient
  87.102 +       inkscape:collect="always"
  87.103 +       xlink:href="#linearGradient6049"
  87.104 +       id="linearGradient6216"
  87.105 +       gradientUnits="userSpaceOnUse"
  87.106 +       gradientTransform="translate(-6.0462,-0.664361)"
  87.107 +       x1="333.91171"
  87.108 +       y1="488.79077"
  87.109 +       x2="508.94543"
  87.110 +       y2="263.79077" />
  87.111 +    <linearGradient
  87.112 +       inkscape:collect="always"
  87.113 +       xlink:href="#linearGradient6049"
  87.114 +       id="linearGradient6232"
  87.115 +       gradientUnits="userSpaceOnUse"
  87.116 +       gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)"
  87.117 +       x1="333.91171"
  87.118 +       y1="488.79077"
  87.119 +       x2="508.94543"
  87.120 +       y2="263.79077" />
  87.121 +    <linearGradient
  87.122 +       inkscape:collect="always"
  87.123 +       xlink:href="#linearGradient6049"
  87.124 +       id="linearGradient6772"
  87.125 +       gradientUnits="userSpaceOnUse"
  87.126 +       gradientTransform="matrix(1.000474,0,0,0.790947,222.8399,50.85693)"
  87.127 +       x1="333.91171"
  87.128 +       y1="488.79077"
  87.129 +       x2="508.94543"
  87.130 +       y2="263.79077" />
  87.131 +  </defs>
  87.132 +  <sodipodi:namedview
  87.133 +     id="base"
  87.134 +     pagecolor="#ffffff"
  87.135 +     bordercolor="#666666"
  87.136 +     borderopacity="1.0"
  87.137 +     gridtolerance="10000"
  87.138 +     guidetolerance="10"
  87.139 +     objecttolerance="10"
  87.140 +     inkscape:pageopacity="0.0"
  87.141 +     inkscape:pageshadow="2"
  87.142 +     inkscape:zoom="0.90509668"
  87.143 +     inkscape:cx="390.0539"
  87.144 +     inkscape:cy="690.49342"
  87.145 +     inkscape:document-units="px"
  87.146 +     inkscape:current-layer="layer1"
  87.147 +     showguides="true"
  87.148 +     inkscape:guide-bbox="true"
  87.149 +     inkscape:window-width="906"
  87.150 +     inkscape:window-height="620"
  87.151 +     inkscape:window-x="0"
  87.152 +     inkscape:window-y="25">
  87.153 +    <sodipodi:guide
  87.154 +       orientation="vertical"
  87.155 +       position="-1.4285714"
  87.156 +       id="guide6022" />
  87.157 +  </sodipodi:namedview>
  87.158 +  <metadata
  87.159 +     id="metadata5976">
  87.160 +    <rdf:RDF>
  87.161 +      <cc:Work
  87.162 +         rdf:about="">
  87.163 +        <dc:format>image/svg+xml</dc:format>
  87.164 +        <dc:type
  87.165 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  87.166 +      </cc:Work>
  87.167 +    </rdf:RDF>
  87.168 +  </metadata>
  87.169 +  <g
  87.170 +     inkscape:label="Layer 1"
  87.171 +     inkscape:groupmode="layer"
  87.172 +     id="layer1">
  87.173 +    <rect
  87.174 +       y="245.98355"
  87.175 +       x="328.23956"
  87.176 +       height="258.57144"
  87.177 +       width="174.28572"
  87.178 +       id="rect6047"
  87.179 +       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" />
  87.180 +    <g
  87.181 +       id="g6261"
  87.182 +       transform="translate(234,0)">
  87.183 +      <rect
  87.184 +         y="258.7149"
  87.185 +         x="114.11369"
  87.186 +         height="44.537449"
  87.187 +         width="134.53746"
  87.188 +         id="rect5983"
  87.189 +         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" />
  87.190 +      <text
  87.191 +         id="text5985"
  87.192 +         y="284.47562"
  87.193 +         x="138.7962"
  87.194 +         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"
  87.195 +         xml:space="preserve"><tspan
  87.196 +           style="font-family:Courier"
  87.197 +           y="284.47562"
  87.198 +           x="138.7962"
  87.199 +           id="tspan5987"
  87.200 +           sodipodi:role="line">dfbbb33f3fa3</tspan></text>
  87.201 +    </g>
  87.202 +    <rect
  87.203 +       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"
  87.204 +       id="rect5996"
  87.205 +       width="134.53746"
  87.206 +       height="44.537449"
  87.207 +       x="348.11371"
  87.208 +       y="320.38159" />
  87.209 +    <text
  87.210 +       xml:space="preserve"
  87.211 +       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"
  87.212 +       x="372.7962"
  87.213 +       y="346.1423"
  87.214 +       id="text5998"><tspan
  87.215 +         sodipodi:role="line"
  87.216 +         id="tspan6000"
  87.217 +         x="372.7962"
  87.218 +         y="346.1423"
  87.219 +         style="font-family:Courier">e7639888bb2f</tspan></text>
  87.220 +    <rect
  87.221 +       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"
  87.222 +       id="rect6004"
  87.223 +       width="134.53746"
  87.224 +       height="44.537449"
  87.225 +       x="348.11371"
  87.226 +       y="382.04825" />
  87.227 +    <text
  87.228 +       xml:space="preserve"
  87.229 +       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"
  87.230 +       x="370.65421"
  87.231 +       y="407.80896"
  87.232 +       id="text6006"><tspan
  87.233 +         sodipodi:role="line"
  87.234 +         id="tspan6008"
  87.235 +         x="370.65421"
  87.236 +         y="407.80896"
  87.237 +         style="font-family:Courier">7b064d8bac5e</tspan></text>
  87.238 +    <path
  87.239 +       inkscape:connector-type="polyline"
  87.240 +       id="path6018"
  87.241 +       d="M 415.38242,303.62646 L 415.38242,320.00744"
  87.242 +       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" />
  87.243 +    <path
  87.244 +       inkscape:connection-end="#rect6004"
  87.245 +       inkscape:connector-type="polyline"
  87.246 +       id="path6020"
  87.247 +       d="M 415.38242,365.29315 L 415.38243,381.67412"
  87.248 +       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" />
  87.249 +    <rect
  87.250 +       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"
  87.251 +       id="rect6039"
  87.252 +       width="134.53746"
  87.253 +       height="44.537449"
  87.254 +       x="348.11359"
  87.255 +       y="443.71487" />
  87.256 +    <text
  87.257 +       xml:space="preserve"
  87.258 +       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"
  87.259 +       x="372.79706"
  87.260 +       y="469.47556"
  87.261 +       id="text6041"><tspan
  87.262 +         sodipodi:role="line"
  87.263 +         id="tspan6043"
  87.264 +         x="372.79706"
  87.265 +         y="469.47556"
  87.266 +         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
  87.267 +    <path
  87.268 +       inkscape:connection-end="#rect6039"
  87.269 +       inkscape:connector-type="polyline"
  87.270 +       id="path6045"
  87.271 +       d="M 415.38238,426.95981 L 415.38235,443.34087"
  87.272 +       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" />
  87.273 +    <text
  87.274 +       xml:space="preserve"
  87.275 +       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"
  87.276 +       x="327.66046"
  87.277 +       y="231.36218"
  87.278 +       id="text6102"><tspan
  87.279 +         sodipodi:role="line"
  87.280 +         id="tspan6104"
  87.281 +         x="327.66046"
  87.282 +         y="231.36218">History in repository</tspan></text>
  87.283 +    <rect
  87.284 +       y="245.94225"
  87.285 +       x="557.28418"
  87.286 +       height="204.51619"
  87.287 +       width="174.36833"
  87.288 +       id="rect6140"
  87.289 +       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" />
  87.290 +    <g
  87.291 +       id="g6130"
  87.292 +       transform="translate(262.3254,24.38544)">
  87.293 +      <rect
  87.294 +         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"
  87.295 +         id="rect6106"
  87.296 +         width="134.53746"
  87.297 +         height="44.537449"
  87.298 +         x="314.87415"
  87.299 +         y="257.95059" />
  87.300 +      <text
  87.301 +         xml:space="preserve"
  87.302 +         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"
  87.303 +         x="339.55664"
  87.304 +         y="283.7113"
  87.305 +         id="text6108"><tspan
  87.306 +           sodipodi:role="line"
  87.307 +           id="tspan6110"
  87.308 +           x="339.55664"
  87.309 +           y="283.7113"
  87.310 +           style="font-family:Courier">dfbbb33f3fa3</tspan></text>
  87.311 +    </g>
  87.312 +    <g
  87.313 +       id="g6135"
  87.314 +       transform="translate(263.0396,49.83106)">
  87.315 +      <rect
  87.316 +         inkscape:transform-center-y="102.85714"
  87.317 +         inkscape:transform-center-x="129.28571"
  87.318 +         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"
  87.319 +         id="rect6112"
  87.320 +         width="134.53746"
  87.321 +         height="44.537449"
  87.322 +         x="314.15985"
  87.323 +         y="326.52203" />
  87.324 +      <text
  87.325 +         inkscape:transform-center-y="102.7311"
  87.326 +         inkscape:transform-center-x="128.69672"
  87.327 +         xml:space="preserve"
  87.328 +         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"
  87.329 +         x="338.84335"
  87.330 +         y="352.28271"
  87.331 +         id="text6114"><tspan
  87.332 +           sodipodi:role="line"
  87.333 +           id="tspan6116"
  87.334 +           x="338.84335"
  87.335 +           y="352.28271"
  87.336 +           style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
  87.337 +    </g>
  87.338 +    <text
  87.339 +       xml:space="preserve"
  87.340 +       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"
  87.341 +       x="576.63208"
  87.342 +       y="270.479"
  87.343 +       id="text6118"><tspan
  87.344 +         sodipodi:role="line"
  87.345 +         id="tspan6120"
  87.346 +         x="576.63208"
  87.347 +         y="270.479">First parent</tspan></text>
  87.348 +    <text
  87.349 +       xml:space="preserve"
  87.350 +       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"
  87.351 +       x="576.07544"
  87.352 +       y="364.49615"
  87.353 +       id="text6122"><tspan
  87.354 +         sodipodi:role="line"
  87.355 +         id="tspan6124"
  87.356 +         x="576.07544"
  87.357 +         y="364.49615">Second parent</tspan></text>
  87.358 +    <text
  87.359 +       xml:space="preserve"
  87.360 +       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"
  87.361 +       x="556.61743"
  87.362 +       y="231.36218"
  87.363 +       id="text6195"><tspan
  87.364 +         sodipodi:role="line"
  87.365 +         id="tspan6197"
  87.366 +         x="556.61743"
  87.367 +         y="231.36218">Parents of working directory</tspan></text>
  87.368 +    <path
  87.369 +       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"
  87.370 +       d="M 576.82542,297.63008 L 483.02528,287.95831"
  87.371 +       id="path6266"
  87.372 +       inkscape:connector-type="polyline"
  87.373 +       inkscape:connection-start="#g6130"
  87.374 +       inkscape:connection-end="#g6261" />
  87.375 +    <path
  87.376 +       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
  87.377 +       d="M 665.12232,418.17579 L 665.12232,418.17579"
  87.378 +       id="path6270"
  87.379 +       inkscape:connector-type="polyline" />
  87.380 +    <text
  87.381 +       xml:space="preserve"
  87.382 +       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"
  87.383 +       x="316.86407"
  87.384 +       y="275.6496"
  87.385 +       id="text6573"><tspan
  87.386 +         sodipodi:role="line"
  87.387 +         id="tspan6575"
  87.388 +         x="316.86407"
  87.389 +         y="275.6496"
  87.390 +         style="text-align:end;text-anchor:end">New</tspan><tspan
  87.391 +         sodipodi:role="line"
  87.392 +         x="316.86407"
  87.393 +         y="290.6496"
  87.394 +         id="tspan6577"
  87.395 +         style="text-align:end;text-anchor:end">changeset</tspan></text>
  87.396 +  </g>
  87.397 +</svg>
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/fr/wdir-branch.svg	Thu Feb 05 12:37:03 2009 +0100
    88.3 @@ -0,0 +1,418 @@
    88.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    88.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    88.6 +<svg
    88.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    88.8 +   xmlns:cc="http://web.resource.org/cc/"
    88.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   88.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   88.11 +   xmlns="http://www.w3.org/2000/svg"
   88.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
   88.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   88.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   88.15 +   width="744.09448819"
   88.16 +   height="1052.3622047"
   88.17 +   id="svg5971"
   88.18 +   sodipodi:version="0.32"
   88.19 +   inkscape:version="0.44.1"
   88.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
   88.21 +   sodipodi:docname="wdir-branch.svg">
   88.22 +  <defs
   88.23 +     id="defs5973">
   88.24 +    <marker
   88.25 +       inkscape:stockid="Arrow1Mstart"
   88.26 +       orient="auto"
   88.27 +       refY="0.0"
   88.28 +       refX="0.0"
   88.29 +       id="Arrow1Mstart"
   88.30 +       style="overflow:visible">
   88.31 +      <path
   88.32 +         id="path4855"
   88.33 +         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 "
   88.34 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   88.35 +         transform="scale(0.4) translate(10,0)" />
   88.36 +    </marker>
   88.37 +    <linearGradient
   88.38 +       id="linearGradient6049">
   88.39 +      <stop
   88.40 +         style="stop-color:#686868;stop-opacity:1;"
   88.41 +         offset="0"
   88.42 +         id="stop6051" />
   88.43 +      <stop
   88.44 +         style="stop-color:#f0f0f0;stop-opacity:1;"
   88.45 +         offset="1"
   88.46 +         id="stop6053" />
   88.47 +    </linearGradient>
   88.48 +    <marker
   88.49 +       inkscape:stockid="Arrow1Mend"
   88.50 +       orient="auto"
   88.51 +       refY="0.0"
   88.52 +       refX="0.0"
   88.53 +       id="Arrow1Mend"
   88.54 +       style="overflow:visible;">
   88.55 +      <path
   88.56 +         id="path4852"
   88.57 +         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 "
   88.58 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   88.59 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   88.60 +    </marker>
   88.61 +    <linearGradient
   88.62 +       inkscape:collect="always"
   88.63 +       xlink:href="#linearGradient6049"
   88.64 +       id="linearGradient6083"
   88.65 +       gradientUnits="userSpaceOnUse"
   88.66 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
   88.67 +       x1="333.91171"
   88.68 +       y1="488.79077"
   88.69 +       x2="508.94543"
   88.70 +       y2="263.79077" />
   88.71 +    <linearGradient
   88.72 +       inkscape:collect="always"
   88.73 +       xlink:href="#linearGradient6049"
   88.74 +       id="linearGradient6142"
   88.75 +       gradientUnits="userSpaceOnUse"
   88.76 +       gradientTransform="translate(-42.00893,-30.49544)"
   88.77 +       x1="333.91171"
   88.78 +       y1="488.79077"
   88.79 +       x2="508.94543"
   88.80 +       y2="263.79077" />
   88.81 +    <linearGradient
   88.82 +       inkscape:collect="always"
   88.83 +       xlink:href="#linearGradient6049"
   88.84 +       id="linearGradient6193"
   88.85 +       gradientUnits="userSpaceOnUse"
   88.86 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
   88.87 +       x1="333.91171"
   88.88 +       y1="488.79077"
   88.89 +       x2="508.94543"
   88.90 +       y2="263.79077" />
   88.91 +    <linearGradient
   88.92 +       inkscape:collect="always"
   88.93 +       xlink:href="#linearGradient6049"
   88.94 +       id="linearGradient6216"
   88.95 +       gradientUnits="userSpaceOnUse"
   88.96 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
   88.97 +       x1="333.91171"
   88.98 +       y1="488.79077"
   88.99 +       x2="508.94543"
  88.100 +       y2="263.79077" />
  88.101 +    <linearGradient
  88.102 +       inkscape:collect="always"
  88.103 +       xlink:href="#linearGradient6049"
  88.104 +       id="linearGradient6232"
  88.105 +       gradientUnits="userSpaceOnUse"
  88.106 +       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
  88.107 +       x1="333.91171"
  88.108 +       y1="488.79077"
  88.109 +       x2="508.94543"
  88.110 +       y2="263.79077" />
  88.111 +    <linearGradient
  88.112 +       inkscape:collect="always"
  88.113 +       xlink:href="#linearGradient6049"
  88.114 +       id="linearGradient6445"
  88.115 +       gradientUnits="userSpaceOnUse"
  88.116 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
  88.117 +       x1="333.91171"
  88.118 +       y1="488.79077"
  88.119 +       x2="508.94543"
  88.120 +       y2="263.79077" />
  88.121 +    <linearGradient
  88.122 +       inkscape:collect="always"
  88.123 +       xlink:href="#linearGradient6049"
  88.124 +       id="linearGradient6974"
  88.125 +       gradientUnits="userSpaceOnUse"
  88.126 +       gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)"
  88.127 +       x1="333.91171"
  88.128 +       y1="488.79077"
  88.129 +       x2="508.94543"
  88.130 +       y2="263.79077" />
  88.131 +    <linearGradient
  88.132 +       inkscape:collect="always"
  88.133 +       xlink:href="#linearGradient6049"
  88.134 +       id="linearGradient6996"
  88.135 +       gradientUnits="userSpaceOnUse"
  88.136 +       gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)"
  88.137 +       x1="333.91171"
  88.138 +       y1="488.79077"
  88.139 +       x2="508.94543"
  88.140 +       y2="263.79077" />
  88.141 +  </defs>
  88.142 +  <sodipodi:namedview
  88.143 +     id="base"
  88.144 +     pagecolor="#ffffff"
  88.145 +     bordercolor="#666666"
  88.146 +     borderopacity="1.0"
  88.147 +     gridtolerance="10000"
  88.148 +     guidetolerance="10"
  88.149 +     objecttolerance="10"
  88.150 +     inkscape:pageopacity="0.0"
  88.151 +     inkscape:pageshadow="2"
  88.152 +     inkscape:zoom="0.90509668"
  88.153 +     inkscape:cx="345.85973"
  88.154 +     inkscape:cy="690.49342"
  88.155 +     inkscape:document-units="px"
  88.156 +     inkscape:current-layer="layer1"
  88.157 +     showguides="true"
  88.158 +     inkscape:guide-bbox="true"
  88.159 +     inkscape:window-width="906"
  88.160 +     inkscape:window-height="620"
  88.161 +     inkscape:window-x="0"
  88.162 +     inkscape:window-y="25">
  88.163 +    <sodipodi:guide
  88.164 +       orientation="vertical"
  88.165 +       position="-1.4285714"
  88.166 +       id="guide6022" />
  88.167 +  </sodipodi:namedview>
  88.168 +  <metadata
  88.169 +     id="metadata5976">
  88.170 +    <rdf:RDF>
  88.171 +      <cc:Work
  88.172 +         rdf:about="">
  88.173 +        <dc:format>image/svg+xml</dc:format>
  88.174 +        <dc:type
  88.175 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  88.176 +      </cc:Work>
  88.177 +    </rdf:RDF>
  88.178 +  </metadata>
  88.179 +  <g
  88.180 +     inkscape:label="Layer 1"
  88.181 +     inkscape:groupmode="layer"
  88.182 +     id="layer1">
  88.183 +    <rect
  88.184 +       y="246.06918"
  88.185 +       x="64.325172"
  88.186 +       height="204.26233"
  88.187 +       width="333.2135"
  88.188 +       id="rect6047"
  88.189 +       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" />
  88.190 +    <g
  88.191 +       id="g1935">
  88.192 +      <rect
  88.193 +         y="266.24374"
  88.194 +         x="84.113708"
  88.195 +         height="44.537449"
  88.196 +         width="134.53746"
  88.197 +         id="rect5996"
  88.198 +         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" />
  88.199 +      <text
  88.200 +         id="text5998"
  88.201 +         y="292.00446"
  88.202 +         x="108.7962"
  88.203 +         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"
  88.204 +         xml:space="preserve"><tspan
  88.205 +           style="font-family:Courier"
  88.206 +           y="292.00446"
  88.207 +           x="108.7962"
  88.208 +           id="tspan6000"
  88.209 +           sodipodi:role="line">e7639888bb2f</tspan></text>
  88.210 +    </g>
  88.211 +    <g
  88.212 +       id="g6976"
  88.213 +       transform="translate(70,0)">
  88.214 +      <rect
  88.215 +         y="327.9104"
  88.216 +         x="40.113693"
  88.217 +         height="44.537449"
  88.218 +         width="134.53746"
  88.219 +         id="rect6004"
  88.220 +         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" />
  88.221 +      <text
  88.222 +         id="text6006"
  88.223 +         y="353.67111"
  88.224 +         x="62.654205"
  88.225 +         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"
  88.226 +         xml:space="preserve"><tspan
  88.227 +           style="font-family:Courier"
  88.228 +           y="353.67111"
  88.229 +           x="62.654205"
  88.230 +           id="tspan6008"
  88.231 +           sodipodi:role="line">7b064d8bac5e</tspan></text>
  88.232 +    </g>
  88.233 +    <path
  88.234 +       inkscape:connector-type="polyline"
  88.235 +       id="path6020"
  88.236 +       d="M 160.92915,311.15532 L 167.83571,327.53627"
  88.237 +       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"
  88.238 +       inkscape:connection-end="#g6976"
  88.239 +       inkscape:connection-start="#g1935" />
  88.240 +    <rect
  88.241 +       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"
  88.242 +       id="rect6039"
  88.243 +       width="134.53746"
  88.244 +       height="44.537449"
  88.245 +       x="110.11359"
  88.246 +       y="389.57703" />
  88.247 +    <text
  88.248 +       xml:space="preserve"
  88.249 +       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"
  88.250 +       x="134.79706"
  88.251 +       y="415.33771"
  88.252 +       id="text6041"><tspan
  88.253 +         sodipodi:role="line"
  88.254 +         id="tspan6043"
  88.255 +         x="134.79706"
  88.256 +         y="415.33771"
  88.257 +         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
  88.258 +    <path
  88.259 +       inkscape:connection-end="#rect6039"
  88.260 +       inkscape:connector-type="polyline"
  88.261 +       id="path6045"
  88.262 +       d="M 177.38238,372.82195 L 177.38235,389.20303"
  88.263 +       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" />
  88.264 +    <rect
  88.265 +       y="245.94225"
  88.266 +       x="447.28412"
  88.267 +       height="204.51619"
  88.268 +       width="174.36833"
  88.269 +       id="rect6140"
  88.270 +       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" />
  88.271 +    <g
  88.272 +       id="g6130"
  88.273 +       transform="translate(152.3254,24.38544)">
  88.274 +      <rect
  88.275 +         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"
  88.276 +         id="rect6106"
  88.277 +         width="134.53746"
  88.278 +         height="44.537449"
  88.279 +         x="314.87415"
  88.280 +         y="257.95059" />
  88.281 +      <text
  88.282 +         xml:space="preserve"
  88.283 +         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"
  88.284 +         x="339.55664"
  88.285 +         y="283.7113"
  88.286 +         id="text6108"><tspan
  88.287 +           sodipodi:role="line"
  88.288 +           id="tspan6110"
  88.289 +           x="339.55664"
  88.290 +           y="283.7113"
  88.291 +           style="font-family:Courier">ffb20e1701ea</tspan></text>
  88.292 +    </g>
  88.293 +    <g
  88.294 +       id="g6135"
  88.295 +       transform="translate(153.0396,49.83106)">
  88.296 +      <rect
  88.297 +         inkscape:transform-center-y="102.85714"
  88.298 +         inkscape:transform-center-x="129.28571"
  88.299 +         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"
  88.300 +         id="rect6112"
  88.301 +         width="134.53746"
  88.302 +         height="44.537449"
  88.303 +         x="314.15985"
  88.304 +         y="326.52203" />
  88.305 +      <text
  88.306 +         inkscape:transform-center-y="102.7311"
  88.307 +         inkscape:transform-center-x="128.69672"
  88.308 +         xml:space="preserve"
  88.309 +         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"
  88.310 +         x="338.84335"
  88.311 +         y="352.28271"
  88.312 +         id="text6114"><tspan
  88.313 +           sodipodi:role="line"
  88.314 +           id="tspan6116"
  88.315 +           x="338.84335"
  88.316 +           y="352.28271"
  88.317 +           style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
  88.318 +    </g>
  88.319 +    <text
  88.320 +       xml:space="preserve"
  88.321 +       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"
  88.322 +       x="466.63208"
  88.323 +       y="270.479"
  88.324 +       id="text6118"><tspan
  88.325 +         sodipodi:role="line"
  88.326 +         id="tspan6120"
  88.327 +         x="466.63208"
  88.328 +         y="270.479">First parent</tspan></text>
  88.329 +    <text
  88.330 +       xml:space="preserve"
  88.331 +       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"
  88.332 +       x="466.07544"
  88.333 +       y="364.49615"
  88.334 +       id="text6122"><tspan
  88.335 +         sodipodi:role="line"
  88.336 +         id="tspan6124"
  88.337 +         x="466.07544"
  88.338 +         y="364.49615">Second parent</tspan></text>
  88.339 +    <text
  88.340 +       xml:space="preserve"
  88.341 +       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"
  88.342 +       x="446.61743"
  88.343 +       y="231.36218"
  88.344 +       id="text6195"><tspan
  88.345 +         sodipodi:role="line"
  88.346 +         id="tspan6197"
  88.347 +         x="446.61743"
  88.348 +         y="231.36218">Parents of working directory</tspan></text>
  88.349 +    <path
  88.350 +       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"
  88.351 +       d="M 466.82542,300.21999 L 377.00207,294.39744"
  88.352 +       id="path6266"
  88.353 +       inkscape:connector-type="polyline"
  88.354 +       inkscape:connection-start="#g6130"
  88.355 +       inkscape:connection-end="#rect1925" />
  88.356 +    <path
  88.357 +       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
  88.358 +       d="M 665.12232,418.17579 L 665.12232,418.17579"
  88.359 +       id="path6270"
  88.360 +       inkscape:connector-type="polyline" />
  88.361 +    <g
  88.362 +       id="g2845">
  88.363 +      <rect
  88.364 +         y="266.24374"
  88.365 +         x="242.09048"
  88.366 +         height="44.537449"
  88.367 +         width="134.53746"
  88.368 +         id="rect1925"
  88.369 +         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" />
  88.370 +      <text
  88.371 +         id="text1927"
  88.372 +         y="292.00446"
  88.373 +         x="266.77298"
  88.374 +         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"
  88.375 +         xml:space="preserve"><tspan
  88.376 +           style="font-family:Courier"
  88.377 +           y="292.00446"
  88.378 +           x="266.77298"
  88.379 +           id="tspan1929"
  88.380 +           sodipodi:role="line">ffb20e1701ea</tspan></text>
  88.381 +    </g>
  88.382 +    <path
  88.383 +       inkscape:connector-type="polyline"
  88.384 +       id="path1933"
  88.385 +       d="M 260.89978,311.15532 L 225.84185,327.53627"
  88.386 +       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"
  88.387 +       inkscape:connection-end="#g6976" />
  88.388 +    <text
  88.389 +       xml:space="preserve"
  88.390 +       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"
  88.391 +       x="109.45568"
  88.392 +       y="231.4554"
  88.393 +       id="text2837"><tspan
  88.394 +         sodipodi:role="line"
  88.395 +         id="tspan2839"
  88.396 +         x="109.45568"
  88.397 +         y="231.4554">Pre-existing head</tspan></text>
  88.398 +    <text
  88.399 +       xml:space="preserve"
  88.400 +       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"
  88.401 +       x="237.54184"
  88.402 +       y="231.4554"
  88.403 +       id="text2841"><tspan
  88.404 +         sodipodi:role="line"
  88.405 +         id="tspan2843"
  88.406 +         x="237.54184"
  88.407 +         y="231.4554">Newly created head (and tip)</tspan></text>
  88.408 +    <path
  88.409 +       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)"
  88.410 +       d="M 148.05048,235.87482 L 149.94915,265.86962"
  88.411 +       id="path2850"
  88.412 +       inkscape:connector-type="polyline"
  88.413 +       inkscape:connection-end="#g1935" />
  88.414 +    <path
  88.415 +       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)"
  88.416 +       d="M 303.83495,238.08453 L 306.87874,265.86962"
  88.417 +       id="path2852"
  88.418 +       inkscape:connector-type="polyline"
  88.419 +       inkscape:connection-end="#g2845" />
  88.420 +  </g>
  88.421 +</svg>
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/fr/wdir-merge.svg	Thu Feb 05 12:37:03 2009 +0100
    89.3 @@ -0,0 +1,425 @@
    89.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    89.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    89.6 +<svg
    89.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    89.8 +   xmlns:cc="http://web.resource.org/cc/"
    89.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   89.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   89.11 +   xmlns="http://www.w3.org/2000/svg"
   89.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
   89.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   89.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   89.15 +   width="744.09448819"
   89.16 +   height="1052.3622047"
   89.17 +   id="svg5971"
   89.18 +   sodipodi:version="0.32"
   89.19 +   inkscape:version="0.44.1"
   89.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
   89.21 +   sodipodi:docname="wdir-merge.svg">
   89.22 +  <defs
   89.23 +     id="defs5973">
   89.24 +    <marker
   89.25 +       inkscape:stockid="Arrow1Mstart"
   89.26 +       orient="auto"
   89.27 +       refY="0.0"
   89.28 +       refX="0.0"
   89.29 +       id="Arrow1Mstart"
   89.30 +       style="overflow:visible">
   89.31 +      <path
   89.32 +         id="path4855"
   89.33 +         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 "
   89.34 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   89.35 +         transform="scale(0.4) translate(10,0)" />
   89.36 +    </marker>
   89.37 +    <linearGradient
   89.38 +       id="linearGradient6049">
   89.39 +      <stop
   89.40 +         style="stop-color:#686868;stop-opacity:1;"
   89.41 +         offset="0"
   89.42 +         id="stop6051" />
   89.43 +      <stop
   89.44 +         style="stop-color:#f0f0f0;stop-opacity:1;"
   89.45 +         offset="1"
   89.46 +         id="stop6053" />
   89.47 +    </linearGradient>
   89.48 +    <marker
   89.49 +       inkscape:stockid="Arrow1Mend"
   89.50 +       orient="auto"
   89.51 +       refY="0.0"
   89.52 +       refX="0.0"
   89.53 +       id="Arrow1Mend"
   89.54 +       style="overflow:visible;">
   89.55 +      <path
   89.56 +         id="path4852"
   89.57 +         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 "
   89.58 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   89.59 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   89.60 +    </marker>
   89.61 +    <linearGradient
   89.62 +       inkscape:collect="always"
   89.63 +       xlink:href="#linearGradient6049"
   89.64 +       id="linearGradient6083"
   89.65 +       gradientUnits="userSpaceOnUse"
   89.66 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
   89.67 +       x1="333.91171"
   89.68 +       y1="488.79077"
   89.69 +       x2="508.94543"
   89.70 +       y2="263.79077" />
   89.71 +    <linearGradient
   89.72 +       inkscape:collect="always"
   89.73 +       xlink:href="#linearGradient6049"
   89.74 +       id="linearGradient6142"
   89.75 +       gradientUnits="userSpaceOnUse"
   89.76 +       gradientTransform="translate(-42.00893,-30.49544)"
   89.77 +       x1="333.91171"
   89.78 +       y1="488.79077"
   89.79 +       x2="508.94543"
   89.80 +       y2="263.79077" />
   89.81 +    <linearGradient
   89.82 +       inkscape:collect="always"
   89.83 +       xlink:href="#linearGradient6049"
   89.84 +       id="linearGradient6193"
   89.85 +       gradientUnits="userSpaceOnUse"
   89.86 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
   89.87 +       x1="333.91171"
   89.88 +       y1="488.79077"
   89.89 +       x2="508.94543"
   89.90 +       y2="263.79077" />
   89.91 +    <linearGradient
   89.92 +       inkscape:collect="always"
   89.93 +       xlink:href="#linearGradient6049"
   89.94 +       id="linearGradient6216"
   89.95 +       gradientUnits="userSpaceOnUse"
   89.96 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
   89.97 +       x1="333.91171"
   89.98 +       y1="488.79077"
   89.99 +       x2="508.94543"
  89.100 +       y2="263.79077" />
  89.101 +    <linearGradient
  89.102 +       inkscape:collect="always"
  89.103 +       xlink:href="#linearGradient6049"
  89.104 +       id="linearGradient6232"
  89.105 +       gradientUnits="userSpaceOnUse"
  89.106 +       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
  89.107 +       x1="333.91171"
  89.108 +       y1="488.79077"
  89.109 +       x2="508.94543"
  89.110 +       y2="263.79077" />
  89.111 +    <linearGradient
  89.112 +       inkscape:collect="always"
  89.113 +       xlink:href="#linearGradient6049"
  89.114 +       id="linearGradient6445"
  89.115 +       gradientUnits="userSpaceOnUse"
  89.116 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
  89.117 +       x1="333.91171"
  89.118 +       y1="488.79077"
  89.119 +       x2="508.94543"
  89.120 +       y2="263.79077" />
  89.121 +    <linearGradient
  89.122 +       inkscape:collect="always"
  89.123 +       xlink:href="#linearGradient6049"
  89.124 +       id="linearGradient6974"
  89.125 +       gradientUnits="userSpaceOnUse"
  89.126 +       gradientTransform="matrix(1.911882,0,0,0.789965,-574.7896,51.22599)"
  89.127 +       x1="333.91171"
  89.128 +       y1="488.79077"
  89.129 +       x2="508.94543"
  89.130 +       y2="263.79077" />
  89.131 +    <linearGradient
  89.132 +       inkscape:collect="always"
  89.133 +       xlink:href="#linearGradient6049"
  89.134 +       id="linearGradient6996"
  89.135 +       gradientUnits="userSpaceOnUse"
  89.136 +       gradientTransform="matrix(1.000473,0,0,0.790947,112.8399,50.85693)"
  89.137 +       x1="333.91171"
  89.138 +       y1="488.79077"
  89.139 +       x2="508.94543"
  89.140 +       y2="263.79077" />
  89.141 +  </defs>
  89.142 +  <sodipodi:namedview
  89.143 +     id="base"
  89.144 +     pagecolor="#ffffff"
  89.145 +     bordercolor="#666666"
  89.146 +     borderopacity="1.0"
  89.147 +     gridtolerance="10000"
  89.148 +     guidetolerance="10"
  89.149 +     objecttolerance="10"
  89.150 +     inkscape:pageopacity="0.0"
  89.151 +     inkscape:pageshadow="2"
  89.152 +     inkscape:zoom="1.28"
  89.153 +     inkscape:cx="345.85973"
  89.154 +     inkscape:cy="690.49342"
  89.155 +     inkscape:document-units="px"
  89.156 +     inkscape:current-layer="layer1"
  89.157 +     showguides="true"
  89.158 +     inkscape:guide-bbox="true"
  89.159 +     inkscape:window-width="906"
  89.160 +     inkscape:window-height="620"
  89.161 +     inkscape:window-x="0"
  89.162 +     inkscape:window-y="25">
  89.163 +    <sodipodi:guide
  89.164 +       orientation="vertical"
  89.165 +       position="-1.4285714"
  89.166 +       id="guide6022" />
  89.167 +  </sodipodi:namedview>
  89.168 +  <metadata
  89.169 +     id="metadata5976">
  89.170 +    <rdf:RDF>
  89.171 +      <cc:Work
  89.172 +         rdf:about="">
  89.173 +        <dc:format>image/svg+xml</dc:format>
  89.174 +        <dc:type
  89.175 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  89.176 +      </cc:Work>
  89.177 +    </rdf:RDF>
  89.178 +  </metadata>
  89.179 +  <g
  89.180 +     inkscape:label="Layer 1"
  89.181 +     inkscape:groupmode="layer"
  89.182 +     id="layer1">
  89.183 +    <rect
  89.184 +       y="246.06918"
  89.185 +       x="64.325172"
  89.186 +       height="204.26233"
  89.187 +       width="333.2135"
  89.188 +       id="rect6047"
  89.189 +       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" />
  89.190 +    <g
  89.191 +       id="g6976"
  89.192 +       transform="translate(70,0)">
  89.193 +      <rect
  89.194 +         y="327.9104"
  89.195 +         x="40.113693"
  89.196 +         height="44.537449"
  89.197 +         width="134.53746"
  89.198 +         id="rect6004"
  89.199 +         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" />
  89.200 +      <text
  89.201 +         id="text6006"
  89.202 +         y="353.67111"
  89.203 +         x="62.654205"
  89.204 +         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"
  89.205 +         xml:space="preserve"><tspan
  89.206 +           style="font-family:Courier"
  89.207 +           y="353.67111"
  89.208 +           x="62.654205"
  89.209 +           id="tspan6008"
  89.210 +           sodipodi:role="line">7b064d8bac5e</tspan></text>
  89.211 +    </g>
  89.212 +    <path
  89.213 +       inkscape:connector-type="polyline"
  89.214 +       id="path6020"
  89.215 +       d="M 160.92915,311.15532 L 167.83571,327.53627"
  89.216 +       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"
  89.217 +       inkscape:connection-end="#g6976"
  89.218 +       inkscape:connection-start="#g1935" />
  89.219 +    <rect
  89.220 +       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"
  89.221 +       id="rect6039"
  89.222 +       width="134.53746"
  89.223 +       height="44.537449"
  89.224 +       x="110.11359"
  89.225 +       y="389.57703" />
  89.226 +    <text
  89.227 +       xml:space="preserve"
  89.228 +       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"
  89.229 +       x="134.79706"
  89.230 +       y="415.33771"
  89.231 +       id="text6041"><tspan
  89.232 +         sodipodi:role="line"
  89.233 +         id="tspan6043"
  89.234 +         x="134.79706"
  89.235 +         y="415.33771"
  89.236 +         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
  89.237 +    <path
  89.238 +       inkscape:connection-end="#rect6039"
  89.239 +       inkscape:connector-type="polyline"
  89.240 +       id="path6045"
  89.241 +       d="M 177.38238,372.82195 L 177.38235,389.20303"
  89.242 +       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" />
  89.243 +    <rect
  89.244 +       y="245.94225"
  89.245 +       x="447.28412"
  89.246 +       height="204.51619"
  89.247 +       width="174.36833"
  89.248 +       id="rect6140"
  89.249 +       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" />
  89.250 +    <g
  89.251 +       id="g6130"
  89.252 +       transform="translate(152.3254,24.38544)">
  89.253 +      <rect
  89.254 +         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"
  89.255 +         id="rect6106"
  89.256 +         width="134.53746"
  89.257 +         height="44.537449"
  89.258 +         x="314.87415"
  89.259 +         y="257.95059" />
  89.260 +      <text
  89.261 +         xml:space="preserve"
  89.262 +         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"
  89.263 +         x="339.55664"
  89.264 +         y="283.7113"
  89.265 +         id="text6108"><tspan
  89.266 +           sodipodi:role="line"
  89.267 +           id="tspan6110"
  89.268 +           x="339.55664"
  89.269 +           y="283.7113"
  89.270 +           style="font-family:Courier">ffb20e1701ea</tspan></text>
  89.271 +    </g>
  89.272 +    <g
  89.273 +       id="g6135"
  89.274 +       transform="translate(153.0396,49.83106)">
  89.275 +      <rect
  89.276 +         inkscape:transform-center-y="102.85714"
  89.277 +         inkscape:transform-center-x="129.28571"
  89.278 +         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"
  89.279 +         id="rect6112"
  89.280 +         width="134.53746"
  89.281 +         height="44.537449"
  89.282 +         x="314.15985"
  89.283 +         y="326.52203" />
  89.284 +      <text
  89.285 +         inkscape:transform-center-y="102.7311"
  89.286 +         inkscape:transform-center-x="128.69672"
  89.287 +         xml:space="preserve"
  89.288 +         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"
  89.289 +         x="338.84335"
  89.290 +         y="352.28271"
  89.291 +         id="text6114"><tspan
  89.292 +           sodipodi:role="line"
  89.293 +           id="tspan6116"
  89.294 +           x="338.84335"
  89.295 +           y="352.28271"
  89.296 +           style="fill:black;fill-opacity:1;font-family:Courier">e7639888bb2f</tspan></text>
  89.297 +    </g>
  89.298 +    <text
  89.299 +       xml:space="preserve"
  89.300 +       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"
  89.301 +       x="466.63208"
  89.302 +       y="270.479"
  89.303 +       id="text6118"><tspan
  89.304 +         sodipodi:role="line"
  89.305 +         id="tspan6120"
  89.306 +         x="466.63208"
  89.307 +         y="270.479">First parent (unchanged)</tspan></text>
  89.308 +    <text
  89.309 +       xml:space="preserve"
  89.310 +       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"
  89.311 +       x="466.07544"
  89.312 +       y="364.49615"
  89.313 +       id="text6122"><tspan
  89.314 +         sodipodi:role="line"
  89.315 +         id="tspan6124"
  89.316 +         x="466.07544"
  89.317 +         y="364.49615">Second parent</tspan></text>
  89.318 +    <text
  89.319 +       xml:space="preserve"
  89.320 +       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"
  89.321 +       x="446.61743"
  89.322 +       y="231.36218"
  89.323 +       id="text6195"><tspan
  89.324 +         sodipodi:role="line"
  89.325 +         id="tspan6197"
  89.326 +         x="446.61743"
  89.327 +         y="231.36218">Parents of working directory</tspan></text>
  89.328 +    <path
  89.329 +       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"
  89.330 +       d="M 466.82542,300.21999 L 377.00207,294.39744"
  89.331 +       id="path6266"
  89.332 +       inkscape:connector-type="polyline"
  89.333 +       inkscape:connection-start="#g6130"
  89.334 +       inkscape:connection-end="#rect1925" />
  89.335 +    <path
  89.336 +       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
  89.337 +       d="M 665.12232,418.17579 L 665.12232,418.17579"
  89.338 +       id="path6270"
  89.339 +       inkscape:connector-type="polyline" />
  89.340 +    <g
  89.341 +       id="g2845">
  89.342 +      <rect
  89.343 +         y="266.24374"
  89.344 +         x="242.09048"
  89.345 +         height="44.537449"
  89.346 +         width="134.53746"
  89.347 +         id="rect1925"
  89.348 +         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" />
  89.349 +      <text
  89.350 +         id="text1927"
  89.351 +         y="292.00446"
  89.352 +         x="266.77298"
  89.353 +         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"
  89.354 +         xml:space="preserve"><tspan
  89.355 +           style="font-family:Courier"
  89.356 +           y="292.00446"
  89.357 +           x="266.77298"
  89.358 +           id="tspan1929"
  89.359 +           sodipodi:role="line">ffb20e1701ea</tspan></text>
  89.360 +    </g>
  89.361 +    <path
  89.362 +       inkscape:connector-type="polyline"
  89.363 +       id="path1933"
  89.364 +       d="M 260.89978,311.15532 L 225.84185,327.53627"
  89.365 +       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"
  89.366 +       inkscape:connection-end="#g6976" />
  89.367 +    <text
  89.368 +       xml:space="preserve"
  89.369 +       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"
  89.370 +       x="109.45568"
  89.371 +       y="231.4554"
  89.372 +       id="text2837"><tspan
  89.373 +         sodipodi:role="line"
  89.374 +         id="tspan2839"
  89.375 +         x="109.45568"
  89.376 +         y="231.4554">Pre-existing head</tspan></text>
  89.377 +    <text
  89.378 +       xml:space="preserve"
  89.379 +       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"
  89.380 +       x="237.54184"
  89.381 +       y="231.4554"
  89.382 +       id="text2841"><tspan
  89.383 +         sodipodi:role="line"
  89.384 +         id="tspan2843"
  89.385 +         x="237.54184"
  89.386 +         y="231.4554">Newly created head (and tip)</tspan></text>
  89.387 +    <path
  89.388 +       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)"
  89.389 +       d="M 148.05048,235.87482 L 149.94915,265.86962"
  89.390 +       id="path2850"
  89.391 +       inkscape:connector-type="polyline"
  89.392 +       inkscape:connection-end="#g1935" />
  89.393 +    <path
  89.394 +       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)"
  89.395 +       d="M 303.83495,238.08453 L 306.87874,265.86962"
  89.396 +       id="path2852"
  89.397 +       inkscape:connector-type="polyline"
  89.398 +       inkscape:connection-end="#g2845" />
  89.399 +    <path
  89.400 +       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"
  89.401 +       d="M 466.82545,379.17944 L 219.0253,307.95488"
  89.402 +       id="path3016"
  89.403 +       inkscape:connector-type="polyline"
  89.404 +       inkscape:connection-start="#g6135"
  89.405 +       inkscape:connection-end="#g1935" />
  89.406 +    <g
  89.407 +       id="g1935">
  89.408 +      <rect
  89.409 +         y="266.24374"
  89.410 +         x="84.113708"
  89.411 +         height="44.537449"
  89.412 +         width="134.53746"
  89.413 +         id="rect5996"
  89.414 +         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" />
  89.415 +      <text
  89.416 +         id="text5998"
  89.417 +         y="292.00446"
  89.418 +         x="108.7962"
  89.419 +         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"
  89.420 +         xml:space="preserve"><tspan
  89.421 +           style="font-family:Courier"
  89.422 +           y="292.00446"
  89.423 +           x="108.7962"
  89.424 +           id="tspan6000"
  89.425 +           sodipodi:role="line">e7639888bb2f</tspan></text>
  89.426 +    </g>
  89.427 +  </g>
  89.428 +</svg>
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/fr/wdir-pre-branch.svg	Thu Feb 05 12:37:03 2009 +0100
    90.3 @@ -0,0 +1,364 @@
    90.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    90.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    90.6 +<svg
    90.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    90.8 +   xmlns:cc="http://web.resource.org/cc/"
    90.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   90.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   90.11 +   xmlns="http://www.w3.org/2000/svg"
   90.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
   90.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   90.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   90.15 +   width="744.09448819"
   90.16 +   height="1052.3622047"
   90.17 +   id="svg5971"
   90.18 +   sodipodi:version="0.32"
   90.19 +   inkscape:version="0.44.1"
   90.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
   90.21 +   sodipodi:docname="wdir-branch.svg">
   90.22 +  <defs
   90.23 +     id="defs5973">
   90.24 +    <marker
   90.25 +       inkscape:stockid="Arrow1Mstart"
   90.26 +       orient="auto"
   90.27 +       refY="0.0"
   90.28 +       refX="0.0"
   90.29 +       id="Arrow1Mstart"
   90.30 +       style="overflow:visible">
   90.31 +      <path
   90.32 +         id="path4855"
   90.33 +         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 "
   90.34 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   90.35 +         transform="scale(0.4) translate(10,0)" />
   90.36 +    </marker>
   90.37 +    <linearGradient
   90.38 +       id="linearGradient6049">
   90.39 +      <stop
   90.40 +         style="stop-color:#686868;stop-opacity:1;"
   90.41 +         offset="0"
   90.42 +         id="stop6051" />
   90.43 +      <stop
   90.44 +         style="stop-color:#f0f0f0;stop-opacity:1;"
   90.45 +         offset="1"
   90.46 +         id="stop6053" />
   90.47 +    </linearGradient>
   90.48 +    <marker
   90.49 +       inkscape:stockid="Arrow1Mend"
   90.50 +       orient="auto"
   90.51 +       refY="0.0"
   90.52 +       refX="0.0"
   90.53 +       id="Arrow1Mend"
   90.54 +       style="overflow:visible;">
   90.55 +      <path
   90.56 +         id="path4852"
   90.57 +         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 "
   90.58 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   90.59 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   90.60 +    </marker>
   90.61 +    <linearGradient
   90.62 +       inkscape:collect="always"
   90.63 +       xlink:href="#linearGradient6049"
   90.64 +       id="linearGradient6083"
   90.65 +       gradientUnits="userSpaceOnUse"
   90.66 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
   90.67 +       x1="333.91171"
   90.68 +       y1="488.79077"
   90.69 +       x2="508.94543"
   90.70 +       y2="263.79077" />
   90.71 +    <linearGradient
   90.72 +       inkscape:collect="always"
   90.73 +       xlink:href="#linearGradient6049"
   90.74 +       id="linearGradient6142"
   90.75 +       gradientUnits="userSpaceOnUse"
   90.76 +       gradientTransform="translate(-42.00893,-30.49544)"
   90.77 +       x1="333.91171"
   90.78 +       y1="488.79077"
   90.79 +       x2="508.94543"
   90.80 +       y2="263.79077" />
   90.81 +    <linearGradient
   90.82 +       inkscape:collect="always"
   90.83 +       xlink:href="#linearGradient6049"
   90.84 +       id="linearGradient6193"
   90.85 +       gradientUnits="userSpaceOnUse"
   90.86 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
   90.87 +       x1="333.91171"
   90.88 +       y1="488.79077"
   90.89 +       x2="508.94543"
   90.90 +       y2="263.79077" />
   90.91 +    <linearGradient
   90.92 +       inkscape:collect="always"
   90.93 +       xlink:href="#linearGradient6049"
   90.94 +       id="linearGradient6216"
   90.95 +       gradientUnits="userSpaceOnUse"
   90.96 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
   90.97 +       x1="333.91171"
   90.98 +       y1="488.79077"
   90.99 +       x2="508.94543"
  90.100 +       y2="263.79077" />
  90.101 +    <linearGradient
  90.102 +       inkscape:collect="always"
  90.103 +       xlink:href="#linearGradient6049"
  90.104 +       id="linearGradient6232"
  90.105 +       gradientUnits="userSpaceOnUse"
  90.106 +       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
  90.107 +       x1="333.91171"
  90.108 +       y1="488.79077"
  90.109 +       x2="508.94543"
  90.110 +       y2="263.79077" />
  90.111 +    <linearGradient
  90.112 +       inkscape:collect="always"
  90.113 +       xlink:href="#linearGradient6049"
  90.114 +       id="linearGradient6445"
  90.115 +       gradientUnits="userSpaceOnUse"
  90.116 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
  90.117 +       x1="333.91171"
  90.118 +       y1="488.79077"
  90.119 +       x2="508.94543"
  90.120 +       y2="263.79077" />
  90.121 +    <linearGradient
  90.122 +       inkscape:collect="always"
  90.123 +       xlink:href="#linearGradient6049"
  90.124 +       id="linearGradient6974"
  90.125 +       gradientUnits="userSpaceOnUse"
  90.126 +       gradientTransform="matrix(1.000474,0,0,0.790947,-314.246,50.85694)"
  90.127 +       x1="333.91171"
  90.128 +       y1="488.79077"
  90.129 +       x2="508.94543"
  90.130 +       y2="263.79077" />
  90.131 +    <linearGradient
  90.132 +       inkscape:collect="always"
  90.133 +       xlink:href="#linearGradient6049"
  90.134 +       id="linearGradient6996"
  90.135 +       gradientUnits="userSpaceOnUse"
  90.136 +       gradientTransform="matrix(1.000473,0,0,0.790947,-85.16012,50.85693)"
  90.137 +       x1="333.91171"
  90.138 +       y1="488.79077"
  90.139 +       x2="508.94543"
  90.140 +       y2="263.79077" />
  90.141 +  </defs>
  90.142 +  <sodipodi:namedview
  90.143 +     id="base"
  90.144 +     pagecolor="#ffffff"
  90.145 +     bordercolor="#666666"
  90.146 +     borderopacity="1.0"
  90.147 +     gridtolerance="10000"
  90.148 +     guidetolerance="10"
  90.149 +     objecttolerance="10"
  90.150 +     inkscape:pageopacity="0.0"
  90.151 +     inkscape:pageshadow="2"
  90.152 +     inkscape:zoom="0.90509668"
  90.153 +     inkscape:cx="390.0539"
  90.154 +     inkscape:cy="690.49342"
  90.155 +     inkscape:document-units="px"
  90.156 +     inkscape:current-layer="layer1"
  90.157 +     showguides="true"
  90.158 +     inkscape:guide-bbox="true"
  90.159 +     inkscape:window-width="906"
  90.160 +     inkscape:window-height="620"
  90.161 +     inkscape:window-x="0"
  90.162 +     inkscape:window-y="25">
  90.163 +    <sodipodi:guide
  90.164 +       orientation="vertical"
  90.165 +       position="-1.4285714"
  90.166 +       id="guide6022" />
  90.167 +  </sodipodi:namedview>
  90.168 +  <metadata
  90.169 +     id="metadata5976">
  90.170 +    <rdf:RDF>
  90.171 +      <cc:Work
  90.172 +         rdf:about="">
  90.173 +        <dc:format>image/svg+xml</dc:format>
  90.174 +        <dc:type
  90.175 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  90.176 +      </cc:Work>
  90.177 +    </rdf:RDF>
  90.178 +  </metadata>
  90.179 +  <g
  90.180 +     inkscape:label="Layer 1"
  90.181 +     inkscape:groupmode="layer"
  90.182 +     id="layer1">
  90.183 +    <rect
  90.184 +       y="245.94225"
  90.185 +       x="20.198257"
  90.186 +       height="204.51619"
  90.187 +       width="174.36833"
  90.188 +       id="rect6047"
  90.189 +       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" />
  90.190 +    <rect
  90.191 +       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"
  90.192 +       id="rect5996"
  90.193 +       width="134.53746"
  90.194 +       height="44.537449"
  90.195 +       x="40.113693"
  90.196 +       y="266.24374" />
  90.197 +    <text
  90.198 +       xml:space="preserve"
  90.199 +       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"
  90.200 +       x="64.796204"
  90.201 +       y="292.00446"
  90.202 +       id="text5998"><tspan
  90.203 +         sodipodi:role="line"
  90.204 +         id="tspan6000"
  90.205 +         x="64.796204"
  90.206 +         y="292.00446"
  90.207 +         style="font-family:Courier">e7639888bb2f</tspan></text>
  90.208 +    <g
  90.209 +       id="g6976">
  90.210 +      <rect
  90.211 +         y="327.9104"
  90.212 +         x="40.113693"
  90.213 +         height="44.537449"
  90.214 +         width="134.53746"
  90.215 +         id="rect6004"
  90.216 +         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" />
  90.217 +      <text
  90.218 +         id="text6006"
  90.219 +         y="353.67111"
  90.220 +         x="62.654205"
  90.221 +         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"
  90.222 +         xml:space="preserve"><tspan
  90.223 +           style="font-family:Courier"
  90.224 +           y="353.67111"
  90.225 +           x="62.654205"
  90.226 +           id="tspan6008"
  90.227 +           sodipodi:role="line">7b064d8bac5e</tspan></text>
  90.228 +    </g>
  90.229 +    <path
  90.230 +       inkscape:connection-end="#rect6004"
  90.231 +       inkscape:connector-type="polyline"
  90.232 +       id="path6020"
  90.233 +       d="M 107.38242,311.15529 L 107.38242,327.53626"
  90.234 +       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" />
  90.235 +    <rect
  90.236 +       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"
  90.237 +       id="rect6039"
  90.238 +       width="134.53746"
  90.239 +       height="44.537449"
  90.240 +       x="40.113571"
  90.241 +       y="389.57703" />
  90.242 +    <text
  90.243 +       xml:space="preserve"
  90.244 +       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"
  90.245 +       x="64.797073"
  90.246 +       y="415.33771"
  90.247 +       id="text6041"><tspan
  90.248 +         sodipodi:role="line"
  90.249 +         id="tspan6043"
  90.250 +         x="64.797073"
  90.251 +         y="415.33771"
  90.252 +         style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
  90.253 +    <path
  90.254 +       inkscape:connection-end="#rect6039"
  90.255 +       inkscape:connector-type="polyline"
  90.256 +       id="path6045"
  90.257 +       d="M 107.38238,372.82195 L 107.38235,389.20301"
  90.258 +       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" />
  90.259 +    <text
  90.260 +       xml:space="preserve"
  90.261 +       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"
  90.262 +       x="19.660461"
  90.263 +       y="231.36218"
  90.264 +       id="text6102"><tspan
  90.265 +         sodipodi:role="line"
  90.266 +         id="tspan6104"
  90.267 +         x="19.660461"
  90.268 +         y="231.36218">History in repository</tspan></text>
  90.269 +    <rect
  90.270 +       y="245.94225"
  90.271 +       x="249.28412"
  90.272 +       height="204.51619"
  90.273 +       width="174.36833"
  90.274 +       id="rect6140"
  90.275 +       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" />
  90.276 +    <g
  90.277 +       id="g6130"
  90.278 +       transform="translate(-45.67459,24.38544)">
  90.279 +      <rect
  90.280 +         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"
  90.281 +         id="rect6106"
  90.282 +         width="134.53746"
  90.283 +         height="44.537449"
  90.284 +         x="314.87415"
  90.285 +         y="257.95059" />
  90.286 +      <text
  90.287 +         xml:space="preserve"
  90.288 +         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"
  90.289 +         x="339.55664"
  90.290 +         y="283.7113"
  90.291 +         id="text6108"><tspan
  90.292 +           sodipodi:role="line"
  90.293 +           id="tspan6110"
  90.294 +           x="339.55664"
  90.295 +           y="283.7113"
  90.296 +           style="font-family:Courier">7b064d8bac5e</tspan></text>
  90.297 +    </g>
  90.298 +    <g
  90.299 +       id="g6135"
  90.300 +       transform="translate(-44.96042,49.83106)">
  90.301 +      <rect
  90.302 +         inkscape:transform-center-y="102.85714"
  90.303 +         inkscape:transform-center-x="129.28571"
  90.304 +         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"
  90.305 +         id="rect6112"
  90.306 +         width="134.53746"
  90.307 +         height="44.537449"
  90.308 +         x="314.15985"
  90.309 +         y="326.52203" />
  90.310 +      <text
  90.311 +         inkscape:transform-center-y="102.7311"
  90.312 +         inkscape:transform-center-x="128.69672"
  90.313 +         xml:space="preserve"
  90.314 +         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"
  90.315 +         x="338.84335"
  90.316 +         y="352.28271"
  90.317 +         id="text6114"><tspan
  90.318 +           sodipodi:role="line"
  90.319 +           id="tspan6116"
  90.320 +           x="338.84335"
  90.321 +           y="352.28271"
  90.322 +           style="fill:#979797;fill-opacity:1;font-family:Courier">000000000000</tspan></text>
  90.323 +    </g>
  90.324 +    <text
  90.325 +       xml:space="preserve"
  90.326 +       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"
  90.327 +       x="268.63208"
  90.328 +       y="270.479"
  90.329 +       id="text6118"><tspan
  90.330 +         sodipodi:role="line"
  90.331 +         id="tspan6120"
  90.332 +         x="268.63208"
  90.333 +         y="270.479">First parent</tspan></text>
  90.334 +    <text
  90.335 +       xml:space="preserve"
  90.336 +       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"
  90.337 +       x="268.07544"
  90.338 +       y="364.49615"
  90.339 +       id="text6122"><tspan
  90.340 +         sodipodi:role="line"
  90.341 +         id="tspan6124"
  90.342 +         x="268.07544"
  90.343 +         y="364.49615">Second parent</tspan></text>
  90.344 +    <text
  90.345 +       xml:space="preserve"
  90.346 +       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"
  90.347 +       x="248.61746"
  90.348 +       y="231.36218"
  90.349 +       id="text6195"><tspan
  90.350 +         sodipodi:role="line"
  90.351 +         id="tspan6197"
  90.352 +         x="248.61746"
  90.353 +         y="231.36218">Parents of working directory</tspan></text>
  90.354 +    <path
  90.355 +       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"
  90.356 +       d="M 268.82543,318.06163 L 175.02528,336.72225"
  90.357 +       id="path6266"
  90.358 +       inkscape:connector-type="polyline"
  90.359 +       inkscape:connection-end="#g6976"
  90.360 +       inkscape:connection-start="#g6130" />
  90.361 +    <path
  90.362 +       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
  90.363 +       d="M 665.12232,418.17579 L 665.12232,418.17579"
  90.364 +       id="path6270"
  90.365 +       inkscape:connector-type="polyline" />
  90.366 +  </g>
  90.367 +</svg>
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/fr/wdir.svg	Thu Feb 05 12:37:03 2009 +0100
    91.3 @@ -0,0 +1,348 @@
    91.4 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    91.5 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
    91.6 +<svg
    91.7 +   xmlns:dc="http://purl.org/dc/elements/1.1/"
    91.8 +   xmlns:cc="http://web.resource.org/cc/"
    91.9 +   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   91.10 +   xmlns:svg="http://www.w3.org/2000/svg"
   91.11 +   xmlns="http://www.w3.org/2000/svg"
   91.12 +   xmlns:xlink="http://www.w3.org/1999/xlink"
   91.13 +   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   91.14 +   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   91.15 +   width="744.09448819"
   91.16 +   height="1052.3622047"
   91.17 +   id="svg5971"
   91.18 +   sodipodi:version="0.32"
   91.19 +   inkscape:version="0.44.1"
   91.20 +   sodipodi:docbase="/home/bos/hg/hgbook/en"
   91.21 +   sodipodi:docname="wdir.svg">
   91.22 +  <defs
   91.23 +     id="defs5973">
   91.24 +    <marker
   91.25 +       inkscape:stockid="Arrow1Mstart"
   91.26 +       orient="auto"
   91.27 +       refY="0.0"
   91.28 +       refX="0.0"
   91.29 +       id="Arrow1Mstart"
   91.30 +       style="overflow:visible">
   91.31 +      <path
   91.32 +         id="path4855"
   91.33 +         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 "
   91.34 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
   91.35 +         transform="scale(0.4) translate(10,0)" />
   91.36 +    </marker>
   91.37 +    <linearGradient
   91.38 +       id="linearGradient6049">
   91.39 +      <stop
   91.40 +         style="stop-color:#686868;stop-opacity:1;"
   91.41 +         offset="0"
   91.42 +         id="stop6051" />
   91.43 +      <stop
   91.44 +         style="stop-color:#f0f0f0;stop-opacity:1;"
   91.45 +         offset="1"
   91.46 +         id="stop6053" />
   91.47 +    </linearGradient>
   91.48 +    <marker
   91.49 +       inkscape:stockid="Arrow1Mend"
   91.50 +       orient="auto"
   91.51 +       refY="0.0"
   91.52 +       refX="0.0"
   91.53 +       id="Arrow1Mend"
   91.54 +       style="overflow:visible;">
   91.55 +      <path
   91.56 +         id="path4852"
   91.57 +         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 "
   91.58 +         style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
   91.59 +         transform="scale(0.4) rotate(180) translate(10,0)" />
   91.60 +    </marker>
   91.61 +    <linearGradient
   91.62 +       inkscape:collect="always"
   91.63 +       xlink:href="#linearGradient6049"
   91.64 +       id="linearGradient6083"
   91.65 +       gradientUnits="userSpaceOnUse"
   91.66 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
   91.67 +       x1="333.91171"
   91.68 +       y1="488.79077"
   91.69 +       x2="508.94543"
   91.70 +       y2="263.79077" />
   91.71 +    <linearGradient
   91.72 +       inkscape:collect="always"
   91.73 +       xlink:href="#linearGradient6049"
   91.74 +       id="linearGradient6142"
   91.75 +       gradientUnits="userSpaceOnUse"
   91.76 +       gradientTransform="translate(-42.00893,-30.49544)"
   91.77 +       x1="333.91171"
   91.78 +       y1="488.79077"
   91.79 +       x2="508.94543"
   91.80 +       y2="263.79077" />
   91.81 +    <linearGradient
   91.82 +       inkscape:collect="always"
   91.83 +       xlink:href="#linearGradient6049"
   91.84 +       id="linearGradient6193"
   91.85 +       gradientUnits="userSpaceOnUse"
   91.86 +       gradientTransform="translate(-240.0462,-8.633237e-6)"
   91.87 +       x1="333.91171"
   91.88 +       y1="488.79077"
   91.89 +       x2="508.94543"
   91.90 +       y2="263.79077" />
   91.91 +    <linearGradient
   91.92 +       inkscape:collect="always"
   91.93 +       xlink:href="#linearGradient6049"
   91.94 +       id="linearGradient6216"
   91.95 +       gradientUnits="userSpaceOnUse"
   91.96 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
   91.97 +       x1="333.91171"
   91.98 +       y1="488.79077"
   91.99 +       x2="508.94543"
  91.100 +       y2="263.79077" />
  91.101 +    <linearGradient
  91.102 +       inkscape:collect="always"
  91.103 +       xlink:href="#linearGradient6049"
  91.104 +       id="linearGradient6232"
  91.105 +       gradientUnits="userSpaceOnUse"
  91.106 +       gradientTransform="matrix(1.000473,0,0,0.790947,-11.16012,50.85693)"
  91.107 +       x1="333.91171"
  91.108 +       y1="488.79077"
  91.109 +       x2="508.94543"
  91.110 +       y2="263.79077" />
  91.111 +    <linearGradient
  91.112 +       inkscape:collect="always"
  91.113 +       xlink:href="#linearGradient6049"
  91.114 +       id="linearGradient6445"
  91.115 +       gradientUnits="userSpaceOnUse"
  91.116 +       gradientTransform="matrix(1.000474,0,0,0.790947,-240.246,50.9948)"
  91.117 +       x1="333.91171"
  91.118 +       y1="488.79077"
  91.119 +       x2="508.94543"
  91.120 +       y2="263.79077" />
  91.121 +  </defs>
  91.122 +  <sodipodi:namedview
  91.123 +     id="base"
  91.124 +     pagecolor="#ffffff"
  91.125 +     bordercolor="#666666"
  91.126 +     borderopacity="1.0"
  91.127 +     gridtolerance="10000"
  91.128 +     guidetolerance="10"
  91.129 +     objecttolerance="10"
  91.130 +     inkscape:pageopacity="0.0"
  91.131 +     inkscape:pageshadow="2"
  91.132 +     inkscape:zoom="0.90509668"
  91.133 +     inkscape:cx="390.0539"
  91.134 +     inkscape:cy="690.49342"
  91.135 +     inkscape:document-units="px"
  91.136 +     inkscape:current-layer="layer1"
  91.137 +     showguides="true"
  91.138 +     inkscape:guide-bbox="true"
  91.139 +     inkscape:window-width="906"
  91.140 +     inkscape:window-height="620"
  91.141 +     inkscape:window-x="0"
  91.142 +     inkscape:window-y="25">
  91.143 +    <sodipodi:guide
  91.144 +       orientation="vertical"
  91.145 +       position="-1.4285714"
  91.146 +       id="guide6022" />
  91.147 +  </sodipodi:namedview>
  91.148 +  <metadata
  91.149 +     id="metadata5976">
  91.150 +    <rdf:RDF>
  91.151 +      <cc:Work
  91.152 +         rdf:about="">
  91.153 +        <dc:format>image/svg+xml</dc:format>
  91.154 +        <dc:type
  91.155 +           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  91.156 +      </cc:Work>
  91.157 +    </rdf:RDF>
  91.158 +  </metadata>
  91.159 +  <g
  91.160 +     inkscape:label="Layer 1"
  91.161 +     inkscape:groupmode="layer"
  91.162 +     id="layer1">
  91.163 +    <g
  91.164 +       id="g6431"
  91.165 +       transform="translate(0,-0.137863)">
  91.166 +      <rect
  91.167 +         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"
  91.168 +         id="rect6047"
  91.169 +         width="174.36833"
  91.170 +         height="204.51619"
  91.171 +         x="94.198257"
  91.172 +         y="246.08011" />
  91.173 +      <rect
  91.174 +         y="266.38159"
  91.175 +         x="114.11369"
  91.176 +         height="44.537449"
  91.177 +         width="134.53746"
  91.178 +         id="rect5996"
  91.179 +         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" />
  91.180 +      <text
  91.181 +         id="text5998"
  91.182 +         y="292.1423"
  91.183 +         x="138.7962"
  91.184 +         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"
  91.185 +         xml:space="preserve"><tspan
  91.186 +           style="font-family:Courier"
  91.187 +           y="292.1423"
  91.188 +           x="138.7962"
  91.189 +           id="tspan6000"
  91.190 +           sodipodi:role="line">e7639888bb2f</tspan></text>
  91.191 +      <rect
  91.192 +         y="328.04825"
  91.193 +         x="114.11369"
  91.194 +         height="44.537449"
  91.195 +         width="134.53746"
  91.196 +         id="rect6004"
  91.197 +         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" />
  91.198 +      <text
  91.199 +         id="text6006"
  91.200 +         y="353.80896"
  91.201 +         x="136.65421"
  91.202 +         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"
  91.203 +         xml:space="preserve"><tspan
  91.204 +           style="font-family:Courier"
  91.205 +           y="353.80896"
  91.206 +           x="136.65421"
  91.207 +           id="tspan6008"
  91.208 +           sodipodi:role="line">7b064d8bac5e</tspan></text>
  91.209 +      <path
  91.210 +         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"
  91.211 +         d="M 181.38242,311.29315 L 181.38242,327.67412"
  91.212 +         id="path6020"
  91.213 +         inkscape:connector-type="polyline"
  91.214 +         inkscape:connection-end="#rect6004" />
  91.215 +      <rect
  91.216 +         y="389.71487"
  91.217 +         x="114.11357"
  91.218 +         height="44.537449"
  91.219 +         width="134.53746"
  91.220 +         id="rect6039"
  91.221 +         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" />
  91.222 +      <text
  91.223 +         id="text6041"
  91.224 +         y="415.47556"
  91.225 +         x="138.79707"
  91.226 +         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"
  91.227 +         xml:space="preserve"><tspan
  91.228 +           style="fill:#979797;fill-opacity:1;font-family:Courier"
  91.229 +           y="415.47556"
  91.230 +           x="138.79707"
  91.231 +           id="tspan6043"
  91.232 +           sodipodi:role="line">000000000000</tspan></text>
  91.233 +      <path
  91.234 +         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"
  91.235 +         d="M 181.38238,372.95981 L 181.38235,389.34087"
  91.236 +         id="path6045"
  91.237 +         inkscape:connector-type="polyline"
  91.238 +         inkscape:connection-end="#rect6039" />
  91.239 +    </g>
  91.240 +    <text
  91.241 +       xml:space="preserve"
  91.242 +       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"
  91.243 +       x="93.660484"
  91.244 +       y="231.36218"
  91.245 +       id="text6102"><tspan
  91.246 +         sodipodi:role="line"
  91.247 +         id="tspan6104"
  91.248 +         x="93.660484"
  91.249 +         y="231.36218">History in repository</tspan></text>
  91.250 +    <g
  91.251 +       id="g6416">
  91.252 +      <rect
  91.253 +         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"
  91.254 +         id="rect6140"
  91.255 +         width="174.36833"
  91.256 +         height="204.51619"
  91.257 +         x="323.28412"
  91.258 +         y="245.94225" />
  91.259 +      <g
  91.260 +         transform="translate(28.32541,24.38544)"
  91.261 +         id="g6130">
  91.262 +        <rect
  91.263 +           y="257.95059"
  91.264 +           x="314.87415"
  91.265 +           height="44.537449"
  91.266 +           width="134.53746"
  91.267 +           id="rect6106"
  91.268 +           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" />
  91.269 +        <text
  91.270 +           id="text6108"
  91.271 +           y="283.7113"
  91.272 +           x="339.55664"
  91.273 +           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"
  91.274 +           xml:space="preserve"><tspan
  91.275 +             style="font-family:Courier"
  91.276 +             y="283.7113"
  91.277 +             x="339.55664"
  91.278 +             id="tspan6110"
  91.279 +             sodipodi:role="line">e7639888bb2f</tspan></text>
  91.280 +      </g>
  91.281 +      <g
  91.282 +         transform="translate(29.03958,49.83106)"
  91.283 +         id="g6135">
  91.284 +        <rect
  91.285 +           y="326.52203"
  91.286 +           x="314.15985"
  91.287 +           height="44.537449"
  91.288 +           width="134.53746"
  91.289 +           id="rect6112"
  91.290 +           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"
  91.291 +           inkscape:transform-center-x="129.28571"
  91.292 +           inkscape:transform-center-y="102.85714" />
  91.293 +        <text
  91.294 +           id="text6114"
  91.295 +           y="352.28271"
  91.296 +           x="338.84335"
  91.297 +           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"
  91.298 +           xml:space="preserve"
  91.299 +           inkscape:transform-center-x="128.69672"
  91.300 +           inkscape:transform-center-y="102.7311"><tspan
  91.301 +             style="fill:#979797;fill-opacity:1;font-family:Courier"
  91.302 +             y="352.28271"
  91.303 +             x="338.84335"
  91.304 +             id="tspan6116"
  91.305 +             sodipodi:role="line">000000000000</tspan></text>
  91.306 +      </g>
  91.307 +      <text
  91.308 +         id="text6118"
  91.309 +         y="270.479"
  91.310 +         x="342.63208"
  91.311 +         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"
  91.312 +         xml:space="preserve"><tspan
  91.313 +           y="270.479"
  91.314 +           x="342.63208"
  91.315 +           id="tspan6120"
  91.316 +           sodipodi:role="line">First parent</tspan></text>
  91.317 +      <text
  91.318 +         id="text6122"
  91.319 +         y="364.49615"
  91.320 +         x="342.07544"
  91.321 +         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"
  91.322 +         xml:space="preserve"><tspan
  91.323 +           y="364.49615"
  91.324 +           x="342.07544"
  91.325 +           id="tspan6124"
  91.326 +           sodipodi:role="line">Second parent</tspan></text>
  91.327 +    </g>
  91.328 +    <text
  91.329 +       xml:space="preserve"
  91.330 +       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"
  91.331 +       x="322.61746"
  91.332 +       y="231.36218"
  91.333 +       id="text6195"><tspan
  91.334 +         sodipodi:role="line"
  91.335 +         id="tspan6197"
  91.336 +         x="322.61746"
  91.337 +         y="231.36218">Parents of working directory</tspan></text>
  91.338 +    <path
  91.339 +       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"
  91.340 +       d="M 342.82543,299.89384 L 249.02528,293.36123"
  91.341 +       id="path6266"
  91.342 +       inkscape:connector-type="polyline"
  91.343 +       inkscape:connection-start="#g6130"
  91.344 +       inkscape:connection-end="#rect5996" />
  91.345 +    <path
  91.346 +       style="fill:none;fill-opacity:0.75;fill-rule:evenodd;stroke:black;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
  91.347 +       d="M 665.12232,418.17579 L 665.12232,418.17579"
  91.348 +       id="path6270"
  91.349 +       inkscape:connector-type="polyline" />
  91.350 +  </g>
  91.351 +</svg>